Compare commits

...

8 Commits

30 changed files with 567 additions and 687 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,8 +27,16 @@ add_executable(zion
scheduler/jump_user_space.s
scheduler/process_manager.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_enter.s
syscall/thread.cpp
zion.cpp)
target_include_directories(zion

View File

@ -4,58 +4,125 @@
#include "ztypes.h"
void ZProcessExit(uint64_t code);
#define SYS0(name) \
struct Z##name##Req {}; \
[[nodiscard]] inline z_err_t Z##name() { \
Z##name##Req req{}; \
return SysCall1(kZion##name, &req); \
}
[[nodiscard]] 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);
#define SYS1(name, t1, a1) \
struct Z##name##Req { \
t1 a1; \
}; \
[[nodiscard]] inline z_err_t Z##name(t1 a1) { \
Z##name##Req req{ \
.a1 = a1, \
}; \
return SysCall1(kZion##name, &req); \
}
// UNUSED for now, I think we can get away with just starting a thread.
[[nodiscard]] z_err_t ZProcessStart(z_cap_t proc_cap, z_cap_t thread_cap,
uint64_t entry, uint64_t arg1,
uint64_t arg2);
#define SYS2(name, t1, a1, t2, a2) \
struct Z##name##Req { \
t1 a1; \
t2 a2; \
}; \
[[nodiscard]] inline z_err_t Z##name(t1 a1, t2 a2) { \
Z##name##Req req{ \
.a1 = a1, \
.a2 = a2, \
}; \
return SysCall1(kZion##name, &req); \
}
[[nodiscard]] z_err_t ZThreadCreate(z_cap_t proc_cap, z_cap_t* thread_cap);
#define SYS3(name, t1, a1, t2, a2, t3, a3) \
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); \
}
[[nodiscard]] z_err_t ZThreadStart(z_cap_t thread_cap, uint64_t entry,
uint64_t arg1, uint64_t arg2);
#define SYS4(name, t1, a1, t2, a2, t3, a3, t4, a4) \
struct Z##name##Req { \
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); \
}
void ZThreadExit();
#define SYS5(name, t1, a1, t2, a2, t3, a3, t4, a4, t5, a5) \
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); \
}
[[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);
z_err_t SysCall1(uint64_t code, const void* req);
[[nodiscard]] z_err_t ZTempPcieConfigObjectCreate(z_cap_t* vmmo_cap,
uint64_t* vmmo_size);
SYS1(ProcessExit, uint64_t, code);
SYS5(ProcessSpawn, 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);
[[nodiscard]] z_err_t ZChannelCreate(z_cap_t* channel1, z_cap_t* channel2);
[[nodiscard]] 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);
[[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);
SYS2(ThreadCreate, z_cap_t, proc_cap, z_cap_t*, thread_cap);
SYS4(ThreadStart, z_cap_t, thread_cap, uint64_t, entry, uint64_t, arg1,
uint64_t, arg2);
SYS0(ThreadExit);
[[nodiscard]] z_err_t ZPortCreate(z_cap_t* port_cap);
[[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);
SYS4(AddressSpaceMap, z_cap_t, vmas_cap, uint64_t, vmas_offset, z_cap_t,
vmmo_cap, uint64_t*, vaddr);
[[nodiscard]] z_err_t ZCapDuplicate(z_cap_t cap_in, z_cap_t* cap_out);
SYS2(MemoryObjectCreate, uint64_t, size, z_cap_t*, vmmo_cap);
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);
[[nodiscard]] z_err_t ZDebug(const char* message);
SYS2(ChannelCreate, z_cap_t*, channel1, z_cap_t*, channel2);
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.
#define Z_PROCESS_EXIT 0x01
#define Z_PROCESS_SPAWN 0x02
#define Z_PROCESS_START 0x03
const uint64_t kZionProcessExit = 0x1;
const uint64_t kZionProcessSpawn = 0x2;
// Thread Calls.
#define Z_THREAD_CREATE 0x10
#define Z_THREAD_START 0x11
#define Z_THREAD_EXIT 0x12
const uint64_t kZionThreadCreate = 0x10;
const uint64_t kZionThreadStart = 0x11;
const uint64_t kZionThreadExit = 0x12;
// Memory Calls
#define Z_ADDRESS_SPACE_MAP 0x21
#define Z_ADDRESS_SPACE_UNMAP 0x22
const uint64_t kZionAddressSpaceMap = 0x21;
const uint64_t kZionAddressSpaceUnMap = 0x21;
#define Z_MEMORY_OBJECT_CREATE 0x30
#define Z_MEMORY_OBJECT_CREATE_PHYSICAL 0x31
const uint64_t kZionMemoryObjectCreate = 0x30;
const uint64_t kZionMemoryObjectCreatePhysical = 0x31;
const uint64_t kZionMemoryObjectCreateContiguous = 0x32;
#define Z_TEMP_PCIE_CONFIG_OBJECT_CREATE 0x3F
const uint64_t kZionTempPcieConfigObjectCreate = 0x3F;
// IPC Calls
#define Z_CHANNEL_CREATE 0x40
#define Z_CHANNEL_SEND 0x41
#define Z_CHANNEL_RECV 0x42
#define Z_CHANNEL_SENDRECV 0x43
const uint64_t kZionChannelCreate = 0x40;
const uint64_t kZionChannelSend = 0x41;
const uint64_t kZionChannelRecv = 0x42;
const uint64_t kZionChannelSendRecv = 0x43;
#define Z_PORT_CREATE 0x50
#define Z_PORT_SEND 0x51
#define Z_PORT_RECV 0x52
#define Z_PORT_POLL 0x53
const uint64_t kZionPortCreate = 0x50;
const uint64_t kZionPortSend = 0x51;
const uint64_t kZionPortRecv = 0x52;
const uint64_t kZionPortPoll = 0x53;
#define Z_IRQ_REGISTER 0x58
const uint64_t kZionIrqRegister = 0x58;
#define Z_IRQ_PCI_BASE 0x30
// Capability Calls
#define Z_CAP_DUPLICATE 0x60
const uint64_t kZionCapDuplicate = 0x70;
// Debugging Calls.
#define Z_DEBUG_PRINT 0x10000000
const uint64_t kZionDebug = 0x1'0000;
/* ------------------------------
* Capability Types

View File

@ -0,0 +1,26 @@
#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

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

View File

@ -0,0 +1,13 @@
#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

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

52
zion/syscall/channel.cpp Normal file
View File

@ -0,0 +1,52 @@
#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;
}

7
zion/syscall/channel.h Normal file
View File

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

8
zion/syscall/debug.cpp Normal file
View File

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

5
zion/syscall/debug.h Normal file
View File

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

View File

@ -0,0 +1,42 @@
#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

@ -0,0 +1,8 @@
#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);

81
zion/syscall/port.cpp Normal file
View File

@ -0,0 +1,81 @@
#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;
}

9
zion/syscall/port.h Normal file
View File

@ -0,0 +1,9 @@
#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);

38
zion/syscall/process.cpp Normal file
View File

@ -0,0 +1,38 @@
#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;
}

6
zion/syscall/process.h Normal file
View File

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

View File

@ -2,7 +2,6 @@
#include <stdint.h>
#include "boot/acpi.h"
#include "common/msr.h"
#include "debug/debug.h"
#include "include/zcall.h"
@ -13,15 +12,16 @@
#include "object/process.h"
#include "scheduler/process_manager.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"
#define RET_IF_NULL(expr) \
{ \
if (!expr) { \
return Z_ERR_CAP_TYPE; \
} \
}
#define EFER 0xC0000080
#define STAR 0xC0000081
#define LSTAR 0xC0000082
@ -65,263 +65,41 @@ z_err_t ValidateCap(const RefPtr<Capability>& cap, uint64_t permissions) {
return Z_OK;
}
z_err_t ProcessSpawn(ZProcessSpawnReq* req, ZProcessSpawnResp* resp) {
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);
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;
}
#define CASE(name) \
case kZion##name: \
return name(reinterpret_cast<Z##name##Req*>(req));
extern "C" z_err_t SyscallHandler(uint64_t call_id, void* req, void* resp) {
RefPtr<Thread> thread = gScheduler->CurrentThread();
switch (call_id) {
case Z_PROCESS_EXIT:
// FIXME: kill process here.
dbgln("Exit code: %x", req);
thread->Exit();
panic("Returned from thread exit");
break;
case Z_PROCESS_SPAWN:
return ProcessSpawn(reinterpret_cast<ZProcessSpawnReq*>(req),
reinterpret_cast<ZProcessSpawnResp*>(resp));
case Z_THREAD_CREATE:
return ThreadCreate(reinterpret_cast<ZThreadCreateReq*>(req),
reinterpret_cast<ZThreadCreateResp*>(resp));
case Z_THREAD_START:
return ThreadStart(reinterpret_cast<ZThreadStartReq*>(req));
case Z_THREAD_EXIT:
thread->Exit();
panic("Returned from thread exit");
break;
case Z_ADDRESS_SPACE_MAP:
return AddressSpaceMap(reinterpret_cast<ZAddressSpaceMapReq*>(req),
reinterpret_cast<ZAddressSpaceMapResp*>(resp));
case Z_MEMORY_OBJECT_CREATE:
return MemoryObjectCreate(
reinterpret_cast<ZMemoryObjectCreateReq*>(req),
reinterpret_cast<ZMemoryObjectCreateResp*>(resp));
case Z_MEMORY_OBJECT_CREATE_PHYSICAL:
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;
// syscall/process.h
CASE(ProcessExit);
CASE(ProcessSpawn);
// syscall/thread.h
CASE(ThreadCreate);
CASE(ThreadStart);
CASE(ThreadExit);
// syscall/address_space.h
CASE(AddressSpaceMap);
// syscall/memory_object.h
CASE(MemoryObjectCreate);
CASE(MemoryObjectCreatePhysical);
CASE(MemoryObjectCreateContiguous);
CASE(TempPcieConfigObjectCreate);
// syscall/channel.h
CASE(ChannelCreate);
CASE(ChannelSend);
CASE(ChannelRecv);
// syscall/port.h
CASE(PortCreate);
CASE(PortSend);
CASE(PortRecv);
CASE(PortPoll);
CASE(IrqRegister);
// syscall/capability.h
CASE(CapDuplicate);
// syscall/debug.h
CASE(Debug);
default:
panic("Unhandled syscall number: %x", call_id);
}

View File

@ -1,3 +1,16 @@
#pragma once
#include "capability/capability.h"
#include "include/ztypes.h"
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; \
} \
}

34
zion/syscall/thread.cpp Normal file
View File

@ -0,0 +1,34 @@
#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");
}

7
zion/syscall/thread.h Normal file
View File

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

View File

@ -4,236 +4,8 @@
#include "usr/zcall_internal.h"
z_err_t SysCall2(uint64_t number, const void* first, const void* second) {
z_err_t SysCall1(uint64_t number, const void* first) {
z_err_t return_code;
asm("syscall"
: "=a"(return_code)
: "D"(number), "S"(first), "d"(second)
: "rcx", "r11");
asm("syscall" : "=a"(return_code) : "D"(number), "S"(first) : "rcx", "r11");
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,70 +4,6 @@
#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 {
uint64_t num_bytes;
void* data;
@ -75,43 +11,3 @@ struct ZMessage {
uint64_t num_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;
};