diff --git a/lib/glacier/status/error_or.h b/lib/glacier/status/error_or.h index cbdc158..ca0c85a 100644 --- a/lib/glacier/status/error_or.h +++ b/lib/glacier/status/error_or.h @@ -32,12 +32,15 @@ class ErrorOr { bool ok_; }; -#define ASSIGN_OR_RETURN(lhs, rhs) \ - \ - auto e##__LINE__ = rhs; \ - if (!e##__LINE__.ok()) { \ - return e##__LINE__.error(); \ - } \ +#define AOR_INNER(a, b) a##b +#define AOR_VAR(a) AOR_INNER(e, a) + +#define ASSIGN_OR_RETURN(lhs, rhs) \ + \ + auto AOR_VAR(__LINE__) = rhs; \ + if (!AOR_VAR(__LINE__).ok()) { \ + return AOR_VAR(__LINE__).error(); \ + } \ lhs = rhs.value(); } // namespace glcr diff --git a/lib/mammoth/CMakeLists.txt b/lib/mammoth/CMakeLists.txt index e8ba624..8edb58e 100644 --- a/lib/mammoth/CMakeLists.txt +++ b/lib/mammoth/CMakeLists.txt @@ -1,6 +1,8 @@ add_library(mammoth_lib STATIC src/channel.cpp src/debug.cpp + src/endpoint_client.cpp + src/endpoint_server.cpp src/init.cpp src/memory_region.cpp src/process.cpp diff --git a/lib/mammoth/include/mammoth/endpoint_client.h b/lib/mammoth/include/mammoth/endpoint_client.h new file mode 100644 index 0000000..9b54933 --- /dev/null +++ b/lib/mammoth/include/mammoth/endpoint_client.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include +#include + +class EndpointClient { + public: + static EndpointClient AdoptEndpoint(z_cap_t cap); + + template + glcr::ErrorOr> CallEndpoint(const Req& req); + + private: + EndpointClient(uint64_t cap) : cap_(cap) {} + z_cap_t cap_; +}; + +template +glcr::ErrorOr> EndpointClient::CallEndpoint( + const Req& req) { + uint64_t reply_port_cap; + RET_ERR(ZEndpointSend(cap_, sizeof(Req), &req, &reply_port_cap)); + + Resp resp; + z_cap_t cap = 0; + uint64_t num_caps = 1; + uint64_t num_bytes = sizeof(Resp); + RET_ERR(ZReplyPortRecv(reply_port_cap, &num_bytes, &resp, &num_caps, &cap)); + + if (num_bytes != sizeof(resp) || num_caps != 1) { + return glcr::FAILED_PRECONDITION; + } + + return glcr::Pair{resp, cap}; +} diff --git a/lib/mammoth/include/mammoth/endpoint_server.h b/lib/mammoth/include/mammoth/endpoint_server.h new file mode 100644 index 0000000..51af6c3 --- /dev/null +++ b/lib/mammoth/include/mammoth/endpoint_server.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +#include "mammoth/endpoint_client.h" + +class EndpointServer { + public: + static glcr::ErrorOr Create(); + static EndpointServer Adopt(z_cap_t endpoint_cap); + + glcr::ErrorOr CreateClient(); + + // FIXME: Release Cap here. + z_cap_t GetCap() { return endpoint_cap_; } + + private: + z_cap_t endpoint_cap_; + + EndpointServer(z_cap_t cap) : endpoint_cap_(cap) {} +}; diff --git a/lib/mammoth/include/mammoth/process.h b/lib/mammoth/include/mammoth/process.h index a331422..b853ae1 100644 --- a/lib/mammoth/include/mammoth/process.h +++ b/lib/mammoth/include/mammoth/process.h @@ -3,6 +3,6 @@ #include #include -#include "mammoth/channel.h" +#include "mammoth/endpoint_client.h" -glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program); +glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program); diff --git a/lib/mammoth/src/endpoint_client.cpp b/lib/mammoth/src/endpoint_client.cpp new file mode 100644 index 0000000..7af836b --- /dev/null +++ b/lib/mammoth/src/endpoint_client.cpp @@ -0,0 +1,3 @@ +#include "mammoth/endpoint_server.h" + +EndpointClient EndpointClient::AdoptEndpoint(z_cap_t cap) { return {cap}; } diff --git a/lib/mammoth/src/endpoint_server.cpp b/lib/mammoth/src/endpoint_server.cpp new file mode 100644 index 0000000..071ddab --- /dev/null +++ b/lib/mammoth/src/endpoint_server.cpp @@ -0,0 +1,14 @@ +#include "mammoth/endpoint_server.h" + +glcr::ErrorOr EndpointServer::Create() { + uint64_t cap; + RET_ERR(ZEndpointCreate(&cap)); + return EndpointServer(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); +} diff --git a/lib/mammoth/src/process.cpp b/lib/mammoth/src/process.cpp index 068cd88..267a991 100644 --- a/lib/mammoth/src/process.cpp +++ b/lib/mammoth/src/process.cpp @@ -3,8 +3,8 @@ #include #include -#include "mammoth/channel.h" #include "mammoth/debug.h" +#include "mammoth/endpoint_server.h" #include "mammoth/init.h" #include "mammoth/port.h" @@ -95,20 +95,21 @@ uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) { } // namespace -glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program) { - Channel local, foreign; - check(CreateChannels(local, foreign)); +glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program) { + ASSIGN_OR_RETURN(EndpointServer server, EndpointServer::Create()); + ASSIGN_OR_RETURN(EndpointClient client, server.CreateClient()); uint64_t proc_cap; uint64_t as_cap; uint64_t foreign_port_id; uint64_t port_cap; + #if MAM_PROC_DEBUG dbgln("Port Create"); #endif - check(ZPortCreate(&port_cap)); + RET_ERR(ZPortCreate(&port_cap)); uint64_t port_cap_donate; - check(ZCapDuplicate(port_cap, &port_cap_donate)); + RET_ERR(ZCapDuplicate(port_cap, &port_cap_donate)); #if MAM_PROC_DEBUG dbgln("Spawn"); @@ -127,12 +128,12 @@ 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, foreign.release_cap())); + check(p.WriteMessage(Z_INIT_CHANNEL, server.GetCap())); #if MAM_PROC_DEBUG dbgln("Thread start"); #endif check(ZThreadStart(thread_cap, entry_point, foreign_port_id, 0)); - return local; + return client; } diff --git a/sys/denali/client/denali_client.cpp b/sys/denali/client/denali_client.cpp index fcda77d..07af87d 100644 --- a/sys/denali/client/denali_client.cpp +++ b/sys/denali/client/denali_client.cpp @@ -4,18 +4,21 @@ #include "denali/denali.h" -MappedMemoryRegion DenaliClient::ReadSectors(uint64_t device_id, uint64_t lba, - uint64_t num_sectors) { +glcr::ErrorOr DenaliClient::ReadSectors( + uint64_t device_id, uint64_t lba, uint64_t num_sectors) { DenaliRead read{ .device_id = device_id, .lba = lba, .size = num_sectors, }; - check(channel_.WriteStruct(&read)); + auto pair_or = endpoint_.CallEndpoint(read); + if (!pair_or) { + return pair_or.error(); + } + auto pair = pair_or.value(); - DenaliReadResponse resp; - uint64_t mem_cap; - check(channel_.ReadStructAndCap(&resp, &mem_cap)); + DenaliReadResponse& resp = pair.first(); + z_cap_t& mem_cap = pair.second(); return MappedMemoryRegion::FromCapability(mem_cap); } diff --git a/sys/denali/include/denali/denali_client.h b/sys/denali/include/denali/denali_client.h index 7a91403..f660289 100644 --- a/sys/denali/include/denali/denali_client.h +++ b/sys/denali/include/denali/denali_client.h @@ -1,15 +1,17 @@ #pragma once -#include +#include +#include #include class DenaliClient { public: - DenaliClient(const Channel& channel) : channel_(channel) {} + DenaliClient(const EndpointClient& endpoint) : endpoint_(endpoint) {} - MappedMemoryRegion ReadSectors(uint64_t device_id, uint64_t lba, - uint64_t num_sectors); + glcr::ErrorOr ReadSectors(uint64_t device_id, + uint64_t lba, + uint64_t num_sectors); private: - Channel channel_; + EndpointClient endpoint_; }; diff --git a/sys/yellowstone/hw/gpt.cpp b/sys/yellowstone/hw/gpt.cpp index e68ca47..bce2360 100644 --- a/sys/yellowstone/hw/gpt.cpp +++ b/sys/yellowstone/hw/gpt.cpp @@ -49,8 +49,9 @@ struct PartitionEntry { GptReader::GptReader(const DenaliClient& client) : denali_(client) {} -z_err_t GptReader::ParsePartitionTables() { - MappedMemoryRegion lba_1_and_2 = denali_.ReadSectors(0, 0, 2); +glcr::ErrorCode GptReader::ParsePartitionTables() { + ASSIGN_OR_RETURN(MappedMemoryRegion lba_1_and_2, + denali_.ReadSectors(0, 0, 2)); uint16_t* mbr_sig = reinterpret_cast(lba_1_and_2.vaddr() + 0x1FE); if (*mbr_sig != 0xAA55) { return glcr::FAILED_PRECONDITION; @@ -83,8 +84,9 @@ z_err_t GptReader::ParsePartitionTables() { dbgln("partition_entry_size: %x", entry_size); dbgln("Num blocks: %x", num_blocks); - MappedMemoryRegion part_table = - denali_.ReadSectors(0, header->lba_partition_entries, num_blocks); + ASSIGN_OR_RETURN( + MappedMemoryRegion part_table, + denali_.ReadSectors(0, header->lba_partition_entries, num_blocks)); dbgln("Entries"); for (uint64_t i = 0; i < num_partitions; i++) { PartitionEntry* entry = reinterpret_cast( diff --git a/sys/yellowstone/hw/gpt.h b/sys/yellowstone/hw/gpt.h index 2d7fe05..8a6da3f 100644 --- a/sys/yellowstone/hw/gpt.h +++ b/sys/yellowstone/hw/gpt.h @@ -8,7 +8,7 @@ class GptReader { public: GptReader(const DenaliClient&); - z_err_t ParsePartitionTables(); + glcr::ErrorCode ParsePartitionTables(); private: DenaliClient denali_; diff --git a/sys/yellowstone/yellowstone.cpp b/sys/yellowstone/yellowstone.cpp index fd898a6..341567c 100644 --- a/sys/yellowstone/yellowstone.cpp +++ b/sys/yellowstone/yellowstone.cpp @@ -1,6 +1,6 @@ #include -#include #include +#include #include #include #include @@ -17,13 +17,13 @@ uint64_t main(uint64_t port_cap) { uint64_t vaddr; check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr)); - auto local_or = SpawnProcessFromElfRegion(vaddr); - if (!local_or) { - check(local_or.error()); + auto endpoint_or = SpawnProcessFromElfRegion(vaddr); + if (!endpoint_or) { + check(endpoint_or.error()); } - Channel local = local_or.value(); + EndpointClient endpoint = endpoint_or.value(); - DenaliClient client(local); + DenaliClient client(endpoint); GptReader reader(client); check(reader.ParsePartitionTables()); diff --git a/zion/include/zcall.h b/zion/include/zcall.h index 16e7452..c666dca 100644 --- a/zion/include/zcall.h +++ b/zion/include/zcall.h @@ -123,6 +123,16 @@ SYS5(PortPoll, z_cap_t, port_cap, uint64_t*, num_bytes, void*, data, uint64_t*, SYS2(IrqRegister, uint64_t, irq_num, z_cap_t*, port_cap); +SYS1(EndpointCreate, z_cap_t*, endpoint_cap); +SYS4(EndpointSend, z_cap_t, endpoint_cap, uint64_t, num_bytes, const void*, + data, z_cap_t*, reply_port_cap); +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); + SYS2(CapDuplicate, z_cap_t, cap_in, z_cap_t*, cap_out); SYS1(Debug, const char*, message); diff --git a/zion/include/ztypes.h b/zion/include/ztypes.h index 55d2ca3..a58535a 100644 --- a/zion/include/ztypes.h +++ b/zion/include/ztypes.h @@ -41,6 +41,13 @@ const uint64_t kZionPortPoll = 0x53; const uint64_t kZionIrqRegister = 0x58; +const uint64_t kZionEndpointCreate = 0x60; +const uint64_t kZionEndpointSend = 0x61; +const uint64_t kZionEndpointRecv = 0x62; +const uint64_t kZionReplyPortSend = 0x63; +const uint64_t kZionReplyPortRecv = 0x64; +const uint64_t kZionEndpointCall = 0x65; + #define Z_IRQ_PCI_BASE 0x30 // Capability Calls