[all] Add stub for new Endpoint kernel object

This commit is contained in:
Drew Galbraith 2023-06-21 21:26:24 -07:00
parent 1f7a15eed4
commit 69501bfe01
15 changed files with 144 additions and 38 deletions

View File

@ -32,11 +32,14 @@ class ErrorOr {
bool ok_; bool ok_;
}; };
#define AOR_INNER(a, b) a##b
#define AOR_VAR(a) AOR_INNER(e, a)
#define ASSIGN_OR_RETURN(lhs, rhs) \ #define ASSIGN_OR_RETURN(lhs, rhs) \
\ \
auto e##__LINE__ = rhs; \ auto AOR_VAR(__LINE__) = rhs; \
if (!e##__LINE__.ok()) { \ if (!AOR_VAR(__LINE__).ok()) { \
return e##__LINE__.error(); \ return AOR_VAR(__LINE__).error(); \
} \ } \
lhs = rhs.value(); lhs = rhs.value();

View File

@ -1,6 +1,8 @@
add_library(mammoth_lib STATIC add_library(mammoth_lib STATIC
src/channel.cpp src/channel.cpp
src/debug.cpp src/debug.cpp
src/endpoint_client.cpp
src/endpoint_server.cpp
src/init.cpp src/init.cpp
src/memory_region.cpp src/memory_region.cpp
src/process.cpp src/process.cpp

View File

@ -0,0 +1,37 @@
#pragma once
#include <glacier/container/pair.h>
#include <glacier/status/error_or.h>
#include <zcall.h>
#include <ztypes.h>
class EndpointClient {
public:
static EndpointClient AdoptEndpoint(z_cap_t cap);
template <typename Req, typename Resp>
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> CallEndpoint(const Req& req);
private:
EndpointClient(uint64_t cap) : cap_(cap) {}
z_cap_t cap_;
};
template <typename Req, typename Resp>
glcr::ErrorOr<glcr::Pair<Resp, z_cap_t>> 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};
}

View File

@ -0,0 +1,22 @@
#pragma once
#include <glacier/status/error_or.h>
#include <ztypes.h>
#include "mammoth/endpoint_client.h"
class EndpointServer {
public:
static glcr::ErrorOr<EndpointServer> Create();
static EndpointServer Adopt(z_cap_t endpoint_cap);
glcr::ErrorOr<EndpointClient> 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) {}
};

View File

@ -3,6 +3,6 @@
#include <glacier/status/error_or.h> #include <glacier/status/error_or.h>
#include <stdint.h> #include <stdint.h>
#include "mammoth/channel.h" #include "mammoth/endpoint_client.h"
glcr::ErrorOr<Channel> SpawnProcessFromElfRegion(uint64_t program); glcr::ErrorOr<EndpointClient> SpawnProcessFromElfRegion(uint64_t program);

View File

@ -0,0 +1,3 @@
#include "mammoth/endpoint_server.h"
EndpointClient EndpointClient::AdoptEndpoint(z_cap_t cap) { return {cap}; }

View File

@ -0,0 +1,14 @@
#include "mammoth/endpoint_server.h"
glcr::ErrorOr<EndpointServer> EndpointServer::Create() {
uint64_t cap;
RET_ERR(ZEndpointCreate(&cap));
return EndpointServer(cap);
}
glcr::ErrorOr<EndpointClient> 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);
}

View File

