diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 1dc6029..c069f7a 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -27,6 +27,7 @@ add_executable(zion scheduler/jump_user_space.s scheduler/process_manager.cpp scheduler/scheduler.cpp + syscall/process.cpp syscall/syscall.cpp syscall/syscall_enter.s zion.cpp) diff --git a/zion/include/zcall.h b/zion/include/zcall.h index 13b8980..6fb2dd7 100644 --- a/zion/include/zcall.h +++ b/zion/include/zcall.h @@ -28,19 +28,62 @@ return SysCall1(kZion##name, &req); \ } +#define SYS3(name, t1, a1, t2, a2, t3, a3) \ + struct Z##name##Req { \ + t1 a1; \ + t2 a2; \ + t3 a3; \ + }; \ + [[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2, t3 a3) { \ + Z##name##Req req{ \ + .a1 = a1, \ + .a2 = a2, \ + .a3 = a3, \ + }; \ + return SysCall1(kZion##name, &req); \ + } + +#define SYS4(name, t1, a1, t2, a2, t3, a3, t4, a4) \ + struct Z##name##Req { \ + t1 a1; \ + t2 a2; \ + t3 a3; \ + t4 a4; \ + }; \ + [[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2, t3 a3, t4 a4) { \ + Z##name##Req req{ \ + .a1 = a1, \ + .a2 = a2, \ + .a3 = a3, \ + .a4 = a4, \ + }; \ + return SysCall1(kZion##name, &req); \ + } + +#define SYS5(name, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \ + struct Z##name##Req { \ + t1 a1; \ + t2 a2; \ + t3 a3; \ + t4 a4; \ + t5 a5; \ + }; \ + [[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) { \ + Z##name##Req req{ \ + .a1 = a1, \ + .a2 = a2, \ + .a3 = a3, \ + .a4 = a4, \ + .a5 = a5, \ + }; \ + return SysCall1(kZion##name, &req); \ + } + z_err_t SysCall1(uint64_t code, const void* req); SYS1(ProcessExit, uint64_t, code); - -[[nodiscard]] z_err_t ZProcessSpawn(z_cap_t proc_cap, z_cap_t bootstrap_cap, - z_cap_t* new_proc_cap, - z_cap_t* new_vmas_cap, - z_cap_t* new_bootstrap_cap); - -// UNUSED for now, I think we can get away with just starting a thread. -[[nodiscard]] z_err_t ZProcessStart(z_cap_t proc_cap, z_cap_t thread_cap, - uint64_t entry, uint64_t arg1, - uint64_t arg2); +SYS5(ProcessSpawn, z_cap_t, proc_cap, z_cap_t, bootstrap_cap, z_cap_t*, + new_proc_cap, z_cap_t*, new_vmas_cap, z_cap_t*, new_bootstrap_cap); SYS2(ThreadCreate, z_cap_t, proc_cap, z_cap_t*, thread_cap); diff --git a/zion/include/ztypes.h b/zion/include/ztypes.h index 5ddf800..492b2a3 100644 --- a/zion/include/ztypes.h +++ b/zion/include/ztypes.h @@ -31,8 +31,7 @@ typedef uint64_t z_err_t; // Process Calls. const uint64_t kZionProcessExit = 0x1; -#define Z_PROCESS_SPAWN 0x02 -#define Z_PROCESS_START 0x03 +const uint64_t kZionProcessSpawn = 0x2; // Thread Calls. const uint64_t kZionThreadCreate = 0x10; diff --git a/zion/syscall/process.cpp b/zion/syscall/process.cpp new file mode 100644 index 0000000..7f8c90f --- /dev/null +++ b/zion/syscall/process.cpp @@ -0,0 +1,38 @@ +#include "syscall/process.h" + +#include "scheduler/process_manager.h" +#include "scheduler/scheduler.h" +#include "syscall/syscall.h" + +z_err_t ProcessExit(ZProcessExitReq* req) { + auto curr_thread = gScheduler->CurrentThread(); + dbgln("Exit code: %x", req->code); + // FIXME: kill process here. + curr_thread->Exit(); + panic("Returned from thread exit"); + return Z_ERR_UNIMPLEMENTED; +} + +z_err_t ProcessSpawn(ZProcessSpawnReq* req) { + auto& curr_proc = gScheduler->CurrentProcess(); + auto cap = curr_proc.GetCapability(req->proc_cap); + RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_PROC)); + + RefPtr proc = Process::Create(); + gProcMan->InsertProcess(proc); + + *req->new_proc_cap = curr_proc.AddNewCapability( + proc, ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD | ZC_WRITE); + *req->new_vmas_cap = curr_proc.AddNewCapability(proc->vmas(), ZC_WRITE); + + if (req->bootstrap_cap != 0) { + auto cap = curr_proc.ReleaseCapability(req->bootstrap_cap); + if (!cap) { + return Z_ERR_CAP_NOT_FOUND; + } + // FIXME: Check permissions. + *req->new_bootstrap_cap = proc->AddExistingCapability(cap); + } + + return Z_OK; +} diff --git a/zion/syscall/process.h b/zion/syscall/process.h new file mode 100644 index 0000000..0540253 --- /dev/null +++ b/zion/syscall/process.h @@ -0,0 +1,6 @@ +#pragma once + +#include "include/zcall.h" + +z_err_t ProcessExit(ZProcessExitReq* req); +z_err_t ProcessSpawn(ZProcessSpawnReq* req); diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index 6effc3d..ddc3ef0 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -13,6 +13,7 @@ #include "object/process.h" #include "scheduler/process_manager.h" #include "scheduler/scheduler.h" +#include "syscall/process.h" #include "usr/zcall_internal.h" #define RET_IF_NULL(expr) \ @@ -65,39 +66,6 @@ z_err_t ValidateCap(const RefPtr& cap, uint64_t permissions) { return Z_OK; } -z_err_t ProcessExit(ZProcessExitReq* req) { - auto curr_thread = gScheduler->CurrentThread(); - dbgln("Exit code: %x", req->code); - // FIXME: kill process here. - curr_thread->Exit(); - panic("Returned from thread exit"); - return Z_ERR_UNIMPLEMENTED; -} - -z_err_t ProcessSpawn(ZProcessSpawnReq* req, ZProcessSpawnResp* resp) { - auto& curr_proc = gScheduler->CurrentProcess(); - auto cap = curr_proc.GetCapability(req->proc_cap); - RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_PROC)); - - RefPtr proc = Process::Create(); - gProcMan->InsertProcess(proc); - - resp->proc_cap = curr_proc.AddNewCapability( - proc, ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD | ZC_WRITE); - resp->vmas_cap = curr_proc.AddNewCapability(proc->vmas(), ZC_WRITE); - - if (req->bootstrap_cap != 0) { - auto cap = curr_proc.ReleaseCapability(req->bootstrap_cap); - if (!cap) { - return Z_ERR_CAP_NOT_FOUND; - } - // FIXME: Check permissions. - resp->bootstrap_cap = proc->AddExistingCapability(cap); - } - - return Z_OK; -} - z_err_t ThreadCreate(ZThreadCreateReq* req) { auto& curr_proc = gScheduler->CurrentProcess(); auto cap = curr_proc.GetCapability(req->proc_cap); @@ -277,11 +245,10 @@ z_err_t CapDuplicate(ZCapDuplicateReq* req, ZCapDuplicateResp* resp) { extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) { RefPtr thread = gScheduler->CurrentThread(); switch (call_id) { + // syscall/process.h CASE(ProcessExit); + CASE(ProcessSpawn); CASE(ThreadCreate); - case Z_PROCESS_SPAWN: - return ProcessSpawn(reinterpret_cast(req), - reinterpret_cast(resp)); case Z_THREAD_START: return ThreadStart(reinterpret_cast(req)); case Z_THREAD_EXIT: diff --git a/zion/syscall/syscall.h b/zion/syscall/syscall.h index dc8e57c..1bd79ee 100644 --- a/zion/syscall/syscall.h +++ b/zion/syscall/syscall.h @@ -1,3 +1,9 @@ #pragma once +#include "capability/capability.h" +#include "include/ztypes.h" + void InitSyscall(); + +// FIXME: This probably belongs in capability.h +z_err_t ValidateCap(const RefPtr& cap, uint64_t permissions); diff --git a/zion/usr/zcall.cpp b/zion/usr/zcall.cpp index dfd71af..f2fedc9 100644 --- a/zion/usr/zcall.cpp +++ b/zion/usr/zcall.cpp @@ -19,21 +19,6 @@ z_err_t SysCall1(uint64_t number, const void* first) { return SysCall2(number, first, 0); } -z_err_t ZProcessSpawn(z_cap_t proc_cap, z_cap_t bootstrap_cap, - z_cap_t* new_proc_cap, z_cap_t* new_vmas_cap, - z_cap_t* new_bootstrap_cap) { - ZProcessSpawnReq req{ - .proc_cap = proc_cap, - .bootstrap_cap = bootstrap_cap, - }; - ZProcessSpawnResp resp; - z_err_t ret = SysCall2(Z_PROCESS_SPAWN, &req, &resp); - *new_proc_cap = resp.proc_cap; - *new_vmas_cap = resp.vmas_cap; - *new_bootstrap_cap = resp.bootstrap_cap; - return ret; -} - z_err_t ZThreadStart(z_cap_t thread_cap, uint64_t entry, uint64_t arg1, uint64_t arg2) { ZThreadStartReq req{ diff --git a/zion/usr/zcall_internal.h b/zion/usr/zcall_internal.h index 936f47e..ee325dd 100644 --- a/zion/usr/zcall_internal.h +++ b/zion/usr/zcall_internal.h @@ -4,17 +4,6 @@ #include "include/ztypes.h" -struct ZProcessSpawnReq { - z_cap_t proc_cap; - z_cap_t bootstrap_cap; -}; - -struct ZProcessSpawnResp { - z_cap_t proc_cap; - z_cap_t vmas_cap; - z_cap_t bootstrap_cap; -}; - struct ZThreadStartReq { z_cap_t thread_cap; uint64_t entry;