diff --git a/lib/glacier/status/error_or.h b/lib/glacier/status/error_or.h index ca0c85a..9150dcb 100644 --- a/lib/glacier/status/error_or.h +++ b/lib/glacier/status/error_or.h @@ -41,6 +41,6 @@ class ErrorOr { if (!AOR_VAR(__LINE__).ok()) { \ return AOR_VAR(__LINE__).error(); \ } \ - lhs = rhs.value(); + lhs = AOR_VAR(__LINE__).value(); } // namespace glcr diff --git a/lib/mammoth/include/mammoth/endpoint_server.h b/lib/mammoth/include/mammoth/endpoint_server.h index 51af6c3..7dd9267 100644 --- a/lib/mammoth/include/mammoth/endpoint_server.h +++ b/lib/mammoth/include/mammoth/endpoint_server.h @@ -15,6 +15,9 @@ class EndpointServer { // FIXME: Release Cap here. z_cap_t GetCap() { return endpoint_cap_; } + glcr::ErrorCode Recieve(uint64_t* num_bytes, void* data, + z_cap_t* reply_port_cap); + private: z_cap_t endpoint_cap_; diff --git a/lib/mammoth/src/endpoint_server.cpp b/lib/mammoth/src/endpoint_server.cpp index 071ddab..8516085 100644 --- a/lib/mammoth/src/endpoint_server.cpp +++ b/lib/mammoth/src/endpoint_server.cpp @@ -6,9 +6,18 @@ glcr::ErrorOr EndpointServer::Create() { return EndpointServer(cap); } +EndpointServer EndpointServer::Adopt(z_cap_t endpoint_cap) { + return EndpointServer(endpoint_cap); +} + glcr::ErrorOr EndpointServer::CreateClient() { uint64_t client_cap; // FIXME: Restrict permissions to send-only here. RET_ERR(ZCapDuplicate(endpoint_cap_, &client_cap)); return EndpointClient::AdoptEndpoint(client_cap); } + +glcr::ErrorCode EndpointServer::Recieve(uint64_t* num_bytes, void* data, + z_cap_t* reply_port_cap) { + return ZEndpointRecv(endpoint_cap_, num_bytes, data, reply_port_cap); +} diff --git a/lib/mammoth/src/init.cpp b/lib/mammoth/src/init.cpp index 5aa0e06..7acfab8 100644 --- a/lib/mammoth/src/init.cpp +++ b/lib/mammoth/src/init.cpp @@ -9,7 +9,7 @@ uint64_t gSelfProcCap = 0; uint64_t gSelfVmasCap = 0; -uint64_t gInitChannelCap = 0; +uint64_t gInitEndpointCap = 0; uint64_t gBootDenaliVmmoCap = 0; @@ -28,8 +28,8 @@ z_err_t ParseInitPort(uint64_t init_port_cap) { dbgln("received vmas"); gSelfVmasCap = init_cap; break; - case Z_INIT_CHANNEL: - gInitChannelCap = init_cap; + case Z_INIT_ENDPOINT: + gInitEndpointCap = init_cap; break; case Z_BOOT_DENALI_VMMO: dbgln("received denali"); diff --git a/lib/mammoth/src/process.cpp b/lib/mammoth/src/process.cpp index 267a991..507e569 100644 --- a/lib/mammoth/src/process.cpp +++ b/lib/mammoth/src/process.cpp @@ -128,7 +128,7 @@ glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program) { Port p(port_cap); check(p.WriteMessage(Z_INIT_SELF_PROC, proc_cap)); check(p.WriteMessage(Z_INIT_SELF_VMAS, as_cap)); - check(p.WriteMessage(Z_INIT_CHANNEL, server.GetCap())); + check(p.WriteMessage(Z_INIT_ENDPOINT, server.GetCap())); #if MAM_PROC_DEBUG dbgln("Thread start"); diff --git a/sys/denali/ahci/command.cpp b/sys/denali/ahci/command.cpp index 1f13c25..aa8a020 100644 --- a/sys/denali/ahci/command.cpp +++ b/sys/denali/ahci/command.cpp @@ -7,8 +7,11 @@ Command::~Command() {} DmaReadCommand::DmaReadCommand(uint64_t lba, uint64_t sector_cnt, - DmaCallback callback) - : lba_(lba), sector_cnt_(sector_cnt), callback_(callback) { + DmaCallback callback, z_cap_t reply_port) + : reply_port_(reply_port), + lba_(lba), + sector_cnt_(sector_cnt), + callback_(callback) { region_ = MappedMemoryRegion::ContiguousPhysical(sector_cnt * 512); } @@ -46,4 +49,6 @@ void DmaReadCommand::PopulatePrdt(PhysicalRegionDescriptor* prdt) { prdt[0].region_address = region_.paddr(); prdt[0].byte_count = region_.size(); } -void DmaReadCommand::Callback() { callback_(lba_, sector_cnt_, region_.cap()); } +void DmaReadCommand::Callback() { + callback_(reply_port_, lba_, sector_cnt_, region_.cap()); +} diff --git a/sys/denali/ahci/command.h b/sys/denali/ahci/command.h index 685b7d8..f502b01 100644 --- a/sys/denali/ahci/command.h +++ b/sys/denali/ahci/command.h @@ -15,8 +15,9 @@ class Command { class DmaReadCommand : public Command { public: - typedef void (*DmaCallback)(uint64_t, uint64_t, uint64_t); - DmaReadCommand(uint64_t lba, uint64_t sector_cnt, DmaCallback callback); + typedef void (*DmaCallback)(z_cap_t, uint64_t, uint64_t, z_cap_t); + DmaReadCommand(uint64_t lba, uint64_t sector_cnt, DmaCallback callback, + z_cap_t reply_port); virtual ~DmaReadCommand() override; @@ -26,6 +27,7 @@ class DmaReadCommand : public Command { void Callback() override; private: + z_cap_t reply_port_; uint64_t lba_; uint64_t sector_cnt_; DmaCallback callback_; diff --git a/sys/denali/denali.cpp b/sys/denali/denali.cpp index e750472..3c8c554 100644 --- a/sys/denali/denali.cpp +++ b/sys/denali/denali.cpp @@ -1,5 +1,6 @@ -#include + #include +#include #include #include @@ -11,7 +12,8 @@ uint64_t main(uint64_t init_port_cap) { AhciDriver driver; RET_ERR(driver.Init()); - DenaliServer server(gInitChannelCap, driver); + EndpointServer endpoint = EndpointServer::Adopt(gInitEndpointCap); + DenaliServer server(endpoint, driver); RET_ERR(server.RunServer()); // FIXME: Add thread join. return 0; diff --git a/sys/denali/denali_server.cpp b/sys/denali/denali_server.cpp index 5208862..bf8aa5b 100644 --- a/sys/denali/denali_server.cpp +++ b/sys/denali/denali_server.cpp @@ -6,22 +6,22 @@ namespace { DenaliServer* gServer = nullptr; -void HandleResponse(uint64_t lba, uint64_t size, uint64_t cap) { - gServer->HandleResponse(lba, size, cap); +void HandleResponse(z_cap_t reply_port, uint64_t lba, uint64_t size, + z_cap_t mem) { + gServer->HandleResponse(reply_port, lba, size, mem); } } // namespace -DenaliServer::DenaliServer(uint64_t channel_cap, AhciDriver& driver) - : channel_cap_(channel_cap), driver_(driver) { +DenaliServer::DenaliServer(EndpointServer server, AhciDriver& driver) + : server_(server), driver_(driver) { gServer = this; } glcr::ErrorCode DenaliServer::RunServer() { while (true) { uint64_t buff_size = kBuffSize; - uint64_t cap_size = 0; - RET_ERR(ZChannelRecv(channel_cap_, &buff_size, read_buffer_, &cap_size, - nullptr)); + z_cap_t reply_port; + RET_ERR(server_.Recieve(&buff_size, read_buffer_, &reply_port)); if (buff_size < sizeof(uint64_t)) { dbgln("Skipping invalid message"); continue; @@ -34,7 +34,7 @@ glcr::ErrorCode DenaliServer::RunServer() { case DENALI_READ: { DenaliRead* read_req = reinterpret_cast(read_buffer_); uint64_t memcap = 0; - RET_ERR(HandleRead(*read_req)); + RET_ERR(HandleRead(*read_req, reply_port)); break; } default: @@ -44,21 +44,22 @@ glcr::ErrorCode DenaliServer::RunServer() { } } -glcr::ErrorCode DenaliServer::HandleRead(const DenaliRead& read) { +glcr::ErrorCode DenaliServer::HandleRead(const DenaliRead& read, + z_cap_t reply_port) { ASSIGN_OR_RETURN(AhciDevice * device, driver_.GetDevice(read.device_id)); device->IssueCommand( - new DmaReadCommand(read.lba, read.size, ::HandleResponse)); + new DmaReadCommand(read.lba, read.size, ::HandleResponse, reply_port)); return glcr::OK; } -void DenaliServer::HandleResponse(uint64_t lba, uint64_t size, uint64_t cap) { +void DenaliServer::HandleResponse(z_cap_t reply_port, uint64_t lba, + uint64_t size, z_cap_t mem) { DenaliReadResponse resp{ .device_id = 0, .lba = lba, .size = size, }; - check(ZChannelSend(channel_cap_, sizeof(resp), - reinterpret_cast(&resp), 1, &cap)); + check(ZReplyPortSend(reply_port, sizeof(resp), &resp, 1, &mem)); } diff --git a/sys/denali/denali_server.h b/sys/denali/denali_server.h index d762c95..3da19a4 100644 --- a/sys/denali/denali_server.h +++ b/sys/denali/denali_server.h @@ -1,24 +1,26 @@ #pragma once #include +#include #include "ahci/ahci_driver.h" #include "denali/denali.h" class DenaliServer { public: - DenaliServer(uint64_t channel_cap, AhciDriver& driver); + DenaliServer(EndpointServer server, AhciDriver& driver); glcr::ErrorCode RunServer(); - void HandleResponse(uint64_t lba, uint64_t size, uint64_t cap); + void HandleResponse(z_cap_t reply_port, uint64_t lba, uint64_t size, + z_cap_t cap); private: static const uint64_t kBuffSize = 1024; - uint64_t channel_cap_; + EndpointServer server_; uint8_t read_buffer_[kBuffSize]; AhciDriver& driver_; - glcr::ErrorCode HandleRead(const DenaliRead& read); + glcr::ErrorCode HandleRead(const DenaliRead& read, z_cap_t reply_port); }; diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index f77df3d..df45647 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -20,9 +20,11 @@ add_executable(zion memory/user_stack_manager.cpp object/address_space.cpp object/channel.cpp + object/endpoint.cpp object/memory_object.cpp object/port.cpp object/process.cpp + object/reply_port.cpp object/thread.cpp scheduler/context_switch.s scheduler/jump_user_space.s @@ -32,9 +34,11 @@ add_executable(zion syscall/capability.cpp syscall/channel.cpp syscall/debug.cpp + syscall/endpoint.cpp syscall/memory_object.cpp syscall/port.cpp syscall/process.cpp + syscall/reply_port.cpp syscall/syscall.cpp syscall/syscall_enter.s syscall/thread.cpp diff --git a/zion/include/zcall.h b/zion/include/zcall.h index c666dca..fe56496 100644 --- a/zion/include/zcall.h +++ b/zion/include/zcall.h @@ -130,8 +130,8 @@ SYS4(EndpointRecv, z_cap_t, endpoint_cap, uint64_t*, num_bytes, void*, data, z_cap_t*, reply_port_cap); SYS5(ReplyPortSend, z_cap_t, reply_port_cap, uint64_t, num_bytes, const void*, data, uint64_t, num_caps, z_cap_t*, caps); -SYS5(ReplyPortRecv, z_cap_t, reply_port_cap, uint64_t*, num_bytes, const void*, - data, uint64_t*, num_caps, z_cap_t*, caps); +SYS5(ReplyPortRecv, z_cap_t, reply_port_cap, uint64_t*, num_bytes, void*, data, + uint64_t*, num_caps, z_cap_t*, caps); SYS2(CapDuplicate, z_cap_t, cap_in, z_cap_t*, cap_out); diff --git a/zion/include/zglobal.h b/zion/include/zglobal.h index abe88a2..5b0d9f7 100644 --- a/zion/include/zglobal.h +++ b/zion/include/zglobal.h @@ -5,6 +5,6 @@ extern uint64_t gSelfProcCap; extern uint64_t gSelfVmasCap; -extern uint64_t gInitChannelCap; +extern uint64_t gInitEndpointCap; extern uint64_t gBootDenaliVmmoCap; diff --git a/zion/include/ztypes.h b/zion/include/ztypes.h index a58535a..2a4e508 100644 --- a/zion/include/ztypes.h +++ b/zion/include/ztypes.h @@ -85,6 +85,6 @@ typedef uint64_t z_cap_t; #define Z_INIT_SELF_PROC 0x4000'0000 #define Z_INIT_SELF_VMAS 0x4000'0001 -#define Z_INIT_CHANNEL 0x4100'0000 +#define Z_INIT_ENDPOINT 0x4100'0000 #define Z_BOOT_DENALI_VMMO 0x4200'0000 diff --git a/zion/lib/message_queue.cpp b/zion/lib/message_queue.cpp index 40f21b2..6bcced6 100644 --- a/zion/lib/message_queue.cpp +++ b/zion/lib/message_queue.cpp @@ -70,3 +70,59 @@ void UnboundedMessageQueue::WriteKernel(uint64_t init, pending_messages_.PushBack(msg); } +glcr::ErrorCode SingleMessageQueue::PushBack(uint64_t num_bytes, + const void* bytes, + uint64_t num_caps, + const z_cap_t* caps) { + if (has_written_) { + return glcr::FAILED_PRECONDITION; + } + num_bytes_ = num_bytes; + bytes_ = new uint8_t[num_bytes]; + + for (uint64_t i = 0; i < num_bytes; i++) { + bytes_[i] = reinterpret_cast(bytes)[i]; + } + + for (uint64_t i = 0; i < num_caps; i++) { + // FIXME: This would feel safer closer to the relevant syscall. + auto cap = gScheduler->CurrentProcess().ReleaseCapability(caps[i]); + if (!cap) { + return glcr::CAP_NOT_FOUND; + } + caps_.PushBack(cap); + } + + has_written_ = true; + + return glcr::OK; +} + +glcr::ErrorCode SingleMessageQueue::PopFront(uint64_t* num_bytes, void* bytes, + uint64_t* num_caps, + z_cap_t* caps) { + if (!has_written_ || has_read_) { + return glcr::FAILED_PRECONDITION; + } + + if (num_bytes_ > *num_bytes) { + return glcr::BUFFER_SIZE; + } + if (caps_.size() > *num_caps) { + return glcr::BUFFER_SIZE; + } + + *num_bytes = num_bytes_; + for (uint64_t i = 0; i < num_bytes_; i++) { + reinterpret_cast(bytes)[i] = bytes_[i]; + } + + *num_caps = caps_.size(); + auto& proc = gScheduler->CurrentProcess(); + for (uint64_t i = 0; i < *num_caps; i++) { + caps[i] = proc.AddExistingCapability(caps_.PopFront()); + } + has_read_ = true; + + return glcr::OK; +} diff --git a/zion/lib/message_queue.h b/zion/lib/message_queue.h index c76b9ab..43ef538 100644 --- a/zion/lib/message_queue.h +++ b/zion/lib/message_queue.h @@ -2,6 +2,7 @@ #include #include +#include #include "capability/capability.h" #include "include/ztypes.h" @@ -11,10 +12,10 @@ class MessageQueue { public: virtual ~MessageQueue() {} - virtual z_err_t PushBack(uint64_t num_bytes, const void* bytes, - uint64_t num_caps, const z_cap_t* caps) = 0; - virtual z_err_t PopFront(uint64_t* num_bytes, void* bytes, uint64_t* num_caps, - z_cap_t* caps) = 0; + virtual glcr::ErrorCode PushBack(uint64_t num_bytes, const void* bytes, + uint64_t num_caps, const z_cap_t* caps) = 0; + virtual glcr::ErrorCode PopFront(uint64_t* num_bytes, void* bytes, + uint64_t* num_caps, z_cap_t* caps) = 0; }; class UnboundedMessageQueue : public MessageQueue { @@ -24,10 +25,10 @@ class UnboundedMessageQueue : public MessageQueue { UnboundedMessageQueue& operator=(const UnboundedMessageQueue&) = delete; virtual ~UnboundedMessageQueue() override {} - z_err_t PushBack(uint64_t num_bytes, const void* bytes, uint64_t num_caps, - const z_cap_t* caps) override; - z_err_t PopFront(uint64_t* num_bytes, void* bytes, uint64_t* num_caps, - z_cap_t* caps) override; + glcr::ErrorCode PushBack(uint64_t num_bytes, const void* bytes, + uint64_t num_caps, const z_cap_t* caps) override; + glcr::ErrorCode PopFront(uint64_t* num_bytes, void* bytes, uint64_t* num_caps, + z_cap_t* caps) override; void WriteKernel(uint64_t init, glcr::RefPtr cap); @@ -44,3 +45,25 @@ class UnboundedMessageQueue : public MessageQueue { LinkedList> pending_messages_; }; + +class SingleMessageQueue : public MessageQueue { + public: + SingleMessageQueue() {} + SingleMessageQueue(const SingleMessageQueue&) = delete; + SingleMessageQueue(SingleMessageQueue&&) = delete; + virtual ~SingleMessageQueue() override {} + + glcr::ErrorCode PushBack(uint64_t num_bytes, const void* bytes, + uint64_t num_caps, const z_cap_t* caps) override; + glcr::ErrorCode PopFront(uint64_t* num_bytes, void* bytes, uint64_t* num_caps, + z_cap_t* caps) override; + + bool empty() { return has_written_ == false; }; + + private: + bool has_written_ = false; + bool has_read_ = false; + uint64_t num_bytes_; + uint8_t* bytes_; + LinkedList> caps_; +}; diff --git a/zion/lib/mutex.cpp b/zion/lib/mutex.cpp index 3cfd323..630f17c 100644 --- a/zion/lib/mutex.cpp +++ b/zion/lib/mutex.cpp @@ -5,7 +5,7 @@ void Mutex::Lock() { while (__atomic_fetch_or(&lock_, 0x1, __ATOMIC_SEQ_CST) == 0x1) { - dbgln("Lock sleep: %s", name_); + // dbgln("Lock sleep: %s", name_); gScheduler->Preempt(); } } diff --git a/zion/object/endpoint.cpp b/zion/object/endpoint.cpp new file mode 100644 index 0000000..3bcb340 --- /dev/null +++ b/zion/object/endpoint.cpp @@ -0,0 +1,43 @@ +#include "object/endpoint.h" + +#include "scheduler/scheduler.h" + +glcr::RefPtr Endpoint::Create() { + return glcr::AdoptPtr(new Endpoint); +} + +glcr::ErrorCode Endpoint::Write(uint64_t num_bytes, const void* data, + z_cap_t reply_port_cap) { + MutexHolder h(mutex_); + RET_ERR(message_queue_.PushBack(num_bytes, data, 1, &reply_port_cap)); + + if (blocked_threads_.size() > 0) { + auto thread = blocked_threads_.PopFront(); + thread->SetState(Thread::RUNNABLE); + gScheduler->Enqueue(thread); + } + + return glcr::OK; +} +glcr::ErrorCode Endpoint::Read(uint64_t* num_bytes, void* data, + z_cap_t* reply_port_cap) { + mutex_.Lock(); + while (message_queue_.empty()) { + auto thread = gScheduler->CurrentThread(); + thread->SetState(Thread::BLOCKED); + mutex_.Unlock(); + gScheduler->Yield(); + mutex_.Lock(); + } + mutex_.Unlock(); + + MutexHolder h(mutex_); + + uint64_t num_caps = 1; + RET_ERR(message_queue_.PopFront(num_bytes, data, &num_caps, reply_port_cap)); + + if (num_caps != 1) { + return glcr::INTERNAL; + } + return glcr::OK; +} diff --git a/zion/object/endpoint.h b/zion/object/endpoint.h new file mode 100644 index 0000000..5b9b2f1 --- /dev/null +++ b/zion/object/endpoint.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +#include "lib/message_queue.h" +#include "lib/mutex.h" +#include "object/kernel_object.h" + +class Endpoint; +class ReplyPort; + +template <> +struct KernelObjectTag { + static const uint64_t type = KernelObject::ENDPOINT; +}; + +class Endpoint : public KernelObject { + public: + uint64_t TypeTag() override { return KernelObject::ENDPOINT; } + static glcr::RefPtr Create(); + + glcr::ErrorCode Write(uint64_t num_bytes, const void* data, + z_cap_t reply_port_cap); + + glcr::ErrorCode Read(uint64_t* num_bytes, void* data, + z_cap_t* reply_port_cap); + + private: + Mutex mutex_{"endpoint"}; + UnboundedMessageQueue message_queue_; + + glcr::IntrusiveList blocked_threads_; + + Endpoint() {} +}; diff --git a/zion/object/kernel_object.h b/zion/object/kernel_object.h index d3a425e..7e258fa 100644 --- a/zion/object/kernel_object.h +++ b/zion/object/kernel_object.h @@ -12,6 +12,8 @@ class KernelObject : public glcr::RefCounted { MEMORY_OBJECT = 0x4, CHANNEL = 0x5, PORT = 0x6, + ENDPOINT = 0x7, + REPLY_PORT = 0x8, }; virtual uint64_t TypeTag() = 0; diff --git a/zion/object/reply_port.cpp b/zion/object/reply_port.cpp new file mode 100644 index 0000000..a2b4e49 --- /dev/null +++ b/zion/object/reply_port.cpp @@ -0,0 +1,41 @@ +#include "object/reply_port.h" + +#include "scheduler/scheduler.h" + +glcr::RefPtr ReplyPort::Create() { + return glcr::AdoptPtr(new ReplyPort); +} + +uint64_t ReplyPort::Write(uint64_t num_bytes, const void* data, + uint64_t num_caps, uint64_t* caps) { + MutexHolder h(mutex_); + RET_ERR(message_holder_.PushBack(num_bytes, data, num_caps, caps)); + + if (blocked_thread_) { + // FIXME: We need to handle the case where the blocked thread has died I + // think. + blocked_thread_->SetState(Thread::RUNNABLE); + gScheduler->Enqueue(blocked_thread_); + blocked_thread_ = nullptr; + } + return glcr::OK; +} + +uint64_t ReplyPort::Read(uint64_t* num_bytes, void* data, uint64_t* num_caps, + uint64_t* caps) { + mutex_.Lock(); + if (message_holder_.empty()) { + // Multiple threads can't block on a reply port. + if (blocked_thread_) { + mutex_.Unlock(); + return glcr::FAILED_PRECONDITION; + } + blocked_thread_ = gScheduler->CurrentThread(); + blocked_thread_->SetState(Thread::BLOCKED); + mutex_.Unlock(); + gScheduler->Yield(); + mutex_.Lock(); + } + + return message_holder_.PopFront(num_bytes, data, num_caps, caps); +} diff --git a/zion/object/reply_port.h b/zion/object/reply_port.h new file mode 100644 index 0000000..c160909 --- /dev/null +++ b/zion/object/reply_port.h @@ -0,0 +1,33 @@ +#pragma once + +#include + +#include "lib/message_queue.h" +#include "lib/mutex.h" +#include "object/kernel_object.h" + +class ReplyPort; + +template <> +struct KernelObjectTag { + static const uint64_t type = KernelObject::REPLY_PORT; +}; + +class ReplyPort : public KernelObject { + public: + uint64_t TypeTag() override { return KernelObject::REPLY_PORT; } + static glcr::RefPtr Create(); + + uint64_t Write(uint64_t num_bytes, const void* data, uint64_t num_caps, + uint64_t* caps); + uint64_t Read(uint64_t* num_bytes, void* data, uint64_t* num_caps, + uint64_t* caps); + + private: + Mutex mutex_{"reply_port"}; + SingleMessageQueue message_holder_; + + glcr::RefPtr blocked_thread_; + + ReplyPort() {} +}; diff --git a/zion/syscall/endpoint.cpp b/zion/syscall/endpoint.cpp new file mode 100644 index 0000000..088d7ee --- /dev/null +++ b/zion/syscall/endpoint.cpp @@ -0,0 +1,35 @@ +#include "syscall/endpoint.h" + +#include "object/endpoint.h" +#include "object/reply_port.h" +#include "scheduler/scheduler.h" + +glcr::ErrorCode EndpointCreate(ZEndpointCreateReq* req) { + auto& proc = gScheduler->CurrentProcess(); + *req->endpoint_cap = + proc.AddNewCapability(Endpoint::Create(), ZC_READ | ZC_WRITE); + return glcr::OK; +} + +glcr::ErrorCode EndpointSend(ZEndpointSendReq* req) { + auto& proc = gScheduler->CurrentProcess(); + + auto endpoint_cap = proc.GetCapability(req->endpoint_cap); + ValidateCapability(endpoint_cap, ZC_WRITE); + auto endpoint = endpoint_cap->obj(); + + auto reply_port = ReplyPort::Create(); + *req->reply_port_cap = proc.AddNewCapability(reply_port, ZC_READ); + uint64_t reply_port_cap_to_send = proc.AddNewCapability(reply_port, ZC_WRITE); + return endpoint->Write(req->num_bytes, req->data, reply_port_cap_to_send); +} + +glcr::ErrorCode EndpointRecv(ZEndpointRecvReq* req) { + auto& proc = gScheduler->CurrentProcess(); + + auto endpoint_cap = proc.GetCapability(req->endpoint_cap); + ValidateCapability(endpoint_cap, ZC_READ); + auto endpoint = endpoint_cap->obj(); + + return endpoint->Read(req->num_bytes, req->data, req->reply_port_cap); +} diff --git a/zion/syscall/endpoint.h b/zion/syscall/endpoint.h new file mode 100644 index 0000000..64594ac --- /dev/null +++ b/zion/syscall/endpoint.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#include "include/zcall.h" + +glcr::ErrorCode EndpointCreate(ZEndpointCreateReq* req); + +glcr::ErrorCode EndpointSend(ZEndpointSendReq* req); + +glcr::ErrorCode EndpointRecv(ZEndpointRecvReq* req); diff --git a/zion/syscall/reply_port.cpp b/zion/syscall/reply_port.cpp new file mode 100644 index 0000000..32f2da4 --- /dev/null +++ b/zion/syscall/reply_port.cpp @@ -0,0 +1,22 @@ +#include "syscall/reply_port.h" + +#include "object/reply_port.h" +#include "scheduler/scheduler.h" + +glcr::ErrorCode ReplyPortSend(ZReplyPortSendReq* req) { + auto& proc = gScheduler->CurrentProcess(); + auto reply_port_cap = proc.GetCapability(req->reply_port_cap); + ValidateCapability(reply_port_cap, ZC_WRITE); + auto reply_port = reply_port_cap->obj(); + + return reply_port->Write(req->num_bytes, req->data, req->num_caps, req->caps); +} +glcr::ErrorCode ReplyPortRecv(ZReplyPortRecvReq* req) { + auto& proc = gScheduler->CurrentProcess(); + + auto reply_port_cap = proc.GetCapability(req->reply_port_cap); + ValidateCapability(reply_port_cap, ZC_READ); + auto reply_port = reply_port_cap->obj(); + + return reply_port->Read(req->num_bytes, req->data, req->num_caps, req->caps); +} diff --git a/zion/syscall/reply_port.h b/zion/syscall/reply_port.h new file mode 100644 index 0000000..4b4d34f --- /dev/null +++ b/zion/syscall/reply_port.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#include "include/zcall.h" + +glcr::ErrorCode ReplyPortSend(ZReplyPortSendReq* req); + +glcr::ErrorCode ReplyPortRecv(ZReplyPortRecvReq* req); diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index e231438..11efd24 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -8,9 +8,11 @@ #include "syscall/capability.h" #include "syscall/channel.h" #include "syscall/debug.h" +#include "syscall/endpoint.h" #include "syscall/memory_object.h" #include "syscall/port.h" #include "syscall/process.h" +#include "syscall/reply_port.h" #include "syscall/thread.h" #define EFER 0xC0000080 @@ -73,6 +75,13 @@ extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req) { CASE(PortRecv); CASE(PortPoll); CASE(IrqRegister); + // syscall/endpoint.h + CASE(EndpointCreate); + CASE(EndpointSend); + CASE(EndpointRecv); + // syscall/reply_port.h + CASE(ReplyPortSend); + CASE(ReplyPortRecv); // syscall/capability.h CASE(CapDuplicate); // syscall/debug.h