@ -3,8 +3,8 @@
#include <glacier/status/error.h> #include <glacier/status/error.h>
#include <zcall.h> #include <zcall.h>
#include "mammoth/channel.h"
#include "mammoth/debug.h" #include "mammoth/debug.h"
#include "mammoth/endpoint_server.h"
#include "mammoth/init.h" #include "mammoth/init.h"
#include "mammoth/port.h" #include "mammoth/port.h"
@ -95,20 +95,21 @@ uint64_t LoadElfProgram(uint64_t base, uint64_t as_cap) {
} // namespace } // namespace
glcr::ErrorOr<Channel> SpawnProcessFromElfRegion(uint64_t program) { glcr::ErrorOr<EndpointClient> SpawnProcessFromElfRegion(uint64_t program) {
Channel local, foreign; ASSIGN_OR_RETURN(EndpointServer server, EndpointServer::Create());
check(CreateChannels(local, foreign)); ASSIGN_OR_RETURN(EndpointClient client, server.CreateClient());
uint64_t proc_cap; uint64_t proc_cap;
uint64_t as_cap; uint64_t as_cap;
uint64_t foreign_port_id; uint64_t foreign_port_id;
uint64_t port_cap; uint64_t port_cap;
#if MAM_PROC_DEBUG #if MAM_PROC_DEBUG
dbgln("Port Create"); dbgln("Port Create");
#endif #endif
check(ZPortCreate(&port_cap)); RET_ERR(ZPortCreate(&port_cap));
uint64_t port_cap_donate; uint64_t port_cap_donate;
check(ZCapDuplicate(port_cap, &port_cap_donate)); RET_ERR(ZCapDuplicate(port_cap, &port_cap_donate));
#if MAM_PROC_DEBUG #if MAM_PROC_DEBUG
dbgln("Spawn"); dbgln("Spawn");
@ -127,12 +128,12 @@ glcr::ErrorOr<Channel> SpawnProcessFromElfRegion(uint64_t program) {
Port p(port_cap); Port p(port_cap);
check(p.WriteMessage<uint64_t>(Z_INIT_SELF_PROC, proc_cap)); check(p.WriteMessage<uint64_t>(Z_INIT_SELF_PROC, proc_cap));
check(p.WriteMessage<uint64_t>(Z_INIT_SELF_VMAS, as_cap)); check(p.WriteMessage<uint64_t>(Z_INIT_SELF_VMAS, as_cap));
check(p.WriteMessage<uint64_t>(Z_INIT_CHANNEL, foreign.release_cap())); check(p.WriteMessage<uint64_t>(Z_INIT_CHANNEL, server.GetCap()));
#if MAM_PROC_DEBUG #if MAM_PROC_DEBUG
dbgln("Thread start"); dbgln("Thread start");
#endif #endif
check(ZThreadStart(thread_cap, entry_point, foreign_port_id, 0)); check(ZThreadStart(thread_cap, entry_point, foreign_port_id, 0));
return local; return client;
} }

View File

@ -4,18 +4,21 @@
#include "denali/denali.h" #include "denali/denali.h"
MappedMemoryRegion DenaliClient::ReadSectors(uint64_t device_id, uint64_t lba, glcr::ErrorOr<MappedMemoryRegion> DenaliClient::ReadSectors(
uint64_t num_sectors) { uint64_t device_id, uint64_t lba, uint64_t num_sectors) {
DenaliRead read{ DenaliRead read{
.device_id = device_id, .device_id = device_id,
.lba = lba, .lba = lba,
.size = num_sectors, .size = num_sectors,
}; };
check(channel_.WriteStruct(&read)); auto pair_or = endpoint_.CallEndpoint<DenaliRead, DenaliReadResponse>(read);
if (!pair_or) {
return pair_or.error();
}
auto pair = pair_or.value();
DenaliReadResponse resp; DenaliReadResponse& resp = pair.first();
uint64_t mem_cap; z_cap_t& mem_cap = pair.second();
check(channel_.ReadStructAndCap(&resp, &mem_cap));
return MappedMemoryRegion::FromCapability(mem_cap); return MappedMemoryRegion::FromCapability(mem_cap);
} }

View File

@ -1,15 +1,17 @@
#pragma once #pragma once
#include <mammoth/channel.h> #include <glacier/status/error_or.h>
#include <mammoth/endpoint_client.h>
#include <mammoth/memory_region.h> #include <mammoth/memory_region.h>
class DenaliClient { class DenaliClient {
public: public:
DenaliClient(const Channel& channel) : channel_(channel) {} DenaliClient(const EndpointClient& endpoint) : endpoint_(endpoint) {}
MappedMemoryRegion ReadSectors(uint64_t device_id, uint64_t lba, glcr::ErrorOr<MappedMemoryRegion> ReadSectors(uint64_t device_id,
uint64_t lba,
uint64_t num_sectors); uint64_t num_sectors);
private: private:
Channel channel_; EndpointClient endpoint_;
}; };

View File

@ -49,8 +49,9 @@ struct PartitionEntry {
GptReader::GptReader(const DenaliClient& client) : denali_(client) {} GptReader::GptReader(const DenaliClient& client) : denali_(client) {}
z_err_t GptReader::ParsePartitionTables() { glcr::ErrorCode GptReader::ParsePartitionTables() {
MappedMemoryRegion lba_1_and_2 = denali_.ReadSectors(0, 0, 2); ASSIGN_OR_RETURN(MappedMemoryRegion lba_1_and_2,
denali_.ReadSectors(0, 0, 2));
uint16_t* mbr_sig = reinterpret_cast<uint16_t*>(lba_1_and_2.vaddr() + 0x1FE); uint16_t* mbr_sig = reinterpret_cast<uint16_t*>(lba_1_and_2.vaddr() + 0x1FE);
if (*mbr_sig != 0xAA55) { if (*mbr_sig != 0xAA55) {
return glcr::FAILED_PRECONDITION; return glcr::FAILED_PRECONDITION;
@ -83,8 +84,9 @@ z_err_t GptReader::ParsePartitionTables() {
dbgln("partition_entry_size: %x", entry_size); dbgln("partition_entry_size: %x", entry_size);
dbgln("Num blocks: %x", num_blocks); dbgln("Num blocks: %x", num_blocks);
MappedMemoryRegion part_table = ASSIGN_OR_RETURN(
denali_.ReadSectors(0, header->lba_partition_entries, num_blocks); MappedMemoryRegion part_table,
denali_.ReadSectors(0, header->lba_partition_entries, num_blocks));
dbgln("Entries"); dbgln("Entries");
for (uint64_t i = 0; i < num_partitions; i++) { for (uint64_t i = 0; i < num_partitions; i++) {
PartitionEntry* entry = reinterpret_cast<PartitionEntry*>( PartitionEntry* entry = reinterpret_cast<PartitionEntry*>(

View File

@ -8,7 +8,7 @@ class GptReader {
public: public:
GptReader(const DenaliClient&); GptReader(const DenaliClient&);
z_err_t ParsePartitionTables(); glcr::ErrorCode ParsePartitionTables();
private: private:
DenaliClient denali_; DenaliClient denali_;

View File

@ -1,6 +1,6 @@
#include <denali/denali.h> #include <denali/denali.h>
#include <mammoth/channel.h>
#include <mammoth/debug.h> #include <mammoth/debug.h>
#include <mammoth/endpoint_client.h>
#include <mammoth/init.h> #include <mammoth/init.h>
#include <mammoth/process.h> #include <mammoth/process.h>
#include <zcall.h> #include <zcall.h>
@ -17,13 +17,13 @@ uint64_t main(uint64_t port_cap) {
uint64_t vaddr; uint64_t vaddr;
check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr)); check(ZAddressSpaceMap(gSelfVmasCap, 0, gBootDenaliVmmoCap, &vaddr));
auto local_or = SpawnProcessFromElfRegion(vaddr); auto endpoint_or = SpawnProcessFromElfRegion(vaddr);
if (!local_or) { if (!endpoint_or) {
check(local_or.error()); check(endpoint_or.error());
} }
Channel local = local_or.value(); EndpointClient endpoint = endpoint_or.value();
DenaliClient client(local); DenaliClient client(endpoint);
GptReader reader(client); GptReader reader(client);
check(reader.ParsePartitionTables()); check(reader.ParsePartitionTables());

View File

@ -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); 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); SYS2(CapDuplicate, z_cap_t, cap_in, z_cap_t*, cap_out);
SYS1(Debug, const char*, message); SYS1(Debug, const char*, message);

View File

@ -41,6 +41,13 @@ const uint64_t kZionPortPoll = 0x53;
const uint64_t kZionIrqRegister = 0x58; 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 #define Z_IRQ_PCI_BASE 0x30
// Capability Calls // Capability Calls