Compare commits

..

No commits in common. "1edd5023ceefda3fb882a827c4716fce382736f6" and "4fef54084f058c6f76596609f0dd31c14807c5b2" have entirely different histories.

30 changed files with 687 additions and 567 deletions

View File

@ -7,8 +7,8 @@ class Channel {
public: public:
Channel() {} Channel() {}
void adopt_cap(uint64_t id); void adopt_cap(uint64_t id);
z_cap_t release_cap(); uint64_t release_cap();
z_cap_t cap(); uint64_t cap();
z_err_t WriteStr(const char* msg); z_err_t WriteStr(const char* msg);
z_err_t ReadStr(char* buffer, uint64_t* size); z_err_t ReadStr(char* buffer, uint64_t* size);
@ -23,7 +23,7 @@ class Channel {
~Channel() {} ~Channel() {}
private: private:
z_cap_t chan_cap_ = 0; uint64_t chan_cap_ = 0;
}; };
uint64_t CreateChannels(Channel& c1, Channel& c2); uint64_t CreateChannels(Channel& c1, Channel& c2);
@ -35,10 +35,9 @@ z_err_t Channel::WriteStruct(T* obj) {
template <typename T> template <typename T>
z_err_t Channel::ReadStructAndCap(T* obj, uint64_t* cap) { z_err_t Channel::ReadStructAndCap(T* obj, uint64_t* cap) {
uint64_t num_bytes = sizeof(T); uint64_t num_bytes, num_caps;
uint64_t num_caps = 1; uint64_t ret = ZChannelRecv(chan_cap_, sizeof(T), obj, /* num_caps= */ 1, cap,
uint64_t ret = ZChannelRecv(chan_cap_, &num_bytes, obj, &num_caps, cap); &num_bytes, &num_caps);
if (ret != Z_OK) { if (ret != Z_OK) {
return ret; return ret;
} }

View File

@ -18,5 +18,6 @@ class Port {
template <typename T> template <typename T>
z_err_t Port::WriteMessage(const T& obj, uint64_t cap) { z_err_t Port::WriteMessage(const T& obj, uint64_t cap) {
return ZPortSend(port_cap_, sizeof(obj), &obj, 1, &cap); return ZPortSend(port_cap_, sizeof(obj),
reinterpret_cast<const uint8_t*>(&obj), 1, &cap);
} }

View File

@ -23,32 +23,33 @@ void Channel::adopt_cap(uint64_t id) {
} }
chan_cap_ = id; chan_cap_ = id;
} }
z_cap_t Channel::release_cap() { uint64_t Channel::release_cap() {
z_cap_t cap = chan_cap_; uint64_t cap = chan_cap_;
chan_cap_ = 0; chan_cap_ = 0;
return cap; return cap;
} }
z_cap_t Channel::cap() { return chan_cap_; } uint64_t Channel::cap() { return chan_cap_; }
z_err_t Channel::WriteStr(const char* msg) { z_err_t Channel::WriteStr(const char* msg) {
if (!chan_cap_) { if (!chan_cap_) {
return Z_ERR_NULL; return Z_ERR_NULL;
} }
return ZChannelSend(chan_cap_, strlen(msg), msg, 0, nullptr); return ZChannelSend(chan_cap_, strlen(msg),
reinterpret_cast<const uint8_t*>(msg), 0, 0);
} }
z_err_t Channel::ReadStr(char* buffer, uint64_t* size) { z_err_t Channel::ReadStr(char* buffer, uint64_t* size) {
if (!chan_cap_) { if (!chan_cap_) {
return Z_ERR_NULL; return Z_ERR_NULL;
} }
uint64_t num_caps = 0; uint64_t num_caps;
return ZChannelRecv(chan_cap_, size, reinterpret_cast<uint8_t*>(buffer), return ZChannelRecv(chan_cap_, *size, reinterpret_cast<uint8_t*>(buffer), 0,
&num_caps, nullptr); 0, size, &num_caps);
} }
z_err_t CreateChannels(Channel& c1, Channel& c2) { z_err_t CreateChannels(Channel& c1, Channel& c2) {
z_cap_t chan1, chan2; uint64_t chan1, chan2;
z_err_t err = ZChannelCreate(&chan1, &chan2); z_err_t err = ZChannelCreate(&chan1, &chan2);
if (err != Z_OK) { if (err != Z_OK) {
return err; return err;

View File

@ -7,10 +7,10 @@
Port::Port(uint64_t port_cap) : port_cap_(port_cap) {} Port::Port(uint64_t port_cap) : port_cap_(port_cap) {}
z_err_t Port::PollForIntCap(uint64_t *msg, uint64_t *cap) { z_err_t Port::PollForIntCap(uint64_t *msg, uint64_t *cap) {
uint64_t bytes = sizeof(uint64_t); uint64_t bytes, caps;
uint64_t caps = 1; RET_ERR(ZPortPoll(port_cap_, sizeof(uint64_t),
RET_ERR(ZPortPoll(port_cap_, &bytes, reinterpret_cast<uint8_t *>(msg), &caps, reinterpret_cast<uint8_t *>(msg), /* num_caps= */ 1, cap,
cap)); &bytes, &caps));
if (bytes != sizeof(uint64_t)) { if (bytes != sizeof(uint64_t)) {
return Z_ERR_INVALID; return Z_ERR_INVALID;

View File

@ -141,7 +141,7 @@ void AhciDriver::InterruptLoop() {
dbgln("Starting interrupt loop"); dbgln("Starting interrupt loop");
while (true) { while (true) {
uint64_t bytes, caps; uint64_t bytes, caps;
check(ZPortRecv(irq_port_cap_, &bytes, nullptr, &caps, nullptr)); check(ZPortRecv(irq_port_cap_, 0, 0, 0, 0, &bytes, &caps));
for (uint64_t i = 0; i < 32; i++) { for (uint64_t i = 0; i < 32; i++) {
if (devices_[i] != nullptr && devices_[i]->IsInit() && if (devices_[i] != nullptr && devices_[i]->IsInit() &&
(ahci_hba_->interrupt_status & (1 << i))) { (ahci_hba_->interrupt_status & (1 << i))) {

View File

@ -19,8 +19,8 @@ z_err_t DenaliServer::RunServer() {
while (true) { while (true) {
uint64_t buff_size = kBuffSize; uint64_t buff_size = kBuffSize;
uint64_t cap_size = 0; uint64_t cap_size = 0;
RET_ERR(ZChannelRecv(channel_cap_, &buff_size, read_buffer_, &cap_size, RET_ERR(ZChannelRecv(channel_cap_, buff_size, read_buffer_, 0, nullptr,
nullptr)); &buff_size, &cap_size));
if (buff_size < sizeof(uint64_t)) { if (buff_size < sizeof(uint64_t)) {
dbgln("Skipping invalid message"); dbgln("Skipping invalid message");
continue; continue;

View File

@ -27,16 +27,8 @@ add_executable(zion
scheduler/jump_user_space.s scheduler/jump_user_space.s
scheduler/process_manager.cpp scheduler/process_manager.cpp
scheduler/scheduler.cpp scheduler/scheduler.cpp
syscall/address_space.cpp
syscall/capability.cpp
syscall/channel.cpp
syscall/debug.cpp
syscall/memory_object.cpp
syscall/port.cpp
syscall/process.cpp
syscall/syscall.cpp syscall/syscall.cpp
syscall/syscall_enter.s syscall/syscall_enter.s
syscall/thread.cpp
zion.cpp) zion.cpp)
target_include_directories(zion target_include_directories(zion

View File

@ -4,125 +4,58 @@
#include "ztypes.h" #include "ztypes.h"
#define SYS0(name) \ void ZProcessExit(uint64_t code);
struct Z##name##Req {}; \
[[nodiscard]] inline z_err_t Z##name() { \
Z##name##Req req{}; \
return SysCall1(kZion##name, &req); \
}
#define SYS1(name, t1, a1) \ [[nodiscard]] z_err_t ZProcessSpawn(z_cap_t proc_cap, z_cap_t bootstrap_cap,
struct Z##name##Req { \ z_cap_t* new_proc_cap,
t1 a1; \ z_cap_t* new_vmas_cap,
}; \ z_cap_t* new_bootstrap_cap);
[[nodiscard]] inline z_err_t Z##name(t1 a1) { \
Z##name##Req req{ \
.a1 = a1, \
}; \
return SysCall1(kZion##name, &req); \
}
#define SYS2(name, t1, a1, t2, a2) \ // UNUSED for now, I think we can get away with just starting a thread.
struct Z##name##Req { \ [[nodiscard]] z_err_t ZProcessStart(z_cap_t proc_cap, z_cap_t thread_cap,
t1 a1; \ uint64_t entry, uint64_t arg1,
t2 a2; \ uint64_t arg2);
}; \
[[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2) { \
Z##name##Req req{ \
.a1 = a1, \
.a2 = a2, \
}; \
return SysCall1(kZion##name, &req); \
}
#define SYS3(name, t1, a1, t2, a2, t3, a3) \ [[nodiscard]] z_err_t ZThreadCreate(z_cap_t proc_cap, z_cap_t* thread_cap);
struct Z##name##Req { \
t1 a1; \
t2 a2; \
t3 a3; \
}; \
[[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2, t3 a3) { \
Z##name##Req req{ \
.a1 = a1, \
.a2 = a2, \
.a3 = a3, \
}; \
return SysCall1(kZion##name, &req); \
}
#define SYS4(name, t1, a1, t2, a2, t3, a3, t4, a4) \ [[nodiscard]] z_err_t ZThreadStart(z_cap_t thread_cap, uint64_t entry,
struct Z##name##Req { \ uint64_t arg1, uint64_t arg2);
t1 a1; \
t2 a2; \
t3 a3; \
t4 a4; \
}; \
[[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2, t3 a3, t4 a4) { \
Z##name##Req req{ \
.a1 = a1, \
.a2 = a2, \
.a3 = a3, \
.a4 = a4, \
}; \
return SysCall1(kZion##name, &req); \
}
#define SYS5(name, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \ void ZThreadExit();
struct Z##name##Req { \
t1 a1; \
t2 a2; \
t3 a3; \
t4 a4; \
t5 a5; \
}; \
[[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) { \
Z##name##Req req{ \
.a1 = a1, \
.a2 = a2, \
.a3 = a3, \
.a4 = a4, \
.a5 = a5, \
}; \
return SysCall1(kZion##name, &req); \
}
z_err_t SysCall1(uint64_t code, const void* req); [[nodiscard]] z_err_t ZAddressSpaceMap(z_cap_t vmas_cap, uint64_t vmas_offset,
z_cap_t vmmo_cap, uint64_t* vaddr);
[[nodiscard]] z_err_t ZMemoryObjectCreate(uint64_t size, z_cap_t* vmmo_cap);
[[nodiscard]] z_err_t ZMemoryObjectCreatePhysical(uint64_t paddr, uint64_t size,
z_cap_t* vmmo_cap);
[[nodiscard]] z_err_t ZMemoryObjectCreateContiguous(uint64_t size,
z_cap_t* vmmo_cap,
uint64_t* paddr);
SYS1(ProcessExit, uint64_t, code); [[nodiscard]] z_err_t ZTempPcieConfigObjectCreate(z_cap_t* vmmo_cap,
SYS5(ProcessSpawn, z_cap_t, proc_cap, z_cap_t, bootstrap_cap, z_cap_t*, uint64_t* vmmo_size);
new_proc_cap, z_cap_t*, new_vmas_cap, z_cap_t*, new_bootstrap_cap);
SYS2(ThreadCreate, z_cap_t, proc_cap, z_cap_t*, thread_cap); [[nodiscard]] z_err_t ZChannelCreate(z_cap_t* channel1, z_cap_t* channel2);
SYS4(ThreadStart, z_cap_t, thread_cap, uint64_t, entry, uint64_t, arg1, [[nodiscard]] z_err_t ZChannelSend(z_cap_t chan_cap, uint64_t num_bytes,
uint64_t, arg2); const void* data, uint64_t num_caps,
SYS0(ThreadExit); const z_cap_t* caps);
[[nodiscard]] z_err_t ZChannelRecv(z_cap_t chan_cap, uint64_t num_bytes,
void* data, uint64_t num_caps, z_cap_t* caps,
uint64_t* actual_bytes,
uint64_t* actual_caps);
SYS4(AddressSpaceMap, z_cap_t, vmas_cap, uint64_t, vmas_offset, z_cap_t, [[nodiscard]] z_err_t ZPortCreate(z_cap_t* port_cap);
vmmo_cap, uint64_t*, vaddr); [[nodiscard]] z_err_t ZPortSend(z_cap_t port_cap, uint64_t num_bytes,
const void* data, uint64_t num_caps,
z_cap_t* caps);
[[nodiscard]] z_err_t ZPortRecv(z_cap_t port_cap, uint64_t num_bytes,
void* data, uint64_t num_caps, z_cap_t* caps,
uint64_t* actual_bytes, uint64_t* actual_caps);
[[nodiscard]] z_err_t ZPortPoll(z_cap_t port_cap, uint64_t num_bytes,
void* data, uint64_t num_caps, z_cap_t* caps,
uint64_t* actual_bytes, uint64_t* actual_caps);
[[nodiscard]] z_err_t ZIrqRegister(uint64_t irq_num, z_cap_t* port_cap);
SYS2(MemoryObjectCreate, uint64_t, size, z_cap_t*, vmmo_cap); [[nodiscard]] z_err_t ZCapDuplicate(z_cap_t cap_in, z_cap_t* cap_out);
SYS3(MemoryObjectCreatePhysical, uint64_t, paddr, uint64_t, size, z_cap_t*,
vmmo_cap);
SYS3(MemoryObjectCreateContiguous, uint64_t, size, z_cap_t*, vmmo_cap,
uint64_t*, paddr);
SYS2(TempPcieConfigObjectCreate, z_cap_t*, vmmo_cap, uint64_t*, vmmo_size);
SYS2(ChannelCreate, z_cap_t*, channel1, z_cap_t*, channel2); [[nodiscard]] z_err_t ZDebug(const char* message);
SYS5(ChannelSend, z_cap_t, chan_cap, uint64_t, num_bytes, const void*, data,
uint64_t, num_caps, z_cap_t*, caps);
SYS5(ChannelRecv, z_cap_t, chan_cap, uint64_t*, num_bytes, void*, data,
uint64_t*, num_caps, z_cap_t*, caps);
SYS1(PortCreate, z_cap_t*, port_cap);
SYS5(PortSend, z_cap_t, port_cap, uint64_t, num_bytes, const void*, data,
uint64_t, num_caps, z_cap_t*, caps);
SYS5(PortRecv, z_cap_t, port_cap, uint64_t*, num_bytes, void*, data, uint64_t*,
num_caps, z_cap_t*, caps);
SYS5(PortPoll, z_cap_t, port_cap, uint64_t*, num_bytes, void*, data, uint64_t*,
num_caps, z_cap_t*, caps);
SYS2(IrqRegister, uint64_t, irq_num, z_cap_t*, port_cap);
SYS2(CapDuplicate, z_cap_t, cap_in, z_cap_t*, cap_out);
SYS1(Debug, const char*, message);

View File

@ -30,44 +30,44 @@ typedef uint64_t z_err_t;
* ------------------------------*/ * ------------------------------*/
// Process Calls. // Process Calls.
const uint64_t kZionProcessExit = 0x1; #define Z_PROCESS_EXIT 0x01
const uint64_t kZionProcessSpawn = 0x2; #define Z_PROCESS_SPAWN 0x02
#define Z_PROCESS_START 0x03
// Thread Calls. // Thread Calls.
const uint64_t kZionThreadCreate = 0x10; #define Z_THREAD_CREATE 0x10
const uint64_t kZionThreadStart = 0x11; #define Z_THREAD_START 0x11
const uint64_t kZionThreadExit = 0x12; #define Z_THREAD_EXIT 0x12
// Memory Calls // Memory Calls
const uint64_t kZionAddressSpaceMap = 0x21; #define Z_ADDRESS_SPACE_MAP 0x21
const uint64_t kZionAddressSpaceUnMap = 0x21; #define Z_ADDRESS_SPACE_UNMAP 0x22
const uint64_t kZionMemoryObjectCreate = 0x30; #define Z_MEMORY_OBJECT_CREATE 0x30
const uint64_t kZionMemoryObjectCreatePhysical = 0x31; #define Z_MEMORY_OBJECT_CREATE_PHYSICAL 0x31
const uint64_t kZionMemoryObjectCreateContiguous = 0x32;
const uint64_t kZionTempPcieConfigObjectCreate = 0x3F; #define Z_TEMP_PCIE_CONFIG_OBJECT_CREATE 0x3F
// IPC Calls // IPC Calls
const uint64_t kZionChannelCreate = 0x40; #define Z_CHANNEL_CREATE 0x40
const uint64_t kZionChannelSend = 0x41; #define Z_CHANNEL_SEND 0x41
const uint64_t kZionChannelRecv = 0x42; #define Z_CHANNEL_RECV 0x42
const uint64_t kZionChannelSendRecv = 0x43; #define Z_CHANNEL_SENDRECV 0x43
const uint64_t kZionPortCreate = 0x50; #define Z_PORT_CREATE 0x50
const uint64_t kZionPortSend = 0x51; #define Z_PORT_SEND 0x51
const uint64_t kZionPortRecv = 0x52; #define Z_PORT_RECV 0x52
const uint64_t kZionPortPoll = 0x53; #define Z_PORT_POLL 0x53
const uint64_t kZionIrqRegister = 0x58; #define Z_IRQ_REGISTER 0x58
#define Z_IRQ_PCI_BASE 0x30 #define Z_IRQ_PCI_BASE 0x30
// Capability Calls // Capability Calls
const uint64_t kZionCapDuplicate = 0x70; #define Z_CAP_DUPLICATE 0x60
// Debugging Calls. // Debugging Calls.
const uint64_t kZionDebug = 0x1'0000; #define Z_DEBUG_PRINT 0x10000000
/* ------------------------------ /* ------------------------------
* Capability Types * Capability Types

View File

@ -1,26 +0,0 @@
#include "syscall/address_space.h"
#include "scheduler/scheduler.h"
#include "syscall/syscall.h"
z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
auto vmas_cap = curr_proc.GetCapability(req->vmas_cap);
auto vmmo_cap = curr_proc.GetCapability(req->vmmo_cap);
RET_ERR(ValidateCap(vmas_cap, ZC_WRITE));
RET_ERR(ValidateCap(vmmo_cap, ZC_WRITE));
auto vmas = vmas_cap->obj<AddressSpace>();
auto vmmo = vmmo_cap->obj<MemoryObject>();
RET_IF_NULL(vmas);
RET_IF_NULL(vmmo);
// FIXME: Validation necessary.
if (req->vmas_offset != 0) {
vmas->MapInMemoryObject(req->vmas_offset, vmmo);
*req->vaddr = req->vmas_offset;
} else {
*req->vaddr = vmas->MapInMemoryObject(vmmo);
}
return Z_OK;
}

View File

@ -1,5 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req);

View File

@ -1,13 +0,0 @@
#include "syscall/capability.h"
#include "scheduler/scheduler.h"
z_err_t CapDuplicate(ZCapDuplicateReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto cap = proc.GetCapability(req->cap_in);
if (!cap) {
return Z_ERR_CAP_NOT_FOUND;
}
*req->cap_out = proc.AddExistingCapability(cap);
return Z_OK;
}

View File

@ -1,5 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t CapDuplicate(ZCapDuplicateReq* req);

View File

@ -1,52 +0,0 @@
#include "syscall/channel.h"
#include "scheduler/scheduler.h"
#include "syscall/syscall.h"
z_err_t ChannelCreate(ZChannelCreateReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto chan_pair = Channel::CreateChannelPair();
*req->channel1 = proc.AddNewCapability(chan_pair.first(), ZC_WRITE | ZC_READ);
*req->channel2 =
proc.AddNewCapability(chan_pair.second(), ZC_WRITE | ZC_READ);
return Z_OK;
}
z_err_t ChannelSend(ZChannelSendReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto chan_cap = proc.GetCapability(req->chan_cap);
RET_ERR(ValidateCap(chan_cap, ZC_WRITE));
auto chan = chan_cap->obj<Channel>();
RET_IF_NULL(chan);
// FIXME: Get rid of this hack.
ZMessage message{
.num_bytes = req->num_bytes,
.data = const_cast<void*>(req->data),
.num_caps = req->num_caps,
.caps = req->caps,
};
return chan->Write(message);
}
z_err_t ChannelRecv(ZChannelRecvReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto chan_cap = proc.GetCapability(req->chan_cap);
RET_ERR(ValidateCap(chan_cap, ZC_READ));
auto chan = chan_cap->obj<Channel>();
RET_IF_NULL(chan);
// FIXME: Get rid of this hack.
ZMessage message{
.num_bytes = *req->num_bytes,
.data = const_cast<void*>(req->data),
.num_caps = *req->num_caps,
.caps = req->caps,
};
RET_ERR(chan->Read(message));
*req->num_bytes = message.num_bytes;
*req->num_caps = message.num_caps;
return Z_OK;
}

View File

@ -1,7 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t ChannelCreate(ZChannelCreateReq* resp);
z_err_t ChannelSend(ZChannelSendReq* req);
z_err_t ChannelRecv(ZChannelRecvReq* req);

View File

@ -1,8 +0,0 @@
#include "syscall/debug.h"
#include "debug/debug.h"
z_err_t Debug(ZDebugReq* req) {
dbgln("[Debug] %s", req->message);
return Z_OK;
}

View File

@ -1,5 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t Debug(ZDebugReq* req);

View File

@ -1,42 +0,0 @@
#include "syscall/memory_object.h"
#include "boot/acpi.h"
#include "memory/physical_memory.h"
#include "scheduler/scheduler.h"
z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
*req->vmmo_cap = curr_proc.AddNewCapability(
MakeRefCounted<MemoryObject>(req->size), ZC_WRITE);
return Z_OK;
}
z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
uint64_t paddr = req->paddr;
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(paddr, req->size);
*req->vmmo_cap = curr_proc.AddNewCapability(
StaticCastRefPtr<MemoryObject>(vmmo_ref), ZC_WRITE);
return Z_OK;
}
z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
uint64_t paddr = phys_mem::AllocateContinuous(((req->size - 1) / 0x1000) + 1);
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(paddr, req->size);
*req->vmmo_cap = curr_proc.AddNewCapability(
StaticCastRefPtr<MemoryObject>(vmmo_ref), ZC_WRITE);
*req->paddr = paddr;
return Z_OK;
}
z_err_t TempPcieConfigObjectCreate(ZTempPcieConfigObjectCreateReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
uint64_t pci_base, pci_size;
RET_ERR(GetPciExtendedConfiguration(&pci_base, &pci_size));
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(pci_base, pci_size);
*req->vmmo_cap = curr_proc.AddNewCapability(
StaticCastRefPtr<MemoryObject>(vmmo_ref), ZC_WRITE);
*req->vmmo_size = pci_size;
return Z_OK;
}

View File

@ -1,8 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req);
z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req);
z_err_t MemoryObjectCreateContiguous(ZMemoryObjectCreateContiguousReq* req);
z_err_t TempPcieConfigObjectCreate(ZTempPcieConfigObjectCreateReq* req);

View File

@ -1,81 +0,0 @@
#include "syscall/port.h"
#include "interrupt/interrupt.h"
#include "scheduler/scheduler.h"
#include "syscall/syscall.h"
z_err_t PortCreate(ZPortCreateReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto port = MakeRefCounted<Port>();
*req->port_cap = proc.AddNewCapability(port, ZC_WRITE | ZC_READ);
return Z_OK;
}
z_err_t PortSend(ZPortSendReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto port_cap = proc.GetCapability(req->port_cap);
RET_ERR(ValidateCap(port_cap, ZC_WRITE));
auto port = port_cap->obj<Port>();
RET_IF_NULL(port);
ZMessage message{
.num_bytes = req->num_bytes,
.data = const_cast<void*>(req->data),
.num_caps = req->num_caps,
.caps = req->caps,
};
return port->Write(message);
}
z_err_t PortRecv(ZPortRecvReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto port_cap = proc.GetCapability(req->port_cap);
RET_ERR(ValidateCap(port_cap, ZC_READ));
auto port = port_cap->obj<Port>();
RET_IF_NULL(port);
ZMessage message{
.num_bytes = *req->num_bytes,
.data = const_cast<void*>(req->data),
.num_caps = *req->num_caps,
.caps = req->caps,
};
RET_ERR(port->Read(message));
*req->num_bytes = message.num_bytes;
*req->num_caps = message.num_caps;
return Z_OK;
}
z_err_t PortPoll(ZPortPollReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto port_cap = proc.GetCapability(req->port_cap);
RET_ERR(ValidateCap(port_cap, ZC_READ));
auto port = port_cap->obj<Port>();
RET_IF_NULL(port);
if (!port->HasMessages()) {
return Z_ERR_EMPTY;
}
ZMessage message{
.num_bytes = *req->num_bytes,
.data = const_cast<void*>(req->data),
.num_caps = *req->num_caps,
.caps = req->caps,
};
RET_ERR(port->Read(message));
*req->num_bytes = message.num_bytes;
*req->num_caps = message.num_caps;
return Z_OK;
}
z_err_t IrqRegister(ZIrqRegisterReq* req) {
auto& proc = gScheduler->CurrentProcess();
if (req->irq_num != Z_IRQ_PCI_BASE) {
// FIXME: Don't hardcode this nonsense.
return Z_ERR_UNIMPLEMENTED;
}
RefPtr<Port> port = MakeRefCounted<Port>();
*req->port_cap = proc.AddNewCapability(port, ZC_READ | ZC_WRITE);
RegisterPciPort(port);
return Z_OK;
}

View File

@ -1,9 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t PortCreate(ZPortCreateReq* req);
z_err_t PortSend(ZPortSendReq* req);
z_err_t PortRecv(ZPortRecvReq* req);
z_err_t PortPoll(ZPortPollReq* req);
z_err_t IrqRegister(ZIrqRegisterReq* req);

View File

@ -1,38 +0,0 @@
#include "syscall/process.h"
#include "scheduler/process_manager.h"
#include "scheduler/scheduler.h"
#include "syscall/syscall.h"
z_err_t ProcessExit(ZProcessExitReq* req) {
auto curr_thread = gScheduler->CurrentThread();
dbgln("Exit code: %x", req->code);
// FIXME: kill process here.
curr_thread->Exit();
panic("Returned from thread exit");
return Z_ERR_UNIMPLEMENTED;
}
z_err_t ProcessSpawn(ZProcessSpawnReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->proc_cap);
RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_PROC));
RefPtr<Process> proc = Process::Create();
gProcMan->InsertProcess(proc);
*req->new_proc_cap = curr_proc.AddNewCapability(
proc, ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD | ZC_WRITE);
*req->new_vmas_cap = curr_proc.AddNewCapability(proc->vmas(), ZC_WRITE);
if (req->bootstrap_cap != 0) {
auto cap = curr_proc.ReleaseCapability(req->bootstrap_cap);
if (!cap) {
return Z_ERR_CAP_NOT_FOUND;
}
// FIXME: Check permissions.
*req->new_bootstrap_cap = proc->AddExistingCapability(cap);
}
return Z_OK;
}

View File

@ -1,6 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t ProcessExit(ZProcessExitReq* req);
z_err_t ProcessSpawn(ZProcessSpawnReq* req);

View File

@ -2,6 +2,7 @@
#include <stdint.h> #include <stdint.h>
#include "boot/acpi.h"
#include "common/msr.h" #include "common/msr.h"
#include "debug/debug.h" #include "debug/debug.h"
#include "include/zcall.h" #include "include/zcall.h"
@ -12,16 +13,15 @@
#include "object/process.h" #include "object/process.h"
#include "scheduler/process_manager.h" #include "scheduler/process_manager.h"
#include "scheduler/scheduler.h" #include "scheduler/scheduler.h"
#include "syscall/address_space.h"
#include "syscall/capability.h"
#include "syscall/channel.h"
#include "syscall/debug.h"
#include "syscall/memory_object.h"
#include "syscall/port.h"
#include "syscall/process.h"
#include "syscall/thread.h"
#include "usr/zcall_internal.h" #include "usr/zcall_internal.h"
#define RET_IF_NULL(expr) \
{ \
if (!expr) { \
return Z_ERR_CAP_TYPE; \
} \
}
#define EFER 0xC0000080 #define EFER 0xC0000080
#define STAR 0xC0000081 #define STAR 0xC0000081
#define LSTAR 0xC0000082 #define LSTAR 0xC0000082
@ -65,41 +65,263 @@ z_err_t ValidateCap(const RefPtr<Capability>& cap, uint64_t permissions) {
return Z_OK; return Z_OK;
} }
#define CASE(name) \ z_err_t ProcessSpawn(ZProcessSpawnReq* req, ZProcessSpawnResp* resp) {
case kZion##name: \ auto& curr_proc = gScheduler->CurrentProcess();
return name(reinterpret_cast<Z##name##Req*>(req)); auto cap = curr_proc.GetCapability(req->proc_cap);
RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_PROC));
RefPtr<Process> proc = Process::Create();
gProcMan->InsertProcess(proc);
resp->proc_cap = curr_proc.AddNewCapability(
proc, ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD | ZC_WRITE);
resp->vmas_cap = curr_proc.AddNewCapability(proc->vmas(), ZC_WRITE);
if (req->bootstrap_cap != 0) {
auto cap = curr_proc.ReleaseCapability(req->bootstrap_cap);
if (!cap) {
return Z_ERR_CAP_NOT_FOUND;
}
// FIXME: Check permissions.
resp->bootstrap_cap = proc->AddExistingCapability(cap);
}
return Z_OK;
}
z_err_t ThreadCreate(ZThreadCreateReq* req, ZThreadCreateResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->proc_cap);
RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_THREAD));
auto parent_proc = cap->obj<Process>();
RET_IF_NULL(parent_proc);
auto thread = parent_proc->CreateThread();
resp->thread_cap = curr_proc.AddNewCapability(thread, ZC_WRITE);
return Z_OK;
}
z_err_t ThreadStart(ZThreadStartReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->thread_cap);
RET_ERR(ValidateCap(cap, ZC_WRITE));
auto thread = cap->obj<Thread>();
RET_IF_NULL(thread);
// FIXME: validate entry point is in user space.
thread->Start(req->entry, req->arg1, req->arg2);
return Z_OK;
}
z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req, ZAddressSpaceMapResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess();
auto vmas_cap = curr_proc.GetCapability(req->vmas_cap);
auto vmmo_cap = curr_proc.GetCapability(req->vmmo_cap);
RET_ERR(ValidateCap(vmas_cap, ZC_WRITE));
RET_ERR(ValidateCap(vmmo_cap, ZC_WRITE));
auto vmas = vmas_cap->obj<AddressSpace>();
auto vmmo = vmmo_cap->obj<MemoryObject>();
RET_IF_NULL(vmas);
RET_IF_NULL(vmmo);
// FIXME: Validation necessary.
if (req->vmas_offset != 0) {
vmas->MapInMemoryObject(req->vmas_offset, vmmo);
resp->vaddr = req->vmas_offset;
} else {
resp->vaddr = vmas->MapInMemoryObject(vmmo);
}
return Z_OK;
}
z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req,
ZMemoryObjectCreateResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess();
resp->vmmo_cap = curr_proc.AddNewCapability(
MakeRefCounted<MemoryObject>(req->size), ZC_WRITE);
return Z_OK;
}
z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req,
ZMemoryObjectCreatePhysicalResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess();
uint64_t paddr = req->paddr;
if (paddr == 0) {
paddr = phys_mem::AllocateContinuous(((req->size - 1) / 0x1000) + 1);
}
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(paddr, req->size);
resp->vmmo_cap = curr_proc.AddNewCapability(
StaticCastRefPtr<MemoryObject>(vmmo_ref), ZC_WRITE);
resp->paddr = paddr;
return Z_OK;
}
z_err_t TempPcieConfigObjectCreate(ZTempPcieConfigObjectCreateResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess();
uint64_t pci_base, pci_size;
RET_ERR(GetPciExtendedConfiguration(&pci_base, &pci_size));
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(pci_base, pci_size);
resp->vmmo_cap = curr_proc.AddNewCapability(
StaticCastRefPtr<MemoryObject>(vmmo_ref), ZC_WRITE);
resp->vmmo_size = pci_size;
return Z_OK;
}
z_err_t ChannelCreate(ZChannelCreateResp* resp) {
auto& proc = gScheduler->CurrentProcess();
auto chan_pair = Channel::CreateChannelPair();
resp->chan_cap1 =
proc.AddNewCapability(chan_pair.first(), ZC_WRITE | ZC_READ);
resp->chan_cap2 =
proc.AddNewCapability(chan_pair.second(), ZC_WRITE | ZC_READ);
return Z_OK;
}
z_err_t ChannelSend(ZChannelSendReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto chan_cap = proc.GetCapability(req->chan_cap);
RET_ERR(ValidateCap(chan_cap, ZC_WRITE));
auto chan = chan_cap->obj<Channel>();
RET_IF_NULL(chan);
chan->Write(req->message);
return Z_OK;
}
z_err_t ChannelRecv(ZChannelRecvReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto chan_cap = proc.GetCapability(req->chan_cap);
RET_ERR(ValidateCap(chan_cap, ZC_READ));
auto chan = chan_cap->obj<Channel>();
RET_IF_NULL(chan);
return chan->Read(req->message);
}
z_err_t PortCreate(ZPortCreateResp* resp) {
auto& proc = gScheduler->CurrentProcess();
auto port = MakeRefCounted<Port>();
resp->port_cap = proc.AddNewCapability(port, ZC_WRITE | ZC_READ);
return Z_OK;
}
z_err_t PortSend(ZPortSendReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto port_cap = proc.GetCapability(req->port_cap);
RET_ERR(ValidateCap(port_cap, ZC_WRITE));
auto port = port_cap->obj<Port>();
RET_IF_NULL(port);
return port->Write(req->message);
}
z_err_t PortRecv(ZPortRecvReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto port_cap = proc.GetCapability(req->port_cap);
RET_ERR(ValidateCap(port_cap, ZC_READ));
auto port = port_cap->obj<Port>();
RET_IF_NULL(port);
return port->Read(req->message);
}
z_err_t PortPoll(ZPortRecvReq* req) {
auto& proc = gScheduler->CurrentProcess();
auto port_cap = proc.GetCapability(req->port_cap);
RET_ERR(ValidateCap(port_cap, ZC_READ));
auto port = port_cap->obj<Port>();
RET_IF_NULL(port);
if (!port->HasMessages()) {
return Z_ERR_EMPTY;
}
return port->Read(req->message);
}
z_err_t IrqRegister(ZIrqRegisterReq* req, ZIrqRegisterResp* resp) {
auto& proc = gScheduler->CurrentProcess();
if (req->irq_num != Z_IRQ_PCI_BASE) {
// FIXME: Don't hardcode this nonsense.
return Z_ERR_UNIMPLEMENTED;
}
RefPtr<Port> port = MakeRefCounted<Port>();
resp->port_cap = proc.AddNewCapability(port, ZC_READ | ZC_WRITE);
RegisterPciPort(port);
return Z_OK;
}
z_err_t CapDuplicate(ZCapDuplicateReq* req, ZCapDuplicateResp* resp) {
auto& proc = gScheduler->CurrentProcess();
auto cap = proc.GetCapability(req->cap);
if (!cap) {
return Z_ERR_CAP_NOT_FOUND;
}
resp->cap = proc.AddExistingCapability(cap);
return Z_OK;
}
extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) { extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) {
RefPtr<Thread> thread = gScheduler->CurrentThread(); RefPtr<Thread> thread = gScheduler->CurrentThread();
switch (call_id) { switch (call_id) {
// syscall/process.h case Z_PROCESS_EXIT:
CASE(ProcessExit); // FIXME: kill process here.
CASE(ProcessSpawn); dbgln("Exit code: %x", req);
// syscall/thread.h thread->Exit();
CASE(ThreadCreate); panic("Returned from thread exit");
CASE(ThreadStart); break;
CASE(ThreadExit); case Z_PROCESS_SPAWN:
// syscall/address_space.h return ProcessSpawn(reinterpret_cast<ZProcessSpawnReq*>(req),
CASE(AddressSpaceMap); reinterpret_cast<ZProcessSpawnResp*>(resp));
// syscall/memory_object.h case Z_THREAD_CREATE:
CASE(MemoryObjectCreate); return ThreadCreate(reinterpret_cast<ZThreadCreateReq*>(req),
CASE(MemoryObjectCreatePhysical); reinterpret_cast<ZThreadCreateResp*>(resp));
CASE(MemoryObjectCreateContiguous); case Z_THREAD_START:
CASE(TempPcieConfigObjectCreate); return ThreadStart(reinterpret_cast<ZThreadStartReq*>(req));
// syscall/channel.h case Z_THREAD_EXIT:
CASE(ChannelCreate); thread->Exit();
CASE(ChannelSend); panic("Returned from thread exit");
CASE(ChannelRecv); break;
// syscall/port.h
CASE(PortCreate); case Z_ADDRESS_SPACE_MAP:
CASE(PortSend); return AddressSpaceMap(reinterpret_cast<ZAddressSpaceMapReq*>(req),
CASE(PortRecv); reinterpret_cast<ZAddressSpaceMapResp*>(resp));
CASE(PortPoll); case Z_MEMORY_OBJECT_CREATE:
CASE(IrqRegister); return MemoryObjectCreate(
// syscall/capability.h reinterpret_cast<ZMemoryObjectCreateReq*>(req),
CASE(CapDuplicate); reinterpret_cast<ZMemoryObjectCreateResp*>(resp));
// syscall/debug.h case Z_MEMORY_OBJECT_CREATE_PHYSICAL:
CASE(Debug); return MemoryObjectCreatePhysical(
reinterpret_cast<ZMemoryObjectCreatePhysicalReq*>(req),
reinterpret_cast<ZMemoryObjectCreatePhysicalResp*>(resp));
case Z_TEMP_PCIE_CONFIG_OBJECT_CREATE:
return TempPcieConfigObjectCreate(
reinterpret_cast<ZTempPcieConfigObjectCreateResp*>(resp));
case Z_CHANNEL_CREATE:
return ChannelCreate(reinterpret_cast<ZChannelCreateResp*>(resp));
case Z_CHANNEL_SEND:
return ChannelSend(reinterpret_cast<ZChannelSendReq*>(req));
case Z_CHANNEL_RECV:
return ChannelRecv(reinterpret_cast<ZChannelRecvReq*>(req));
case Z_PORT_CREATE:
return PortCreate(reinterpret_cast<ZPortCreateResp*>(resp));
case Z_PORT_SEND:
return PortSend(reinterpret_cast<ZPortSendReq*>(req));
case Z_PORT_RECV:
return PortRecv(reinterpret_cast<ZPortRecvReq*>(req));
case Z_PORT_POLL:
return PortPoll(reinterpret_cast<ZPortRecvReq*>(req));
case Z_IRQ_REGISTER:
return IrqRegister(reinterpret_cast<ZIrqRegisterReq*>(req),
reinterpret_cast<ZIrqRegisterResp*>(resp));
case Z_CAP_DUPLICATE:
return CapDuplicate(reinterpret_cast<ZCapDuplicateReq*>(req),
reinterpret_cast<ZCapDuplicateResp*>(resp));
case Z_DEBUG_PRINT:
dbgln("[Debug] %s", req);
return Z_OK;
break;
default: default:
panic("Unhandled syscall number: %x", call_id); panic("Unhandled syscall number: %x", call_id);
} }

View File

@ -1,16 +1,3 @@
#pragma once #pragma once
#include "capability/capability.h"
#include "include/ztypes.h"
void InitSyscall(); void InitSyscall();
// FIXME: This probably belongs in capability.h
z_err_t ValidateCap(const RefPtr<Capability>& cap, uint64_t permissions);
#define RET_IF_NULL(expr) \
{ \
if (!expr) { \
return Z_ERR_CAP_TYPE; \
} \
}

View File

@ -1,34 +0,0 @@
#include "syscall/thread.h"
#include "scheduler/scheduler.h"
#include "syscall/syscall.h"
z_err_t ThreadCreate(ZThreadCreateReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->proc_cap);
RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_THREAD));
auto parent_proc = cap->obj<Process>();
RET_IF_NULL(parent_proc);
auto thread = parent_proc->CreateThread();
*req->thread_cap = curr_proc.AddNewCapability(thread, ZC_WRITE);
return Z_OK;
}
z_err_t ThreadStart(ZThreadStartReq* req) {
auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->thread_cap);
RET_ERR(ValidateCap(cap, ZC_WRITE));
auto thread = cap->obj<Thread>();
RET_IF_NULL(thread);
// FIXME: validate entry point is in user space.
thread->Start(req->entry, req->arg1, req->arg2);
return Z_OK;
}
z_err_t ThreadExit(ZThreadExitReq*) {
auto curr_thread = gScheduler->CurrentThread();
curr_thread->Exit();
panic("Returned from thread exit");
}

View File

@ -1,7 +0,0 @@
#pragma once
#include "include/zcall.h"
z_err_t ThreadCreate(ZThreadCreateReq* req);
z_err_t ThreadStart(ZThreadStartReq* req);
z_err_t ThreadExit(ZThreadExitReq*);

View File

@ -8,7 +8,6 @@ _start:
_exit: _exit:
// EXIT syscall. // EXIT syscall.
mov $1, %rdi mov $1, %rdi
// Return code as a "struct" on the stack. // Return code as a param.
push %rax mov %rax, %rsi
mov %rsp, %rsi
syscall syscall

View File

@ -4,8 +4,236 @@
#include "usr/zcall_internal.h" #include "usr/zcall_internal.h"
z_err_t SysCall1(uint64_t number, const void* first) { z_err_t SysCall2(uint64_t number, const void* first, const void* second) {
z_err_t return_code; z_err_t return_code;
asm("syscall" : "=a"(return_code) : "D"(number), "S"(first) : "rcx", "r11"); asm("syscall"
: "=a"(return_code)
: "D"(number), "S"(first), "d"(second)
: "rcx", "r11");
return return_code; return return_code;
} }
z_err_t SysCall0(uint64_t number) { return SysCall2(number, 0, 0); }
z_err_t SysCall1(uint64_t number, const void* first) {
return SysCall2(number, first, 0);
}
void ZProcessExit(uint64_t code) {
SysCall1(Z_PROCESS_EXIT, reinterpret_cast<void*>(code));
}
z_err_t ZProcessSpawn(z_cap_t proc_cap, z_cap_t bootstrap_cap,
z_cap_t* new_proc_cap, z_cap_t* new_vmas_cap,
z_cap_t* new_bootstrap_cap) {
ZProcessSpawnReq req{
.proc_cap = proc_cap,
.bootstrap_cap = bootstrap_cap,
};
ZProcessSpawnResp resp;
z_err_t ret = SysCall2(Z_PROCESS_SPAWN, &req, &resp);
*new_proc_cap = resp.proc_cap;
*new_vmas_cap = resp.vmas_cap;
*new_bootstrap_cap = resp.bootstrap_cap;
return ret;
}
z_err_t ZThreadCreate(z_cap_t proc_cap, z_cap_t* thread_cap) {
ZThreadCreateReq req{
.proc_cap = proc_cap,
};
ZThreadCreateResp resp;
z_err_t ret = SysCall2(Z_THREAD_CREATE, &req, &resp);
*thread_cap = resp.thread_cap;
return ret;
}
z_err_t ZThreadStart(z_cap_t thread_cap, uint64_t entry, uint64_t arg1,
uint64_t arg2) {
ZThreadStartReq req{
.thread_cap = thread_cap,
.entry = entry,
.arg1 = arg1,
.arg2 = arg2,
};
return SysCall1(Z_THREAD_START, &req);
}
void ZThreadExit() { SysCall0(Z_THREAD_EXIT); }
z_err_t ZAddressSpaceMap(z_cap_t vmas_cap, uint64_t vmas_offset,
z_cap_t vmmo_cap, uint64_t* vaddr) {
ZAddressSpaceMapReq req{
.vmas_cap = vmas_cap,
.vmas_offset = vmas_offset,
.vmmo_cap = vmmo_cap,
};
ZAddressSpaceMapResp resp;
z_err_t ret = SysCall2(Z_ADDRESS_SPACE_MAP, &req, &resp);
*vaddr = resp.vaddr;
return ret;
}
z_err_t ZMemoryObjectCreate(uint64_t size, z_cap_t* vmmo_cap) {
ZMemoryObjectCreateReq req{
.size = size,
};
ZMemoryObjectCreateResp resp;
z_err_t ret = SysCall2(Z_MEMORY_OBJECT_CREATE, &req, &resp);
*vmmo_cap = resp.vmmo_cap;
return ret;
}
z_err_t ZMemoryObjectCreatePhysical(uint64_t paddr, uint64_t size,
z_cap_t* vmmo_cap) {
ZMemoryObjectCreatePhysicalReq req{
.paddr = paddr,
.size = size,
};
ZMemoryObjectCreatePhysicalResp resp;
z_err_t ret = SysCall2(Z_MEMORY_OBJECT_CREATE_PHYSICAL, &req, &resp);
*vmmo_cap = resp.vmmo_cap;
return ret;
}
z_err_t ZMemoryObjectCreateContiguous(uint64_t size, z_cap_t* vmmo_cap,
uint64_t* paddr) {
ZMemoryObjectCreatePhysicalReq req{
.paddr = 0,
.size = size,
};
ZMemoryObjectCreatePhysicalResp resp;
z_err_t ret = SysCall2(Z_MEMORY_OBJECT_CREATE_PHYSICAL, &req, &resp);
*vmmo_cap = resp.vmmo_cap;
*paddr = resp.paddr;
return ret;
}
z_err_t ZTempPcieConfigObjectCreate(z_cap_t* vmmo_cap, uint64_t* vmmo_size) {
ZTempPcieConfigObjectCreateResp resp;
z_err_t ret = SysCall2(Z_TEMP_PCIE_CONFIG_OBJECT_CREATE, 0, &resp);
*vmmo_cap = resp.vmmo_cap;
*vmmo_size = resp.vmmo_size;
return ret;
}
z_err_t ZChannelCreate(z_cap_t* channel1, z_cap_t* channel2) {
ZChannelCreateResp resp;
z_err_t ret = SysCall2(Z_CHANNEL_CREATE, 0, &resp);
*channel1 = resp.chan_cap1;
*channel2 = resp.chan_cap2;
return ret;
}
z_err_t ZChannelSend(z_cap_t chan_cap, uint64_t num_bytes, const void* data,
uint64_t num_caps, const z_cap_t* caps) {
ZChannelSendReq req{
.chan_cap = chan_cap,
.message =
{
.num_bytes = num_bytes,
.data = const_cast<void*>(data),
.num_caps = num_caps,
.caps = const_cast<z_cap_t*>(caps),
},
};
return SysCall1(Z_CHANNEL_SEND, &req);
}
z_err_t ZChannelRecv(z_cap_t chan_cap, uint64_t num_bytes, void* data,
uint64_t num_caps, z_cap_t* caps, uint64_t* actual_bytes,
uint64_t* actual_caps) {
ZChannelRecvReq req{
.chan_cap = chan_cap,
.message =
{
.num_bytes = num_bytes,
.data = data,
.num_caps = num_caps,
.caps = caps,
},
};
z_err_t ret = SysCall1(Z_CHANNEL_RECV, &req);
*actual_bytes = req.message.num_bytes;
*actual_caps = req.message.num_caps;
return ret;
}
z_err_t ZPortCreate(z_cap_t* port_cap) {
ZPortCreateResp resp;
z_err_t ret = SysCall2(Z_PORT_CREATE, 0, &resp);
*port_cap = resp.port_cap;
return ret;
}
z_err_t ZPortSend(z_cap_t port_cap, uint64_t num_bytes, const void* data,
uint64_t num_caps, z_cap_t* caps) {
ZPortSendReq req{.port_cap = port_cap,
.message = {
.num_bytes = num_bytes,
.data = const_cast<void*>(data),
.num_caps = num_caps,
.caps = caps,
}};
return SysCall1(Z_PORT_SEND, &req);
}
z_err_t ZPortRecv(z_cap_t port_cap, uint64_t num_bytes, void* data,
uint64_t num_caps, z_cap_t* caps, uint64_t* actual_bytes,
uint64_t* actual_caps) {
ZPortRecvReq req{
.port_cap = port_cap,
.message =
{
.num_bytes = num_bytes,
.data = data,
.num_caps = num_caps,
.caps = caps,
},
};
z_err_t ret = SysCall1(Z_PORT_RECV, &req);
*actual_bytes = req.message.num_bytes;
*actual_caps = req.message.num_caps;
return ret;
}
z_err_t ZPortPoll(z_cap_t port_cap, uint64_t num_bytes, void* data,
uint64_t num_caps, z_cap_t* caps, uint64_t* actual_bytes,
uint64_t* actual_caps) {
ZPortRecvReq req{
.port_cap = port_cap,
.message =
{
.num_bytes = num_bytes,
.data = data,
.num_caps = num_caps,
.caps = caps,
},
};
z_err_t ret = SysCall1(Z_PORT_POLL, &req);
*actual_bytes = req.message.num_bytes;
*actual_caps = req.message.num_caps;
return ret;
}
z_err_t ZIrqRegister(uint64_t irq_num, z_cap_t* port_cap) {
ZIrqRegisterReq req{
.irq_num = irq_num,
};
ZIrqRegisterResp resp;
z_err_t ret = SysCall2(Z_IRQ_REGISTER, &req, &resp);
*port_cap = resp.port_cap;
return ret;
}
z_err_t ZCapDuplicate(z_cap_t cap_in, z_cap_t* cap_out) {
ZCapDuplicateReq req{
.cap = cap_in,
};
ZCapDuplicateResp resp;
z_err_t ret = SysCall2(Z_CAP_DUPLICATE, &req, &resp);
*cap_out = resp.cap;
return ret;
}
z_err_t ZDebug(const char* message) { return SysCall1(Z_DEBUG_PRINT, message); }

View File

@ -4,6 +4,70 @@
#include "include/ztypes.h" #include "include/ztypes.h"
struct ZProcessSpawnReq {
z_cap_t proc_cap;
z_cap_t bootstrap_cap;
};
struct ZProcessSpawnResp {
z_cap_t proc_cap;
z_cap_t vmas_cap;
z_cap_t bootstrap_cap;
};
struct ZThreadCreateReq {
z_cap_t proc_cap;
};
struct ZThreadCreateResp {
z_cap_t thread_cap;
};
struct ZThreadStartReq {
z_cap_t thread_cap;
uint64_t entry;
uint64_t arg1;
uint64_t arg2;
};
struct ZAddressSpaceMapReq {
z_cap_t vmas_cap;
z_cap_t vmas_offset;
z_cap_t vmmo_cap;
};
struct ZAddressSpaceMapResp {
uint64_t vaddr;
};
struct ZMemoryObjectCreateReq {
uint64_t size;
};
struct ZMemoryObjectCreateResp {
z_cap_t vmmo_cap;
};
struct ZMemoryObjectCreatePhysicalReq {
uint64_t paddr;
uint64_t size;
};
struct ZMemoryObjectCreatePhysicalResp {
z_cap_t vmmo_cap;
uint64_t paddr;
};
struct ZTempPcieConfigObjectCreateResp {
z_cap_t vmmo_cap;
uint64_t vmmo_size;
};
struct ZChannelCreateResp {
z_cap_t chan_cap1;
z_cap_t chan_cap2;
};
struct ZMessage { struct ZMessage {
uint64_t num_bytes; uint64_t num_bytes;
void* data; void* data;
@ -11,3 +75,43 @@ struct ZMessage {
uint64_t num_caps; uint64_t num_caps;
z_cap_t* caps; z_cap_t* caps;
}; };
struct ZChannelSendReq {
z_cap_t chan_cap;
ZMessage message;
};
struct ZChannelRecvReq {
z_cap_t chan_cap;
ZMessage message;
};
struct ZPortCreateResp {
z_cap_t port_cap;
};
struct ZPortSendReq {
z_cap_t port_cap;
ZMessage message;
};
struct ZPortRecvReq {
z_cap_t port_cap;
ZMessage message;
};
struct ZIrqRegisterReq {
uint64_t irq_num;
};
struct ZIrqRegisterResp {
z_cap_t port_cap;
};
struct ZCapDuplicateReq {
z_cap_t cap;
};
struct ZCapDuplicateResp {
z_cap_t cap;
};