diff --git a/zion/include/zcall.h b/zion/include/zcall.h index dc0cc81..c0c756f 100644 --- a/zion/include/zcall.h +++ b/zion/include/zcall.h @@ -46,6 +46,9 @@ #define Z_IRQ_PCI_BASE 0x30 +// Capability Calls +#define Z_CAP_DUPLICATE 0x60 + // Debugging Calls. #define Z_DEBUG_PRINT 0x10000000 @@ -101,4 +104,6 @@ void ZThreadExit(); uint64_t* actual_bytes, uint64_t* actual_caps); [[nodiscard]] z_err_t ZIrqRegister(uint64_t irq_num, uint64_t* port_cap); +[[nodiscard]] z_err_t ZCapDuplicate(uint64_t cap_in, uint64_t* cap_out); + [[nodiscard]] z_err_t ZDebug(const char* message); diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index 4bdf22d..2e79bfa 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -239,6 +239,16 @@ z_err_t IrqRegister(ZIrqRegisterReq* req, ZIrqRegisterResp* resp) { return Z_OK; } +z_err_t CapDuplicate(ZCapDuplicateReq* req, ZCapDuplicateResp* resp) { + auto& proc = gScheduler->CurrentProcess(); + auto cap = proc.GetCapability(req->cap); + if (!cap) { + return Z_ERR_CAP_NOT_FOUND; + } + resp->cap = proc.AddExistingCapability(cap); + return Z_OK; +} + extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) { RefPtr thread = gScheduler->CurrentThread(); switch (call_id) { @@ -290,6 +300,9 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) { case Z_IRQ_REGISTER: return IrqRegister(reinterpret_cast(req), reinterpret_cast(resp)); + case Z_CAP_DUPLICATE: + return CapDuplicate(reinterpret_cast(req), + reinterpret_cast(resp)); case Z_DEBUG_PRINT: dbgln("[Debug] %s", req); return Z_OK; diff --git a/zion/usr/zcall.cpp b/zion/usr/zcall.cpp index f7b981a..fe98066 100644 --- a/zion/usr/zcall.cpp +++ b/zion/usr/zcall.cpp @@ -222,4 +222,14 @@ z_err_t ZIrqRegister(uint64_t irq_num, uint64_t* port_cap) { return ret; } +z_err_t ZCapDuplicate(uint64_t cap_in, uint64_t* cap_out) { + ZCapDuplicateReq req{ + .cap = cap_in, + }; + ZCapDuplicateResp resp; + z_err_t ret = SysCall2(Z_CAP_DUPLICATE, &req, &resp); + *cap_out = resp.cap; + return ret; +} + z_err_t ZDebug(const char* message) { return SysCall1(Z_DEBUG_PRINT, message); } diff --git a/zion/usr/zcall_internal.h b/zion/usr/zcall_internal.h index 031c0a2..6fd5382 100644 --- a/zion/usr/zcall_internal.h +++ b/zion/usr/zcall_internal.h @@ -102,3 +102,11 @@ struct ZIrqRegisterReq { struct ZIrqRegisterResp { uint64_t port_cap; }; + +struct ZCapDuplicateReq { + uint64_t cap; +}; + +struct ZCapDuplicateResp { + uint64_t cap; +};