diff --git a/CMakeLists.txt b/CMakeLists.txt index c67f1ca..e62ea69 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED True) set(CMAKE_EXPORT_COMPILE_COMMANDS True) -set(BASE_COMPILE_FLAGS "-fno-rtti -fno-exceptions -mgeneral-regs-only") +set(BASE_COMPILE_FLAGS "-ffreestanding -fno-rtti -fno-exceptions -mgeneral-regs-only") set(BASE_LINK_FLAGS "-nostdlib") add_subdirectory(zion) diff --git a/sys/yellowstone/yellowstone.cpp b/sys/yellowstone/yellowstone.cpp index fcad96a..8cc084d 100644 --- a/sys/yellowstone/yellowstone.cpp +++ b/sys/yellowstone/yellowstone.cpp @@ -6,10 +6,22 @@ #include "hw/pcie.h" -int main() { +int main(uint64_t port_cap) { dbgln("Yellowstone Initializing."); + uint64_t msg_type, type, cap, bytes, caps; + check(ZPortRecv(port_cap, 8, reinterpret_cast(&msg_type), 1, &cap, + &type, &bytes, &caps)); + uint64_t vmmo_cap = 0; + if (bytes != 8 || caps != 1) { + crash("Invalid boot msg", Z_ERR_INVALID); + } + if (msg_type == Z_INIT_BOOT_VMMO) { + vmmo_cap = cap; + } else { + crash("Missing vmmo cap", Z_ERR_UNIMPLEMENTED); + } uint64_t vaddr; - check(ZAddressSpaceMap(Z_INIT_VMAS_SELF, 0, Z_INIT_BOOT_VMMO, &vaddr)); + check(ZAddressSpaceMap(Z_INIT_VMAS_SELF, 0, vmmo_cap, &vaddr)); Channel local; check(SpawnProcessFromElfRegion(vaddr, local)); @@ -23,7 +35,7 @@ int main() { reinterpret_cast(&read), 0, nullptr)); DenaliReadResponse resp; - uint64_t mem_cap, type, bytes, caps; + uint64_t mem_cap; check(ZChannelRecv(local.cap(), sizeof(resp), reinterpret_cast(&resp), 1, &mem_cap, &type, diff --git a/zion/loader/init_loader.cpp b/zion/loader/init_loader.cpp index 3caa42c..4d1d550 100644 --- a/zion/loader/init_loader.cpp +++ b/zion/loader/init_loader.cpp @@ -8,6 +8,7 @@ #include "object/process.h" #include "object/thread.h" #include "scheduler/process_manager.h" +#include "scheduler/scheduler.h" #define K_INIT_DEBUG 0 @@ -127,7 +128,26 @@ void LoadInitProgram() { RefPtr prog2_vmmo = MakeRefCounted(prog2.size); prog2_vmmo->CopyBytesToObject(reinterpret_cast(prog2.address), prog2.size); - proc->AddNewCapabilityWithId(Z_INIT_BOOT_VMMO, prog2_vmmo, ZC_WRITE); - proc->CreateThread()->Start(entry, 0, 0); + // TODO: Probably add a way for the kernel to write caps directly rather than + // by installing them first. + uint64_t vmmo_cap = + gScheduler->CurrentProcess().AddNewCapability(prog2_vmmo, ZC_WRITE); + + auto port = MakeRefCounted(); + uint64_t port_cap = proc->AddNewCapability(port, ZC_READ | ZC_WRITE); + + uint64_t vmmo_id = Z_INIT_BOOT_VMMO; + ZMessage vmmo_msg{ + .type = 0, + .num_bytes = 8, + .bytes = reinterpret_cast(&vmmo_id), + .num_caps = 1, + .caps = &vmmo_cap, + }; + if (port->Write(vmmo_msg) != Z_OK) { + panic("Failed to write cap"); + } + + proc->CreateThread()->Start(entry, port_cap, 0); } diff --git a/zion/object/port.cpp b/zion/object/port.cpp index dfbd134..3e3391c 100644 --- a/zion/object/port.cpp +++ b/zion/object/port.cpp @@ -5,23 +5,25 @@ Port::Port() {} z_err_t Port::Write(const ZMessage& msg) { - if (msg.num_caps > 0) { - dbgln("Unimplemented passing caps on port"); - return Z_ERR_UNIMPLEMENTED; - } - if (msg.num_bytes > 0x1000) { dbgln("Large message size unimplemented: %x", msg.num_bytes); return Z_ERR_INVALID; } + dbgln("port write"); - Message message{ - .type = msg.type, - .num_bytes = msg.num_bytes, - .bytes = new uint8_t[msg.num_bytes], - }; + auto message = MakeShared(); + message->type = msg.type, message->num_bytes = msg.num_bytes; + message->bytes = new uint8_t[msg.num_bytes]; for (uint64_t i = 0; i < msg.num_bytes; i++) { - message.bytes[i] = msg.bytes[i]; + message->bytes[i] = msg.bytes[i]; + } + + for (uint64_t i = 0; i < msg.num_caps; i++) { + auto cap = gScheduler->CurrentProcess().ReleaseCapability(msg.caps[i]); + if (!cap) { + return Z_ERR_CAP_NOT_FOUND; + } + message->caps.PushBack(cap); } MutexHolder lock(mutex_); @@ -35,6 +37,7 @@ z_err_t Port::Write(const ZMessage& msg) { } z_err_t Port::Read(ZMessage& msg) { + dbgln("port read"); mutex_.Lock(); while (pending_messages_.size() < 1) { blocked_threads_.PushBack(gScheduler->CurrentThread()); @@ -45,17 +48,25 @@ z_err_t Port::Read(ZMessage& msg) { mutex_.Unlock(); MutexHolder lock(mutex_); - Message next_msg = pending_messages_.PeekFront(); - if (next_msg.num_bytes > msg.num_bytes) { + auto next_msg = pending_messages_.PeekFront(); + if (next_msg->num_bytes > msg.num_bytes) { + return Z_ERR_BUFF_SIZE; + } + if (next_msg->caps.size() > msg.num_caps) { return Z_ERR_BUFF_SIZE; } - msg.type = next_msg.type; - msg.num_bytes = next_msg.num_bytes; - msg.num_caps = 0; + msg.type = next_msg->type; + msg.num_bytes = next_msg->num_bytes; for (uint64_t i = 0; i < msg.num_bytes; i++) { - msg.bytes[i] = next_msg.bytes[i]; + msg.bytes[i] = next_msg->bytes[i]; + } + + msg.num_caps = next_msg->caps.size(); + auto& proc = gScheduler->CurrentProcess(); + for (uint64_t i = 0; i < msg.num_caps; i++) { + msg.caps[i] = proc.AddExistingCapability(next_msg->caps.PopFront()); } pending_messages_.PopFront(); diff --git a/zion/object/port.h b/zion/object/port.h index ade1821..3440d04 100644 --- a/zion/object/port.h +++ b/zion/object/port.h @@ -1,7 +1,9 @@ #pragma once +#include "capability/capability.h" #include "lib/linked_list.h" #include "lib/mutex.h" +#include "lib/shared_ptr.h" #include "object/kernel_object.h" #include "object/thread.h" #include "usr/zcall_internal.h" @@ -27,9 +29,11 @@ class Port : public KernelObject { uint64_t type; uint64_t num_bytes; uint8_t* bytes; + + LinkedList> caps; }; - LinkedList pending_messages_; + LinkedList> pending_messages_; LinkedList> blocked_threads_;