From a46694d0f7b2acb8329629c9a7292db5232bc626 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Thu, 22 Jun 2023 02:19:16 -0700 Subject: [PATCH] [yellowstone] Add yellowstone server for endpoint registration. --- lib/mammoth/include/mammoth/endpoint_client.h | 2 + lib/mammoth/include/mammoth/port.h | 10 ++ lib/mammoth/include/mammoth/process.h | 5 +- lib/mammoth/src/port.cpp | 22 ++++ lib/mammoth/src/process.cpp | 22 ++-- sys/denali/CMakeLists.txt | 1 + sys/denali/denali.cpp | 21 +++- sys/yellowstone/CMakeLists.txt | 16 +++ sys/yellowstone/include/yellowstone.h | 12 ++ sys/yellowstone/stub/yellowstone_stub.cpp | 3 + sys/yellowstone/yellowstone.cpp | 27 ++--- sys/yellowstone/yellowstone_server.cpp | 105 ++++++++++++++++++ sys/yellowstone/yellowstone_server.h | 33 ++++++ 13 files changed, 248 insertions(+), 31 deletions(-) create mode 100644 sys/yellowstone/include/yellowstone.h create mode 100644 sys/yellowstone/stub/yellowstone_stub.cpp create mode 100644 sys/yellowstone/yellowstone_server.cpp create mode 100644 sys/yellowstone/yellowstone_server.h diff --git a/lib/mammoth/include/mammoth/endpoint_client.h b/lib/mammoth/include/mammoth/endpoint_client.h index 9b54933..66a14fc 100644 --- a/lib/mammoth/include/mammoth/endpoint_client.h +++ b/lib/mammoth/include/mammoth/endpoint_client.h @@ -12,6 +12,8 @@ class EndpointClient { template glcr::ErrorOr> CallEndpoint(const Req& req); + z_cap_t GetCap() { return cap_; } + private: EndpointClient(uint64_t cap) : cap_(cap) {} z_cap_t cap_; diff --git a/lib/mammoth/include/mammoth/port.h b/lib/mammoth/include/mammoth/port.h index 8344a05..97c72b7 100644 --- a/lib/mammoth/include/mammoth/port.h +++ b/lib/mammoth/include/mammoth/port.h @@ -1,17 +1,27 @@ #pragma once +#include +#include #include #include +// FIXME: Split send and receive. class Port { public: + static glcr::ErrorOr Create(); Port(uint64_t port_cap); + glcr::ErrorCode RecvCap(uint64_t* num_bytes, char* msg, uint64_t* cap); z_err_t PollForIntCap(uint64_t* msg, uint64_t* cap); template z_err_t WriteMessage(const T& obj, uint64_t cap); + glcr::ErrorCode WriteString(glcr::String str, uint64_t cap); + + // FIXME: We can't create error_ors of ints + glcr::ErrorCode Duplicate(uint64_t* new_cap); + private: uint64_t port_cap_; }; diff --git a/lib/mammoth/include/mammoth/process.h b/lib/mammoth/include/mammoth/process.h index b853ae1..dd6d0e4 100644 --- a/lib/mammoth/include/mammoth/process.h +++ b/lib/mammoth/include/mammoth/process.h @@ -1,8 +1,9 @@ #pragma once -#include +#include #include #include "mammoth/endpoint_client.h" -glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program); +glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program, + EndpointClient client); diff --git a/lib/mammoth/src/port.cpp b/lib/mammoth/src/port.cpp index d6b1fe3..110def5 100644 --- a/lib/mammoth/src/port.cpp +++ b/lib/mammoth/src/port.cpp @@ -5,8 +5,23 @@ #include "mammoth/debug.h" +glcr::ErrorOr Port::Create() { + z_cap_t port; + RET_ERR(ZPortCreate(&port)); + return Port(port); +} Port::Port(uint64_t port_cap) : port_cap_(port_cap) {} +glcr::ErrorCode Port::RecvCap(uint64_t *num_bytes, char *msg, uint64_t *cap) { + uint64_t caps = 1; + RET_ERR(ZPortRecv(port_cap_, num_bytes, reinterpret_cast(msg), + &caps, cap)); + + if (caps != 1) { + return glcr::FAILED_PRECONDITION; + } + return glcr::OK; +} z_err_t Port::PollForIntCap(uint64_t *msg, uint64_t *cap) { uint64_t bytes = sizeof(uint64_t); uint64_t caps = 1; @@ -21,3 +36,10 @@ z_err_t Port::PollForIntCap(uint64_t *msg, uint64_t *cap) { } return glcr::OK; } +glcr::ErrorCode Port::WriteString(glcr::String str, uint64_t cap) { + return ZPortSend(port_cap_, str.length() + 1, str.cstr(), 1, &cap); +} + +glcr::ErrorCode Port::Duplicate(uint64_t *new_cap) { + return ZCapDuplicate(port_cap_, new_cap); +} diff --git a/lib/mammoth/src/process.cpp b/lib/mammoth/src/process.cpp index 507e569..0578442 100644 --- a/lib/mammoth/src/process.cpp +++ b/lib/mammoth/src/process.cpp @@ -95,10 +95,8 @@ uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) { } // namespace -glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program) { - ASSIGN_OR_RETURN(EndpointServer server, EndpointServer::Create()); - ASSIGN_OR_RETURN(EndpointClient client, server.CreateClient()); - +glcr::ErrorCode SpawnProcessFromElfRegion(uint64_t program, + EndpointClient client) { uint64_t proc_cap; uint64_t as_cap; uint64_t foreign_port_id; @@ -114,8 +112,8 @@ glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program) { #if MAM_PROC_DEBUG dbgln("Spawn"); #endif - check(ZProcessSpawn(gSelfProcCap, port_cap_donate, &proc_cap, &as_cap, - &foreign_port_id)); + RET_ERR(ZProcessSpawn(gSelfProcCap, port_cap_donate, &proc_cap, &as_cap, + &foreign_port_id)); uint64_t entry_point = LoadElfProgram(program, as_cap); @@ -123,17 +121,17 @@ glcr::ErrorOr SpawnProcessFromElfRegion(uint64_t program) { dbgln("Thread Create"); #endif uint64_t thread_cap; - check(ZThreadCreate(proc_cap, &thread_cap)); + RET_ERR(ZThreadCreate(proc_cap, &thread_cap)); 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_ENDPOINT, server.GetCap())); + RET_ERR(p.WriteMessage(Z_INIT_SELF_PROC, proc_cap)); + RET_ERR(p.WriteMessage(Z_INIT_SELF_VMAS, as_cap)); + RET_ERR(p.WriteMessage(Z_INIT_ENDPOINT, client.GetCap())); #if MAM_PROC_DEBUG dbgln("Thread start"); #endif - check(ZThreadStart(thread_cap, entry_point, foreign_port_id, 0)); + RET_ERR(ZThreadStart(thread_cap, entry_point, foreign_port_id, 0)); - return client; + return glcr::OK; } diff --git a/sys/denali/CMakeLists.txt b/sys/denali/CMakeLists.txt index e27b1bb..7dff3d8 100644 --- a/sys/denali/CMakeLists.txt +++ b/sys/denali/CMakeLists.txt @@ -15,6 +15,7 @@ target_link_libraries(denali cxx glacier mammoth_lib + yellowstonestub ) set_target_properties(denali PROPERTIES diff --git a/sys/denali/denali.cpp b/sys/denali/denali.cpp index 3c8c554..5dce931 100644 --- a/sys/denali/denali.cpp +++ b/sys/denali/denali.cpp @@ -2,7 +2,9 @@ #include #include #include +#include #include +#include #include "ahci/ahci_driver.h" #include "denali_server.h" @@ -12,7 +14,24 @@ uint64_t main(uint64_t init_port_cap) { AhciDriver driver; RET_ERR(driver.Init()); - EndpointServer endpoint = EndpointServer::Adopt(gInitEndpointCap); + EndpointClient yellowstone = EndpointClient::AdoptEndpoint(gInitEndpointCap); + YellowstoneGetReq req{ + .type = kYellowstoneGetRegistration, + }; + auto resp_cap_or = + yellowstone + .CallEndpoint(req); + if (!resp_cap_or.ok()) { + dbgln("Bad call"); + check(resp_cap_or.error()); + } + auto resp_cap = resp_cap_or.value(); + Port notify(resp_cap.second()); + + ASSIGN_OR_RETURN(EndpointServer endpoint, EndpointServer::Create()); + ASSIGN_OR_RETURN(EndpointClient client, endpoint.CreateClient()); + notify.WriteMessage("denali", client.GetCap()); + DenaliServer server(endpoint, driver); RET_ERR(server.RunServer()); // FIXME: Add thread join. diff --git a/sys/yellowstone/CMakeLists.txt b/sys/yellowstone/CMakeLists.txt index 92d8b61..2959727 100644 --- a/sys/yellowstone/CMakeLists.txt +++ b/sys/yellowstone/CMakeLists.txt @@ -2,6 +2,7 @@ add_executable(yellowstone hw/gpt.cpp hw/pcie.cpp yellowstone.cpp + yellowstone_server.cpp ) target_include_directories(yellowstone PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) @@ -9,6 +10,7 @@ add_executable(yellowstone target_link_libraries(yellowstone cxx mammoth_lib + glacier libdenali ) @@ -16,3 +18,17 @@ set_target_properties(yellowstone PROPERTIES COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}" LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}" ) + + +add_library(yellowstonestub + stub/yellowstone_stub.cpp + ) + +target_include_directories(yellowstonestub + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include") + +set_target_properties(yellowstonestub PROPERTIES + COMPILE_FLAGS "${CMAKE_CXX_FLAGS} ${BASE_COMPILE_FLAGS}" + LINK_FLAGS "${CMAKE_EXE_LINK_FLAGS} ${BASE_LINK_FLAGS}" + ) diff --git a/sys/yellowstone/include/yellowstone.h b/sys/yellowstone/include/yellowstone.h new file mode 100644 index 0000000..cfea43a --- /dev/null +++ b/sys/yellowstone/include/yellowstone.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +const uint64_t kYellowstoneGetAhci = 0x01; +const uint64_t kYellowstoneGetRegistration = 0x02; + +struct YellowstoneGetReq { + uint64_t type; +}; + +struct YellowstoneGetRegistrationResp {}; diff --git a/sys/yellowstone/stub/yellowstone_stub.cpp b/sys/yellowstone/stub/yellowstone_stub.cpp new file mode 100644 index 0000000..85a0b90 --- /dev/null +++ b/sys/yellowstone/stub/yellowstone_stub.cpp @@ -0,0 +1,3 @@ +// PLACEHOLDER +#include +uint64_t a = 0; diff --git a/sys/yellowstone/yellowstone.cpp b/sys/yellowstone/yellowstone.cpp index 01a5c1d..e0e6b82 100644 --- a/sys/yellowstone/yellowstone.cpp +++ b/sys/yellowstone/yellowstone.cpp @@ -1,4 +1,3 @@ -#include #include #include #include @@ -7,32 +6,28 @@ #include "hw/gpt.h" #include "hw/pcie.h" +#include "yellowstone_server.h" uint64_t main(uint64_t port_cap) { dbgln("Yellowstone Initializing."); check(ParseInitPort(port_cap)); + ASSIGN_OR_RETURN(YellowstoneServer server, YellowstoneServer::Create()); + Thread server_thread = server.RunServer(); + Thread registration_thread = server.RunRegistration(); DumpPciEDevices(); uint64_t vaddr; check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr)); - - auto endpoint_or = SpawnProcessFromElfRegion(vaddr); - if (!endpoint_or) { - check(endpoint_or.error()); - } - EndpointClient endpoint = endpoint_or.value(); - - DenaliClient client(endpoint); - GptReader reader(client); - - check(reader.ParsePartitionTables()); + ASSIGN_OR_RETURN(EndpointClient client, server.GetServerClient()); + check(SpawnProcessFromElfRegion(vaddr, client)); check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootVictoriaFallsVmmoCap, &vaddr)); - auto error_or = SpawnProcessFromElfRegion(vaddr); - if (!error_or) { - check(error_or.error()); - } + ASSIGN_OR_RETURN(client, server.GetServerClient()); + check(SpawnProcessFromElfRegion(vaddr, client)); + + check(server_thread.Join()); + check(registration_thread.Join()); dbgln("Yellowstone Finished Successfully."); return 0; } diff --git a/sys/yellowstone/yellowstone_server.cpp b/sys/yellowstone/yellowstone_server.cpp new file mode 100644 index 0000000..a6608be --- /dev/null +++ b/sys/yellowstone/yellowstone_server.cpp @@ -0,0 +1,105 @@ +#include "yellowstone_server.h" + +#include +#include +#include +#include + +#include "hw/gpt.h" +#include "include/yellowstone.h" + +// FIXME: This linkage was missing :( +void* operator new[](uint64_t size) { return malloc(size); } +namespace { + +void ServerThreadBootstrap(void* yellowstone) { + dbgln("Yellowstone server starting"); + static_cast(yellowstone)->ServerThread(); +} + +void RegistrationThreadBootstrap(void* yellowstone) { + dbgln("Yellowstone registration starting"); + static_cast(yellowstone)->RegistrationThread(); +} + +glcr::ErrorCode HandleDenaliRegistration(z_cap_t endpoint_cap) { + EndpointClient endpoint = EndpointClient::AdoptEndpoint(endpoint_cap); + DenaliClient client(endpoint); + GptReader reader(client); + + return reader.ParsePartitionTables(); +} + +} // namespace + +glcr::ErrorOr YellowstoneServer::Create() { + ASSIGN_OR_RETURN(EndpointServer server, EndpointServer::Create()); + ASSIGN_OR_RETURN(Port port, Port::Create()); + return YellowstoneServer(server, port); +} + +YellowstoneServer::YellowstoneServer(EndpointServer server, Port port) + : server_(server), register_port_(port) {} + +Thread YellowstoneServer::RunServer() { + return Thread(ServerThreadBootstrap, this); +} + +Thread YellowstoneServer::RunRegistration() { + return Thread(RegistrationThreadBootstrap, this); +} + +void YellowstoneServer::ServerThread() { + while (true) { + uint64_t num_bytes = kBufferSize; + uint64_t reply_port_cap; + // FIXME: Error handling. + check(server_.Recieve(&num_bytes, server_buffer_, &reply_port_cap)); + YellowstoneGetReq* req = + reinterpret_cast(server_buffer_); + switch (req->type) { + case kYellowstoneGetAhci: + dbgln("Yellowstone::GetAHCI"); + break; + case kYellowstoneGetRegistration: { + dbgln("Yellowstone::GetRegistration"); + uint64_t reg_cap; + check(register_port_.Duplicate(®_cap)); + YellowstoneGetRegistrationResp resp; + check(ZReplyPortSend(reply_port_cap, sizeof(resp), &resp, 1, ®_cap)); + break; + } + default: + dbgln("Unknown request type: %x", req->type); + break; + } + } +} + +void YellowstoneServer::RegistrationThread() { + while (true) { + uint64_t num_bytes = kBufferSize; + z_cap_t endpoint_cap; + // FIXME: Better error handling here. + check(register_port_.RecvCap(&num_bytes, registration_buffer_, + &endpoint_cap)); + glcr::String name(registration_buffer_); + if (name == "denali") { + denali_cap_ = endpoint_cap; + check(HandleDenaliRegistration(denali_cap_)); + continue; + } + + if (name == "victoriafalls") { + victoria_falls_cap_ = endpoint_cap; + continue; + } + + dbgln("[WARN] Got endpoint cap type:"); + dbgln(name.cstr()); + } +} + +glcr::ErrorOr YellowstoneServer::GetServerClient() { + return server_.CreateClient(); +} diff --git a/sys/yellowstone/yellowstone_server.h b/sys/yellowstone/yellowstone_server.h new file mode 100644 index 0000000..30b355e --- /dev/null +++ b/sys/yellowstone/yellowstone_server.h @@ -0,0 +1,33 @@ +#pragma once + +#include +#include +#include +#include + +class YellowstoneServer { + public: + static glcr::ErrorOr Create(); + + Thread RunServer(); + Thread RunRegistration(); + + void ServerThread(); + void RegistrationThread(); + + glcr::ErrorOr GetServerClient(); + + private: + EndpointServer server_; + Port register_port_; + + static const uint64_t kBufferSize = 128; + uint8_t server_buffer_[kBufferSize]; + char registration_buffer_[kBufferSize]; + + // TODO: Store these in a data structure. + z_cap_t denali_cap_ = 0; + z_cap_t victoria_falls_cap_ = 0; + + YellowstoneServer(EndpointServer server, Port port); +};