[project] Generate syscalls from new interface DSL
This change adds a new interface DSL for specifying objects (with methods) and interfaces (that expose objects, and optionally have their own methods). Significant changes: - Add the new scripts/definitions Python module to parse the DSL - Add the new definitions directory containing DSL definition files - Use cog to generate syscall-related code in kernel and libj6 - Unify ordering of pointer + length pairs in interfaces
This commit is contained in:
@@ -14,7 +14,6 @@ kernel = module("kernel",
|
||||
"clock.cpp",
|
||||
"console.cpp",
|
||||
"cpprt.cpp",
|
||||
"cpu.cpp",
|
||||
"debug.cpp",
|
||||
"debug.s",
|
||||
"device_manager.cpp",
|
||||
@@ -27,7 +26,6 @@ kernel = module("kernel",
|
||||
"interrupts.s",
|
||||
"io.cpp",
|
||||
"log.cpp",
|
||||
"main.cpp",
|
||||
"memory_bootstrap.cpp",
|
||||
"msr.cpp",
|
||||
"objects/channel.cpp",
|
||||
@@ -42,8 +40,6 @@ kernel = module("kernel",
|
||||
"pci.cpp",
|
||||
"scheduler.cpp",
|
||||
"serial.cpp",
|
||||
"syscall.cpp",
|
||||
"syscall.s",
|
||||
"syscalls/channel.cpp",
|
||||
"syscalls/endpoint.cpp",
|
||||
"syscalls/object.cpp",
|
||||
@@ -56,4 +52,15 @@ kernel = module("kernel",
|
||||
"vm_space.cpp",
|
||||
])
|
||||
|
||||
from glob import glob
|
||||
definitions = glob('definitions/**/*.def', recursive=True)
|
||||
sysinc = kernel.add_input("syscalls.inc.cog", deps=definitions)
|
||||
kernel.add_input("syscall.s", deps=[sysinc])
|
||||
|
||||
sysh = kernel.add_input("syscall.h.cog", deps=definitions)
|
||||
sysc = kernel.add_input("syscall.cpp.cog", deps=definitions + [sysh])
|
||||
|
||||
kernel.add_input("main.cpp", deps=[sysh])
|
||||
kernel.add_input("cpu.cpp", deps=[sysh])
|
||||
|
||||
kernel.variables['ldflags'] = ["${ldflags}", "-T", "${source_root}/src/kernel/kernel.ld"]
|
||||
|
||||
@@ -28,10 +28,10 @@ endpoint::close()
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
endpoint::send(j6_tag_t tag, size_t len, void *data)
|
||||
endpoint::send(j6_tag_t tag, const void *data, size_t data_len)
|
||||
{
|
||||
thread_data sender = { &thread::current(), data };
|
||||
sender.len = len;
|
||||
sender.len = data_len;
|
||||
sender.tag = tag;
|
||||
|
||||
if (!check_signal(j6_signal_endpoint_can_send)) {
|
||||
@@ -55,11 +55,11 @@ endpoint::send(j6_tag_t tag, size_t len, void *data)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
endpoint::receive(j6_tag_t *tag, size_t *len, void *data)
|
||||
endpoint::receive(j6_tag_t *tag, void *data, size_t *data_len)
|
||||
{
|
||||
thread_data receiver = { &thread::current(), data };
|
||||
receiver.tag_p = tag;
|
||||
receiver.len_p = len;
|
||||
receiver.len_p = data_len;
|
||||
|
||||
if (!check_signal(j6_signal_endpoint_can_recv)) {
|
||||
assert_signal(j6_signal_endpoint_can_send);
|
||||
@@ -120,7 +120,7 @@ endpoint::do_message_copy(const endpoint::thread_data &sender, endpoint::thread_
|
||||
if (sender.len) {
|
||||
vm_space &source = sender.th->parent().space();
|
||||
vm_space &dest = receiver.th->parent().space();
|
||||
vm_space::copy(source, dest, sender.data, receiver.data, sender.len);
|
||||
vm_space::copy(source, dest, sender.data, receiver.buffer, sender.len);
|
||||
}
|
||||
|
||||
*receiver.len_p = sender.len;
|
||||
|
||||
@@ -27,10 +27,10 @@ public:
|
||||
/// Send a message to a thread waiting to receive on this endpoint. If no threads
|
||||
/// are currently trying to receive, block the current thread.
|
||||
/// \arg tag The application-specified message tag
|
||||
/// \arg len The size in bytes of the message
|
||||
/// \arg data The message data
|
||||
/// \arg len The size in bytes of the message
|
||||
/// \returns j6_status_ok on success
|
||||
j6_status_t send(j6_tag_t tag, size_t len, void *data);
|
||||
j6_status_t send(j6_tag_t tag, const void *data, size_t data_len);
|
||||
|
||||
/// Receive a message from a thread waiting to send on this endpoint. If no threads
|
||||
/// are currently trying to send, block the current thread.
|
||||
@@ -38,7 +38,7 @@ public:
|
||||
/// \arg len [in] The size in bytes of the buffer [out] Number of bytes in the message
|
||||
/// \arg data Buffer for copying message data into
|
||||
/// \returns j6_status_ok on success
|
||||
j6_status_t receive(j6_tag_t *tag, size_t *len, void *data);
|
||||
j6_status_t receive(j6_tag_t *tag, void *data, size_t *data_len);
|
||||
|
||||
/// Give the listener on the endpoint a message that a bound IRQ has been signalled
|
||||
/// \arg irq The IRQ that caused this signal
|
||||
@@ -48,7 +48,10 @@ private:
|
||||
struct thread_data
|
||||
{
|
||||
thread *th;
|
||||
void *data;
|
||||
union {
|
||||
const void *data;
|
||||
void *buffer;
|
||||
};
|
||||
union {
|
||||
j6_tag_t *tag_p;
|
||||
j6_tag_t tag;
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
#include <stddef.h>
|
||||
|
||||
#include "kutil/memory.h"
|
||||
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "log.h"
|
||||
#include "syscall.h"
|
||||
|
||||
extern "C" {
|
||||
void syscall_invalid(uint64_t call);
|
||||
}
|
||||
|
||||
uintptr_t syscall_registry[256] __attribute__((section(".syscall_registry")));
|
||||
const char * syscall_names[256] __attribute__((section(".syscall_registry")));
|
||||
static constexpr size_t num_syscalls = sizeof(syscall_registry) / sizeof(syscall_registry[0]);
|
||||
|
||||
void
|
||||
syscall_invalid(uint64_t call)
|
||||
{
|
||||
console *cons = console::get();
|
||||
cons->set_color(9);
|
||||
cons->printf("\nReceived unknown syscall: %02x\n", call);
|
||||
|
||||
cons->printf(" Known syscalls:\n");
|
||||
cons->printf(" invalid %016lx\n", syscall_invalid);
|
||||
|
||||
for (unsigned i = 0; i < num_syscalls; ++i) {
|
||||
const char *name = syscall_names[i];
|
||||
uintptr_t handler = syscall_registry[i];
|
||||
if (name)
|
||||
cons->printf(" %02x %10s %016lx\n", i, name, handler);
|
||||
}
|
||||
|
||||
cons->set_color();
|
||||
_halt();
|
||||
}
|
||||
|
||||
void
|
||||
syscall_initialize()
|
||||
{
|
||||
kutil::memset(&syscall_registry, 0, sizeof(syscall_registry));
|
||||
kutil::memset(&syscall_names, 0, sizeof(syscall_names));
|
||||
|
||||
#define SYSCALL(id, name, result, ...) \
|
||||
syscall_registry[id] = reinterpret_cast<uintptr_t>(syscalls::name); \
|
||||
syscall_names[id] = #name; \
|
||||
log::debug(logs::syscall, "Enabling syscall 0x%02x as " #name , id);
|
||||
#include "j6/tables/syscalls.inc"
|
||||
#undef SYSCALL
|
||||
}
|
||||
|
||||
56
src/kernel/syscall.cpp.cog
Normal file
56
src/kernel/syscall.cpp.cog
Normal file
@@ -0,0 +1,56 @@
|
||||
// vim: ft=cpp
|
||||
#include <stddef.h>
|
||||
|
||||
#include "kutil/memory.h"
|
||||
|
||||
#include "console.h"
|
||||
#include "debug.h"
|
||||
#include "log.h"
|
||||
#include "syscall.h"
|
||||
|
||||
extern "C" {
|
||||
void syscall_invalid(uint64_t call);
|
||||
}
|
||||
|
||||
/*[[[cog code generation
|
||||
from definitions.context import Context
|
||||
|
||||
ctx = Context(definitions_path)
|
||||
ctx.parse("syscalls.def")
|
||||
syscalls = ctx.interfaces['syscalls']
|
||||
|
||||
cog.outl(f"constexpr size_t num_syscalls = {len(syscalls.methods)};")
|
||||
]]]*/
|
||||
/// [[[end]]]
|
||||
uintptr_t syscall_registry[num_syscalls] __attribute__((section(".syscall_registry")));
|
||||
|
||||
void
|
||||
syscall_invalid(uint64_t call)
|
||||
{
|
||||
console *cons = console::get();
|
||||
cons->set_color(9);
|
||||
cons->printf("\nReceived unknown syscall: %02x\n", call);
|
||||
|
||||
cons->set_color();
|
||||
_halt();
|
||||
}
|
||||
|
||||
void
|
||||
syscall_initialize()
|
||||
{
|
||||
kutil::memset(&syscall_registry, 0, sizeof(syscall_registry));
|
||||
|
||||
/*[[[cog code generation
|
||||
for id, scope, method in syscalls.methods:
|
||||
if scope:
|
||||
name = f"{scope.name}_{method.name}"
|
||||
else:
|
||||
name = method.name
|
||||
|
||||
cog.outl(f"syscall_registry[{id}] = reinterpret_cast<uintptr_t>(syscalls::{name});")
|
||||
cog.outl(f"""log::debug(logs::syscall, "Enabling syscall {id:x} as {name}");""")
|
||||
cog.outl("")
|
||||
]]]*/
|
||||
//[[[end]]]
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "j6/types.h"
|
||||
|
||||
struct cpu_state;
|
||||
|
||||
enum class syscall : uint64_t
|
||||
{
|
||||
#define SYSCALL(id, name, ...) name = id,
|
||||
#include "j6/tables/syscalls.inc"
|
||||
#undef SYSCALL
|
||||
};
|
||||
|
||||
void syscall_initialize();
|
||||
extern "C" void syscall_enable();
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
#define SYSCALL(id, name, ...) j6_status_t name (__VA_ARGS__);
|
||||
#include "j6/tables/syscalls.inc"
|
||||
#undef SYSCALL
|
||||
}
|
||||
60
src/kernel/syscall.h.cog
Normal file
60
src/kernel/syscall.h.cog
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
// vim: ft=cpp
|
||||
|
||||
#include <stdint.h>
|
||||
#include "j6/types.h"
|
||||
|
||||
struct cpu_state;
|
||||
|
||||
/*[[[cog code generation
|
||||
from definitions.context import Context
|
||||
|
||||
ctx = Context(definitions_path)
|
||||
ctx.parse("syscalls.def")
|
||||
syscalls = ctx.interfaces["syscalls"]
|
||||
|
||||
]]]*/
|
||||
/// [[[end]]]
|
||||
|
||||
enum class syscall : uint64_t
|
||||
{
|
||||
/*[[[cog code generation
|
||||
|
||||
for id, scope, method in syscalls.methods:
|
||||
if scope:
|
||||
name = f"{scope.name}_{method.name}"
|
||||
else:
|
||||
name = method.name
|
||||
cog.outl(f"{name:20} = {id},")
|
||||
|
||||
]]]*/
|
||||
//[[[end]]]
|
||||
};
|
||||
|
||||
void syscall_initialize();
|
||||
extern "C" void syscall_enable();
|
||||
|
||||
namespace syscalls
|
||||
{
|
||||
/*[[[cog code generation
|
||||
|
||||
for id, scope, method in syscalls.methods:
|
||||
if scope:
|
||||
name = f"{scope.name}_{method.name}"
|
||||
else:
|
||||
name = method.name
|
||||
|
||||
args = []
|
||||
if method.constructor:
|
||||
args.append("j6_handle_t *handle")
|
||||
elif not method.static:
|
||||
args.append("j6_handle_t handle")
|
||||
|
||||
for param in method.params:
|
||||
for type, suffix in param.type.c_names(param.options):
|
||||
args.append(f"{type} {param.name}{suffix}")
|
||||
|
||||
cog.outl(f"""j6_status_t {name} ({", ".join(args)});""")
|
||||
]]]*/
|
||||
//[[[end]]]
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
%include "tasking.inc"
|
||||
%include "syscalls.inc"
|
||||
|
||||
; SYSCALL/SYSRET control MSRs
|
||||
MSR_STAR equ 0xc0000081
|
||||
@@ -51,7 +52,9 @@ syscall_handler_prelude:
|
||||
|
||||
inc qword [rel __counter_syscall_enter]
|
||||
|
||||
and rax, 0xff ; Only 256 possible syscall values
|
||||
cmp rax, NUM_SYSCALLS
|
||||
jge .bad_syscall
|
||||
|
||||
lea r11, [rel syscall_registry]
|
||||
mov r11, [r11 + rax * 8]
|
||||
cmp r11, 0
|
||||
|
||||
11
src/kernel/syscalls.inc.cog
Normal file
11
src/kernel/syscalls.inc.cog
Normal file
@@ -0,0 +1,11 @@
|
||||
; vim: ft=asm
|
||||
; [[[cog code generation
|
||||
; from definitions.context import Context
|
||||
;
|
||||
; ctx = Context(definitions_path)
|
||||
; ctx.parse("syscalls.def")
|
||||
; syscalls = ctx.interfaces['syscalls']
|
||||
; cog.outl(f"NUM_SYSCALLS equ {len(syscalls.methods)}")
|
||||
; ]]]
|
||||
; [[[end]]]
|
||||
|
||||
@@ -15,7 +15,7 @@ endpoint_create(j6_handle_t *handle)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
endpoint_send(j6_handle_t handle, j6_tag_t tag, size_t len, void *data)
|
||||
endpoint_send(j6_handle_t handle, uint64_t tag, const void * data, size_t data_len)
|
||||
{
|
||||
if (tag & j6_tag_system_flag)
|
||||
return j6_err_invalid_arg;
|
||||
@@ -23,28 +23,28 @@ endpoint_send(j6_handle_t handle, j6_tag_t tag, size_t len, void *data)
|
||||
endpoint *e = get_handle<endpoint>(handle);
|
||||
if (!e) return j6_err_invalid_arg;
|
||||
|
||||
return e->send(tag, len, data);
|
||||
return e->send(tag, data, data_len);
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
endpoint_receive(j6_handle_t handle, j6_tag_t *tag, size_t *len, void *data)
|
||||
endpoint_receive(j6_handle_t handle, uint64_t * tag, void * data, size_t * data_len)
|
||||
{
|
||||
if (!tag || !len || (*len && !data))
|
||||
if (!tag || !data_len || !data)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
endpoint *e = get_handle<endpoint>(handle);
|
||||
if (!e) return j6_err_invalid_arg;
|
||||
|
||||
j6_tag_t out_tag = j6_tag_invalid;
|
||||
size_t out_len = *len;
|
||||
j6_status_t s = e->receive(&out_tag, &out_len, data);
|
||||
size_t out_len = *data_len;
|
||||
j6_status_t s = e->receive(&out_tag, data, &out_len);
|
||||
*tag = out_tag;
|
||||
*len = out_len;
|
||||
*data_len = out_len;
|
||||
return s;
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
endpoint_sendrecv(j6_handle_t handle, j6_tag_t *tag, size_t *len, void *data)
|
||||
endpoint_sendrecv(j6_handle_t handle, uint64_t * tag, void * data, size_t * data_len)
|
||||
{
|
||||
if (!tag || (*tag & j6_tag_system_flag))
|
||||
return j6_err_invalid_arg;
|
||||
@@ -52,15 +52,15 @@ endpoint_sendrecv(j6_handle_t handle, j6_tag_t *tag, size_t *len, void *data)
|
||||
endpoint *e = get_handle<endpoint>(handle);
|
||||
if (!e) return j6_err_invalid_arg;
|
||||
|
||||
j6_status_t status = e->send(*tag, *len, data);
|
||||
j6_status_t status = e->send(*tag, data, *data_len);
|
||||
if (status != j6_status_ok)
|
||||
return status;
|
||||
|
||||
j6_tag_t out_tag = j6_tag_invalid;
|
||||
size_t out_len = *len;
|
||||
j6_status_t s = e->receive(&out_tag, &out_len, data);
|
||||
size_t out_len = *data_len;
|
||||
j6_status_t s = e->receive(&out_tag, data, &out_len);
|
||||
*tag = out_tag;
|
||||
*len = out_len;
|
||||
*data_len = out_len;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
namespace syscalls {
|
||||
|
||||
j6_status_t
|
||||
object_koid(j6_handle_t handle, j6_koid_t *koid)
|
||||
kobject_koid(j6_handle_t handle, j6_koid_t *koid)
|
||||
{
|
||||
if (koid == nullptr)
|
||||
return j6_err_invalid_arg;
|
||||
@@ -23,7 +23,7 @@ object_koid(j6_handle_t handle, j6_koid_t *koid)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
object_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs)
|
||||
kobject_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs)
|
||||
{
|
||||
kobject *obj = get_handle<kobject>(handle);
|
||||
if (!obj)
|
||||
@@ -47,11 +47,11 @@ object_wait(j6_handle_t handle, j6_signal_t mask, j6_signal_t *sigs)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
object_wait_many(j6_handle_t *handles, uint32_t count, j6_signal_t mask, j6_handle_t *handle, j6_signal_t *sigs)
|
||||
kobject_wait_many(j6_handle_t * handles, size_t handles_count, uint64_t mask, j6_handle_t * handle, uint64_t * signals)
|
||||
{
|
||||
kutil::vector<kobject*> objects {count};
|
||||
kutil::vector<kobject*> objects {uint32_t(handles_count)};
|
||||
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
for (unsigned i = 0; i < handles_count; ++i) {
|
||||
j6_handle_t h = handles[i];
|
||||
if (h == j6_handle_invalid)
|
||||
continue;
|
||||
@@ -62,7 +62,7 @@ object_wait_many(j6_handle_t *handles, uint32_t count, j6_signal_t mask, j6_hand
|
||||
|
||||
j6_signal_t current = obj->signals();
|
||||
if ((current & mask) != 0) {
|
||||
*sigs = current;
|
||||
*signals = current;
|
||||
*handle = h;
|
||||
return j6_status_ok;
|
||||
}
|
||||
@@ -81,9 +81,9 @@ object_wait_many(j6_handle_t *handles, uint32_t count, j6_signal_t mask, j6_hand
|
||||
return result;
|
||||
|
||||
*handle = j6_handle_invalid;
|
||||
*sigs = th.get_wait_data();
|
||||
*signals = th.get_wait_data();
|
||||
j6_koid_t koid = th.get_wait_object();
|
||||
for (unsigned i = 0; i < count; ++i) {
|
||||
for (unsigned i = 0; i < handles_count; ++i) {
|
||||
if (koid == objects[i]->koid())
|
||||
*handle = handles[i];
|
||||
else
|
||||
@@ -96,7 +96,7 @@ object_wait_many(j6_handle_t *handles, uint32_t count, j6_signal_t mask, j6_hand
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
object_signal(j6_handle_t handle, j6_signal_t signals)
|
||||
kobject_signal(j6_handle_t handle, j6_signal_t signals)
|
||||
{
|
||||
if ((signals & j6_signal_user_mask) != signals)
|
||||
return j6_err_invalid_arg;
|
||||
@@ -110,7 +110,7 @@ object_signal(j6_handle_t handle, j6_signal_t signals)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
object_close(j6_handle_t handle)
|
||||
kobject_close(j6_handle_t handle)
|
||||
{
|
||||
kobject *obj = get_handle<kobject>(handle);
|
||||
if (!obj)
|
||||
|
||||
@@ -16,14 +16,14 @@ process_create(j6_handle_t *handle)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
process_start(j6_handle_t handle, uintptr_t entrypoint, j6_handle_t *handles, size_t handle_count)
|
||||
process_start(j6_handle_t handle, uintptr_t entrypoint, j6_handle_t * handles, size_t handles_count)
|
||||
{
|
||||
process &p = process::current();
|
||||
process *c = get_handle<process>(handle);
|
||||
if (handle_count && !handles)
|
||||
if (handles_count && !handles)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
for (size_t i = 0; i < handle_count; ++i) {
|
||||
for (size_t i = 0; i < handles_count; ++i) {
|
||||
kobject *o = p.lookup_handle(handles[i]);
|
||||
if (o) c->add_handle(o);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ extern log::logger &g_logger;
|
||||
namespace syscalls {
|
||||
|
||||
j6_status_t
|
||||
system_log(const char *message)
|
||||
log(const char *message)
|
||||
{
|
||||
if (message == nullptr)
|
||||
return j6_err_invalid_arg;
|
||||
@@ -26,7 +26,7 @@ system_log(const char *message)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
system_noop()
|
||||
noop()
|
||||
{
|
||||
thread &th = thread::current();
|
||||
log::debug(logs::syscall, "Thread %llx called noop syscall.", th.koid());
|
||||
@@ -61,18 +61,18 @@ system_bind_irq(j6_handle_t sys, j6_handle_t endp, unsigned irq)
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
system_map_phys(j6_handle_t sys, j6_handle_t *vma_handle, uintptr_t phys_addr, size_t size, uint32_t flags)
|
||||
system_map_phys(j6_handle_t handle, j6_handle_t * area, uintptr_t phys, size_t size, uint32_t flags)
|
||||
{
|
||||
// TODO: check capabilities on sys handle
|
||||
if (!vma_handle) return j6_err_invalid_arg;
|
||||
if (!area) return j6_err_invalid_arg;
|
||||
|
||||
// TODO: check to see if frames are already used? How would that collide with
|
||||
// the bootloader's allocated pages already being marked used?
|
||||
if (!(flags & vm_flags::mmio))
|
||||
frame_allocator::get().used(phys_addr, memory::page_count(size));
|
||||
frame_allocator::get().used(phys, memory::page_count(size));
|
||||
|
||||
vm_flags vmf = (static_cast<vm_flags>(flags) & vm_flags::driver_mask);
|
||||
construct_handle<vm_area_fixed>(vma_handle, phys_addr, size, vmf);
|
||||
construct_handle<vm_area_fixed>(area, phys, size, vmf);
|
||||
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
@@ -4,17 +4,18 @@
|
||||
#include "log.h"
|
||||
#include "objects/process.h"
|
||||
#include "objects/thread.h"
|
||||
#include "syscalls/helpers.h"
|
||||
|
||||
namespace syscalls {
|
||||
|
||||
j6_status_t
|
||||
thread_create(void *rip, j6_handle_t *handle)
|
||||
thread_create(j6_handle_t *handle, uintptr_t entrypoint)
|
||||
{
|
||||
thread &parent = thread::current();
|
||||
process &p = parent.parent();
|
||||
|
||||
thread *child = p.create_thread();
|
||||
child->add_thunk_user(reinterpret_cast<uintptr_t>(rip));
|
||||
child->add_thunk_user(entrypoint);
|
||||
*handle = child->self_handle();
|
||||
child->clear_state(thread::state::loading);
|
||||
child->set_state(thread::state::ready);
|
||||
@@ -36,6 +37,18 @@ thread_exit(int32_t status)
|
||||
return j6_err_unexpected;
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
thread_kill(j6_handle_t handle)
|
||||
{
|
||||
thread *th = get_handle<thread>(handle);
|
||||
if (!th)
|
||||
return j6_err_invalid_arg;
|
||||
|
||||
log::debug(logs::task, "Killing thread %llx", th->koid());
|
||||
th->exit(-1);
|
||||
return j6_status_ok;
|
||||
}
|
||||
|
||||
j6_status_t
|
||||
thread_pause()
|
||||
{
|
||||
|
||||
@@ -286,7 +286,7 @@ vm_space::handle_fault(uintptr_t addr, fault_type fault)
|
||||
}
|
||||
|
||||
size_t
|
||||
vm_space::copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length)
|
||||
vm_space::copy(vm_space &source, vm_space &dest, const void *from, void *to, size_t length)
|
||||
{
|
||||
uintptr_t ifrom = reinterpret_cast<uintptr_t>(from);
|
||||
uintptr_t ito = reinterpret_cast<uintptr_t>(to);
|
||||
|
||||
@@ -103,7 +103,7 @@ public:
|
||||
/// \arg to Pointer to the destination in the dest address space
|
||||
/// \arg length Amount of data to copy, in bytes
|
||||
/// \returnd The number of bytes copied
|
||||
static size_t copy(vm_space &source, vm_space &dest, void *from, void *to, size_t length);
|
||||
static size_t copy(vm_space &source, vm_space &dest, const void *from, void *to, size_t length);
|
||||
|
||||
private:
|
||||
friend class vm_area;
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <j6/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SYSCALL(n, name, ...) j6_status_t j6_ ## name (__VA_ARGS__);
|
||||
#include "j6/tables/syscalls.inc"
|
||||
#undef SYSCALL
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
39
src/libraries/j6/include/j6/syscalls.h.cog
Normal file
39
src/libraries/j6/include/j6/syscalls.h.cog
Normal file
@@ -0,0 +1,39 @@
|
||||
#pragma once
|
||||
// vim: ft=cpp
|
||||
|
||||
#include <j6/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*[[[cog code generation
|
||||
from definitions.context import Context
|
||||
|
||||
ctx = Context(definitions_path)
|
||||
ctx.parse("syscalls.def")
|
||||
syscalls = ctx.interfaces["syscalls"]
|
||||
|
||||
for id, scope, method in syscalls.methods:
|
||||
if scope:
|
||||
name = f"{scope.name}_{method.name}"
|
||||
else:
|
||||
name = method.name
|
||||
|
||||
args = []
|
||||
if method.constructor:
|
||||
args.append("j6_handle_t *handle")
|
||||
elif not method.static:
|
||||
args.append("j6_handle_t handle")
|
||||
|
||||
for param in method.params:
|
||||
for type, suffix in param.type.c_names(param.options):
|
||||
args.append(f"{type} {param.name}{suffix}")
|
||||
|
||||
cog.outl(f"""j6_status_t j6_{name} ({", ".join(args)});""")
|
||||
]]]*/
|
||||
/// [[[end]]]
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -1,9 +1,14 @@
|
||||
# vim: ft=python
|
||||
|
||||
module("j6",
|
||||
j6 = module("j6",
|
||||
kind = "lib",
|
||||
includes = [ "include" ],
|
||||
sources = [
|
||||
"init.cpp",
|
||||
"syscalls.s",
|
||||
])
|
||||
|
||||
from glob import glob
|
||||
definitions = glob('definitions/**/*.def', recursive=True)
|
||||
j6.add_input("include/j6/syscalls.h.cog", deps=definitions)
|
||||
j6.add_input("syscalls.s.cog", deps=definitions)
|
||||
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
%macro SYSCALL 2
|
||||
global j6_%1
|
||||
j6_%1:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
; args should already be in rdi, etc, but rcx will
|
||||
; get stomped, so stash it in r10, which isn't a
|
||||
; callee-saved register, but also isn't used in the
|
||||
; function call ABI.
|
||||
mov r10, rcx
|
||||
|
||||
mov rax, %2
|
||||
syscall
|
||||
; result is now already in rax, so just return
|
||||
|
||||
pop rbp
|
||||
ret
|
||||
%endmacro
|
||||
|
||||
%define SYSCALL(n, name) SYSCALL name, n
|
||||
%define SYSCALL(n, name, a) SYSCALL name, n
|
||||
%define SYSCALL(n, name, a, b) SYSCALL name, n
|
||||
%define SYSCALL(n, name, a, b, c) SYSCALL name, n
|
||||
%define SYSCALL(n, name, a, b, c, d) SYSCALL name, n
|
||||
%define SYSCALL(n, name, a, b, c, d, e) SYSCALL name, n
|
||||
|
||||
%include "j6/tables/syscalls.inc"
|
||||
37
src/libraries/j6/syscalls.s.cog
Normal file
37
src/libraries/j6/syscalls.s.cog
Normal file
@@ -0,0 +1,37 @@
|
||||
; vim: ft=asm
|
||||
|
||||
%macro define_syscall 2
|
||||
global j6_%1
|
||||
j6_%1:
|
||||
push rbp
|
||||
mov rbp, rsp
|
||||
|
||||
; args should already be in rdi, etc, but rcx will
|
||||
; get stomped, so stash it in r10, which isn't a
|
||||
; callee-saved register, but also isn't used in the
|
||||
; function call ABI.
|
||||
mov r10, rcx
|
||||
|
||||
mov rax, %2
|
||||
syscall
|
||||
; result is now already in rax, so just return
|
||||
|
||||
pop rbp
|
||||
ret
|
||||
%endmacro
|
||||
|
||||
; [[[cog code generation
|
||||
; from definitions.context import Context
|
||||
;
|
||||
; ctx = Context(definitions_path)
|
||||
; ctx.parse("syscalls.def")
|
||||
; syscalls = ctx.interfaces['syscalls']
|
||||
;
|
||||
; for id, scope, method in syscalls.methods:
|
||||
; if scope:
|
||||
; name = f"{scope.name}_{method.name}"
|
||||
; else:
|
||||
; name = method.name
|
||||
; cog.outl(f"define_syscall {name:20}, {id}")
|
||||
; ]]]
|
||||
; [[[end]]]
|
||||
@@ -33,7 +33,7 @@ struct entry
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
j6_system_log("fb driver starting");
|
||||
j6_log("fb driver starting");
|
||||
|
||||
size_t initc = 0;
|
||||
j6_init_value *initv = nullptr;
|
||||
@@ -48,7 +48,7 @@ main(int argc, const char **argv)
|
||||
}
|
||||
|
||||
if (!fb || fb->addr == 0) {
|
||||
j6_system_log("fb driver didn't find a framebuffer, exiting");
|
||||
j6_log("fb driver didn't find a framebuffer, exiting");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ main(int argc, const char **argv)
|
||||
buffer_size = size;
|
||||
continue;
|
||||
} else if (s != j6_status_ok) {
|
||||
j6_system_log("fb driver got error from get_log, quitting");
|
||||
j6_log("fb driver got error from get_log, quitting");
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ main(int argc, const char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
j6_system_log("fb driver done, exiting");
|
||||
j6_log("fb driver done, exiting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ j6_handle_t handle_system = 2; // boot protocol is that init gets the system as
|
||||
int
|
||||
main(int argc, const char **argv)
|
||||
{
|
||||
j6_system_log("srv.init starting");
|
||||
j6_log("srv.init starting");
|
||||
|
||||
modules mods = modules::load_modules(_arg_modules_phys, handle_system, handle_self);
|
||||
|
||||
@@ -28,7 +28,7 @@ main(int argc, const char **argv)
|
||||
for (auto &mod : mods.of_type(module_type::program)) {
|
||||
auto &prog = static_cast<const module_program&>(mod);
|
||||
sprintf(message, " program module '%s' at %lx", prog.filename, prog.base_address);
|
||||
j6_system_log(message);
|
||||
j6_log(message);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -70,7 +70,7 @@ modules::load_modules(uintptr_t address, j6_handle_t system, j6_handle_t self)
|
||||
|
||||
char message[100];
|
||||
sprintf(message, "srv.init found %d modules from page at 0x%lx", page->count, address);
|
||||
j6_system_log(message);
|
||||
j6_log(message);
|
||||
|
||||
if (!first)
|
||||
first = page->modules;
|
||||
|
||||
@@ -20,32 +20,32 @@ extern "C" {
|
||||
void
|
||||
thread_proc()
|
||||
{
|
||||
j6_system_log("sub thread starting");
|
||||
j6_log("sub thread starting");
|
||||
|
||||
char buffer[512];
|
||||
size_t len = sizeof(buffer);
|
||||
j6_tag_t tag = 0;
|
||||
j6_status_t result = j6_endpoint_receive(endp, &tag, &len, (void*)buffer);
|
||||
j6_status_t result = j6_endpoint_receive(endp, &tag, (void*)buffer, &len);
|
||||
if (result != j6_status_ok)
|
||||
j6_thread_exit(result);
|
||||
|
||||
j6_system_log("sub thread received message");
|
||||
j6_log("sub thread received message");
|
||||
|
||||
for (int i = 0; i < len; ++i)
|
||||
if (buffer[i] >= 'A' && buffer[i] <= 'Z')
|
||||
buffer[i] += 0x20;
|
||||
|
||||
tag++;
|
||||
result = j6_endpoint_send(endp, tag, len, (void*)buffer);
|
||||
result = j6_endpoint_send(endp, tag, (void*)buffer, len);
|
||||
if (result != j6_status_ok)
|
||||
j6_thread_exit(result);
|
||||
|
||||
j6_system_log("sub thread sent message");
|
||||
j6_log("sub thread sent message");
|
||||
|
||||
for (int i = 1; i < 5; ++i)
|
||||
j6_thread_sleep(i*10);
|
||||
|
||||
j6_system_log("sub thread exiting");
|
||||
j6_log("sub thread exiting");
|
||||
j6_thread_exit(0);
|
||||
}
|
||||
|
||||
@@ -55,10 +55,10 @@ main(int argc, const char **argv)
|
||||
j6_handle_t children[2] = {j6_handle_invalid, j6_handle_invalid};
|
||||
j6_signal_t out = 0;
|
||||
|
||||
j6_system_log("main thread starting");
|
||||
j6_log("main thread starting");
|
||||
|
||||
for (int i = 0; i < argc; ++i)
|
||||
j6_system_log(argv[i]);
|
||||
j6_log(argv[i]);
|
||||
|
||||
void *base = malloc(0x1000);
|
||||
if (!base)
|
||||
@@ -68,57 +68,57 @@ main(int argc, const char **argv)
|
||||
for (int i = 0; i < 3; ++i)
|
||||
vma_ptr[i*100] = uint64_t(i);
|
||||
|
||||
j6_system_log("main thread wrote to memory area");
|
||||
j6_log("main thread wrote to memory area");
|
||||
|
||||
j6_status_t result = j6_endpoint_create(&endp);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
j6_system_log("main thread created endpoint");
|
||||
j6_log("main thread created endpoint");
|
||||
|
||||
result = j6_thread_create(reinterpret_cast<void*>(&thread_proc), &children[1]);
|
||||
result = j6_thread_create(&children[1], reinterpret_cast<uintptr_t>(&thread_proc));
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
j6_system_log("main thread created sub thread");
|
||||
j6_log("main thread created sub thread");
|
||||
|
||||
char message[] = "MAIN THREAD SUCCESSFULLY CALLED SENDRECV IF THIS IS LOWERCASE";
|
||||
size_t size = sizeof(message);
|
||||
j6_tag_t tag = 16;
|
||||
result = j6_endpoint_sendrecv(endp, &tag, &size, (void*)message);
|
||||
result = j6_endpoint_sendrecv(endp, &tag, (void*)message, &size);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
if (tag != 17)
|
||||
j6_system_log("GOT WRONG TAG FROM SENDRECV");
|
||||
j6_log("GOT WRONG TAG FROM SENDRECV");
|
||||
|
||||
result = j6_system_bind_irq(__handle_sys, endp, 3);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
j6_system_log(message);
|
||||
j6_log(message);
|
||||
|
||||
j6_system_log("main thread creating a new process");
|
||||
j6_log("main thread creating a new process");
|
||||
result = j6_process_create(&children[0]);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
j6_system_log("main thread waiting on children");
|
||||
j6_log("main thread waiting on children");
|
||||
|
||||
j6_handle_t outhandle;
|
||||
result = j6_object_wait_many(children, 2, -1ull, &outhandle, &out);
|
||||
result = j6_kobject_wait_many(children, 2, -1ull, &outhandle, &out);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
if (outhandle == children[1]) {
|
||||
j6_system_log(" ok from child thread");
|
||||
j6_log(" ok from child thread");
|
||||
} else if (outhandle == children[0]) {
|
||||
j6_system_log(" ok from child process");
|
||||
j6_log(" ok from child process");
|
||||
} else {
|
||||
j6_system_log(" ... got unknown handle");
|
||||
j6_log(" ... got unknown handle");
|
||||
}
|
||||
|
||||
j6_system_log("main testing irqs");
|
||||
j6_log("main testing irqs");
|
||||
|
||||
|
||||
serial_port com2(COM2);
|
||||
@@ -137,16 +137,10 @@ main(int argc, const char **argv)
|
||||
return result;
|
||||
|
||||
if (j6_tag_is_irq(tag))
|
||||
j6_system_log("main thread got irq!");
|
||||
j6_log("main thread got irq!");
|
||||
}
|
||||
|
||||
j6_system_log("main thread closing endpoint");
|
||||
|
||||
result = j6_object_close(endp);
|
||||
if (result != j6_status_ok)
|
||||
return result;
|
||||
|
||||
j6_system_log("main thread done, exiting");
|
||||
j6_log("main thread done, exiting");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user