Compare commits
8 Commits
4fef54084f
...
1edd5023ce
Author | SHA1 | Date |
---|---|---|
|
1edd5023ce | |
|
bd431b94ce | |
|
77bb3acfb4 | |
|
1a70ce4855 | |
|
f755cd38fe | |
|
c6dd0bbb0f | |
|
76107b7db7 | |
|
5fc7296b20 |
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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))) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "include/zcall.h"
|
||||
|
||||
z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req);
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "include/zcall.h"
|
||||
|
||||
z_err_t CapDuplicate(ZCapDuplicateReq* req);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "include/zcall.h"
|
||||
|
||||
z_err_t Debug(ZDebugReq* req);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "include/zcall.h"
|
||||
|
||||
z_err_t ProcessExit(ZProcessExitReq* req);
|
||||
z_err_t ProcessSpawn(ZProcessSpawnReq* req);
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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; \
|
||||
} \
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
|
@ -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*);
|
|
@ -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
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue