Compare commits

...

5 Commits

Author SHA1 Message Date
Drew Galbraith 242a18ae3c [zion] Finish cleaning up process capability interface.
Make all functions generic and specify existing/vs new cap.
2023-06-16 15:09:15 -07:00
Drew Galbraith fc94bc5bf5 [zion] Update process interface to simplify capability insertion.
Take a templated KernelObject with explicit permissions.
2023-06-16 15:04:33 -07:00
Drew Galbraith a47bac9966 [zion] Dynamically check Capability type.
Instead of passing an enum with the capability when creating it, relying
on polymorphism and a template struct tag to determine the object type
at runtime.

This is cleaner and avoids errors where we pass the wrong capability
type with the cap and do a bad cast at runtime.
2023-06-16 14:53:57 -07:00
Drew Galbraith b4902a79ef [zion] Add per-process CapabilityTable object
Store this information in it's own object to make the API clearer.
2023-06-16 14:25:54 -07:00
Drew Galbraith be12fa9a19 Add mutex fixme 2023-06-16 14:25:23 -07:00
17 changed files with 233 additions and 194 deletions

View File

@ -1,7 +1,7 @@
add_executable(zion add_executable(zion
boot/acpi.cpp boot/acpi.cpp
boot/boot_info.cpp boot/boot_info.cpp
capability/capability.cpp capability/capability_table.cpp
common/gdt.cpp common/gdt.cpp
common/load_gdt.s common/load_gdt.s
common/msr.cpp common/msr.cpp

View File

@ -1,52 +0,0 @@
#include "capability/capability.h"
#include "object/process.h"
#include "object/thread.h"
template <>
RefPtr<Process> Capability::obj<Process>() {
if (type_ != PROCESS) {
panic("Accessing %u cap as object.", type_);
}
return StaticCastRefPtr<Process>(obj_);
}
template <>
RefPtr<Thread> Capability::obj<Thread>() {
if (type_ != THREAD) {
panic("Accessing %u cap as object.", type_);
}
return StaticCastRefPtr<Thread>(obj_);
}
template <>
RefPtr<AddressSpace> Capability::obj<AddressSpace>() {
if (type_ != ADDRESS_SPACE) {
panic("Accessing %u cap as object.", type_);
}
return StaticCastRefPtr<AddressSpace>(obj_);
}
template <>
RefPtr<MemoryObject> Capability::obj<MemoryObject>() {
if (type_ != MEMORY_OBJECT) {
panic("Accessing %u cap as object.", type_);
}
return StaticCastRefPtr<MemoryObject>(obj_);
}
template <>
RefPtr<Channel> Capability::obj<Channel>() {
if (type_ != CHANNEL) {
panic("Accessing %u cap as object.", type_);
}
return StaticCastRefPtr<Channel>(obj_);
}
template <>
RefPtr<Port> Capability::obj<Port>() {
if (type_ != PORT) {
panic("Accessing %u cap as object.", type_);
}
return StaticCastRefPtr<Port>(obj_);
}

View File

@ -10,23 +10,12 @@ class Thread;
class Capability : public RefCounted<Capability> { class Capability : public RefCounted<Capability> {
public: public:
enum Type { Capability(const RefPtr<KernelObject>& obj, uint64_t id, uint64_t permissions)
UNDEFINED, : obj_(obj), id_(id), permissions_(permissions) {}
PROCESS,
THREAD,
ADDRESS_SPACE,
MEMORY_OBJECT,
CHANNEL,
PORT,
};
Capability(const RefPtr<KernelObject>& obj, Type type, uint64_t id,
uint64_t permissions)
: obj_(obj), type_(type), id_(id), permissions_(permissions) {}
template <typename T> template <typename T>
Capability(const RefPtr<T>& obj, Type type, uint64_t id, uint64_t permissions) Capability(const RefPtr<T>& obj, uint64_t id, uint64_t permissions)
: Capability(StaticCastRefPtr<KernelObject>(obj), type, id, permissions) { : Capability(StaticCastRefPtr<KernelObject>(obj), id, permissions) {}
}
template <typename T> template <typename T>
RefPtr<T> obj(); RefPtr<T> obj();
@ -34,8 +23,6 @@ class Capability : public RefCounted<Capability> {
uint64_t id() { return id_; } uint64_t id() { return id_; }
void set_id(uint64_t id) { id_ = id; } void set_id(uint64_t id) { id_ = id; }
bool CheckType(Type type) { return type_ == type; }
uint64_t permissions() { return permissions_; } uint64_t permissions() { return permissions_; }
bool HasPermissions(uint64_t requested) { bool HasPermissions(uint64_t requested) {
return (permissions_ & requested) == requested; return (permissions_ & requested) == requested;
@ -43,7 +30,14 @@ class Capability : public RefCounted<Capability> {
private: private:
RefPtr<KernelObject> obj_; RefPtr<KernelObject> obj_;
Type type_;
uint64_t id_; uint64_t id_;
uint64_t permissions_; uint64_t permissions_;
}; };
template <typename T>
RefPtr<T> Capability::obj() {
if (obj_->TypeTag() != KernelObjectTag<T>::type) {
return nullptr;
}
return StaticCastRefPtr<T>(obj_);
}

View File

@ -0,0 +1,41 @@
#include "capability/capability_table.h"
CapabilityTable::CapabilityTable() {}
uint64_t CapabilityTable::AddExistingCapability(const RefPtr<Capability>& cap) {
MutexHolder h(lock_);
cap->set_id(next_cap_id_++);
capabilities_.PushBack(cap);
return cap->id();
}
RefPtr<Capability> CapabilityTable::GetCapability(uint64_t id) {
MutexHolder h(lock_);
auto iter = capabilities_.begin();
while (iter != capabilities_.end()) {
if (*iter && iter->id() == id) {
return *iter;
}
++iter;
}
dbgln("Bad cap access %u", id);
dbgln("Num caps: %u", capabilities_.size());
return {};
}
RefPtr<Capability> CapabilityTable::ReleaseCapability(uint64_t id) {
MutexHolder h(lock_);
auto iter = capabilities_.begin();
while (iter != capabilities_.end()) {
if (*iter && iter->id() == id) {
// FIXME: Do an actual release here.
auto cap = *iter;
*iter = {nullptr};
return cap;
}
++iter;
}
dbgln("Bad cap release: %u", id);
dbgln("Num caps: %u", capabilities_.size());
return {};
}

View File

@ -0,0 +1,49 @@
#pragma once
#include "capability/capability.h"
#include "lib/linked_list.h"
#include "lib/mutex.h"
#include "lib/ref_ptr.h"
class CapabilityTable {
public:
CapabilityTable();
CapabilityTable(CapabilityTable&) = delete;
CapabilityTable& operator=(CapabilityTable&) = delete;
template <typename T>
uint64_t AddNewCapability(const RefPtr<T>& object, uint64_t permissions);
uint64_t AddExistingCapability(const RefPtr<Capability>& cap);
// FIXME: Remove reliance on this.
template <typename T>
void AddNewCapabilityWithId(uint64_t id, const RefPtr<T>& object,
uint64_t permissions);
RefPtr<Capability> GetCapability(uint64_t id);
RefPtr<Capability> ReleaseCapability(uint64_t id);
private:
Mutex lock_{"cap table"};
// FIXME: store this id here rather than in the capability.
uint64_t next_cap_id_ = 0x100;
// FIXME: use a map data structure.
LinkedList<RefPtr<Capability>> capabilities_;
};
template <typename T>
uint64_t CapabilityTable::AddNewCapability(const RefPtr<T>& object,
uint64_t permissions) {
MutexHolder h(lock_);
uint64_t id = next_cap_id_++;
capabilities_.PushBack(MakeRefCounted<Capability>(object, id, permissions));
return id;
}
template <typename T>
void CapabilityTable::AddNewCapabilityWithId(uint64_t id,
const RefPtr<T>& object,
uint64_t permissions) {
capabilities_.PushBack(MakeRefCounted<Capability>(object, id, permissions));
}

View File

@ -6,6 +6,7 @@ class Mutex {
public: public:
Mutex(const char* name) : name_(name) {} Mutex(const char* name) : name_(name) {}
// FIXME: Block thread on lock rather than "preempting"
void Lock(); void Lock();
void Unlock() { lock_ = false; } void Unlock() { lock_ = false; }

View File

@ -127,7 +127,7 @@ void LoadInitProgram() {
RefPtr<MemoryObject> prog2_vmmo = MakeRefCounted<MemoryObject>(prog2.size); RefPtr<MemoryObject> prog2_vmmo = MakeRefCounted<MemoryObject>(prog2.size);
prog2_vmmo->CopyBytesToObject(reinterpret_cast<uint64_t>(prog2.address), prog2_vmmo->CopyBytesToObject(reinterpret_cast<uint64_t>(prog2.address),
prog2.size); prog2.size);
proc->AddCapability(Z_INIT_BOOT_VMMO, prog2_vmmo); proc->AddNewCapabilityWithId(Z_INIT_BOOT_VMMO, prog2_vmmo, ZC_WRITE);
proc->CreateThread()->Start(entry, 0, 0); proc->CreateThread()->Start(entry, 0, 0);
} }

View File

@ -6,6 +6,13 @@
#include "memory/user_stack_manager.h" #include "memory/user_stack_manager.h"
#include "object/memory_object.h" #include "object/memory_object.h"
class AddressSpace;
template <>
struct KernelObjectTag<AddressSpace> {
static const uint64_t type = KernelObject::ADDRESS_SPACE;
};
// VirtualMemory class holds a memory space for an individual process. // VirtualMemory class holds a memory space for an individual process.
// //
// Memory Regions are predefined for simplicity for now. However, in general // Memory Regions are predefined for simplicity for now. However, in general
@ -26,6 +33,8 @@
// 0xFFFFFFFF 90000000 - 0xFFFFFFFF 9FFFFFFF : KERNEL_STACK (256 MiB) // 0xFFFFFFFF 90000000 - 0xFFFFFFFF 9FFFFFFF : KERNEL_STACK (256 MiB)
class AddressSpace : public KernelObject { class AddressSpace : public KernelObject {
public: public:
uint64_t TypeTag() override { return KernelObject::ADDRESS_SPACE; }
enum MemoryType { enum MemoryType {
UNSPECIFIED, UNSPECIFIED,
UNMAPPED, UNMAPPED,

View File

@ -44,7 +44,7 @@ z_err_t Channel::Read(ZMessage& msg) {
msg.num_caps = next_msg->caps.size(); msg.num_caps = next_msg->caps.size();
auto& proc = gScheduler->CurrentProcess(); auto& proc = gScheduler->CurrentProcess();
for (uint64_t i = 0; i < msg.num_caps; i++) { for (uint64_t i = 0; i < msg.num_caps; i++) {
msg.caps[i] = proc.AddCapability(next_msg->caps.PopFront()); msg.caps[i] = proc.AddExistingCapability(next_msg->caps.PopFront());
} }
pending_messages_.PopFront(); pending_messages_.PopFront();

View File

@ -10,8 +10,16 @@
#include "object/kernel_object.h" #include "object/kernel_object.h"
#include "usr/zcall_internal.h" #include "usr/zcall_internal.h"
class Channel;
template <>
struct KernelObjectTag<Channel> {
static const uint64_t type = KernelObject::CHANNEL;
};
class Channel : public KernelObject { class Channel : public KernelObject {
public: public:
uint64_t TypeTag() override { return KernelObject::CHANNEL; }
static Pair<RefPtr<Channel>, RefPtr<Channel>> CreateChannelPair(); static Pair<RefPtr<Channel>, RefPtr<Channel>> CreateChannelPair();
RefPtr<Channel> peer() { return peer_; } RefPtr<Channel> peer() { return peer_; }

View File

@ -2,4 +2,22 @@
#include "lib/ref_counted.h" #include "lib/ref_counted.h"
class KernelObject : public RefCounted<KernelObject> {}; class KernelObject : public RefCounted<KernelObject> {
public:
enum ObjectType {
INVALID = 0x0,
PROCESS = 0x1,
THREAD = 0x2,
ADDRESS_SPACE = 0x3,
MEMORY_OBJECT = 0x4,
CHANNEL = 0x5,
PORT = 0x6,
};
virtual uint64_t TypeTag() = 0;
};
template <typename T>
struct KernelObjectTag {
static const int type = KernelObject::INVALID;
};

View File

@ -3,6 +3,12 @@
#include "lib/linked_list.h" #include "lib/linked_list.h"
#include "object/kernel_object.h" #include "object/kernel_object.h"
class MemoryObject;
template <>
struct KernelObjectTag<MemoryObject> {
static const uint64_t type = KernelObject::MEMORY_OBJECT;
};
/* /*
* MemoryObject is a page-aligned set of memory that corresponds * MemoryObject is a page-aligned set of memory that corresponds
* to physical pages. * to physical pages.
@ -11,6 +17,7 @@
* */ * */
class MemoryObject : public KernelObject { class MemoryObject : public KernelObject {
public: public:
uint64_t TypeTag() override { return KernelObject::MEMORY_OBJECT; }
MemoryObject(uint64_t size); MemoryObject(uint64_t size);
uint64_t size() { return size_; } uint64_t size() { return size_; }

View File

@ -6,8 +6,17 @@
#include "object/thread.h" #include "object/thread.h"
#include "usr/zcall_internal.h" #include "usr/zcall_internal.h"
class Port;
template <>
struct KernelObjectTag<Port> {
static const uint64_t type = KernelObject::PORT;
};
class Port : public KernelObject { class Port : public KernelObject {
public: public:
uint64_t TypeTag() override { return KernelObject::PORT; }
Port(); Port();
z_err_t Write(const ZMessage& msg); z_err_t Write(const ZMessage& msg);

View File

@ -22,11 +22,9 @@ RefPtr<Process> Process::RootProcess() {
} }
RefPtr<Process> Process::Create() { RefPtr<Process> Process::Create() {
auto proc = MakeRefCounted<Process>(); auto proc = MakeRefCounted<Process>();
proc->caps_.PushBack( proc->AddNewCapabilityWithId(Z_INIT_PROC_SELF, proc,
MakeRefCounted<Capability>(proc, Capability::PROCESS, Z_INIT_PROC_SELF, ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD);
ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD)); proc->AddNewCapabilityWithId(Z_INIT_VMAS_SELF, proc->vmas(), ZC_WRITE);
proc->caps_.PushBack(MakeRefCounted<Capability>(
proc->vmas(), Capability::ADDRESS_SPACE, Z_INIT_VMAS_SELF, ZC_WRITE));
return proc; return proc;
} }
@ -66,88 +64,13 @@ void Process::CheckState() {
} }
RefPtr<Capability> Process::ReleaseCapability(uint64_t cid) { RefPtr<Capability> Process::ReleaseCapability(uint64_t cid) {
MutexHolder lock(mutex_); return caps_.ReleaseCapability(cid);
auto iter = caps_.begin();
while (iter != caps_.end()) {
if (*iter && iter->id() == cid) {
auto cap = *iter;
*iter = {nullptr};
return cap;
}
++iter;
}
dbgln("Bad cap release: %u", cid);
dbgln("Num caps: %u", caps_.size());
return {};
} }
RefPtr<Capability> Process::GetCapability(uint64_t cid) { RefPtr<Capability> Process::GetCapability(uint64_t cid) {
MutexHolder lock(mutex_); return caps_.GetCapability(cid);
auto iter = caps_.begin();
while (iter != caps_.end()) {
if (*iter && iter->id() == cid) {
return *iter;
}
++iter;
}
dbgln("Bad cap access %u", cid);
dbgln("Num caps: %u", caps_.size());
return {};
} }
uint64_t Process::AddCapability(const RefPtr<Capability>& cap) { uint64_t Process::AddExistingCapability(const RefPtr<Capability>& cap) {
MutexHolder lock(mutex_); return caps_.AddExistingCapability(cap);
cap->set_id(next_cap_id_++);
caps_.PushBack(cap);
return cap->id();
}
uint64_t Process::AddCapability(const RefPtr<Thread>& thread) {
MutexHolder lock(mutex_);
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(
MakeRefCounted<Capability>(thread, Capability::THREAD, cap_id, ZC_WRITE));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<Process>& p) {
MutexHolder lock(mutex_);
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(MakeRefCounted<Capability>(p, Capability::PROCESS, cap_id,
ZC_WRITE | ZC_PROC_SPAWN_THREAD));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<AddressSpace>& vmas) {
MutexHolder lock(mutex_);
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(MakeRefCounted<Capability>(vmas, Capability::ADDRESS_SPACE,
cap_id, ZC_WRITE));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<MemoryObject>& vmmo) {
MutexHolder lock(mutex_);
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(MakeRefCounted<Capability>(vmmo, Capability::MEMORY_OBJECT,
cap_id, ZC_WRITE));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<Channel>& chan) {
MutexHolder lock(mutex_);
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(MakeRefCounted<Capability>(chan, Capability::CHANNEL, cap_id,
ZC_WRITE | ZC_READ));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<Port>& port) {
MutexHolder lock(mutex_);
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(MakeRefCounted<Capability>(port, Capability::PORT, cap_id,
ZC_WRITE | ZC_READ));
return cap_id;
}
void Process::AddCapability(uint64_t cap_id, const RefPtr<MemoryObject>& vmmo) {
MutexHolder lock(mutex_);
caps_.PushBack(MakeRefCounted<Capability>(vmmo, Capability::MEMORY_OBJECT,
cap_id, ZC_WRITE));
} }

View File

@ -3,6 +3,7 @@
#include <stdint.h> #include <stdint.h>
#include "capability/capability.h" #include "capability/capability.h"
#include "capability/capability_table.h"
#include "lib/linked_list.h" #include "lib/linked_list.h"
#include "lib/mutex.h" #include "lib/mutex.h"
#include "lib/ref_ptr.h" #include "lib/ref_ptr.h"
@ -13,8 +14,14 @@
// Forward decl due to cyclic dependency. // Forward decl due to cyclic dependency.
class Thread; class Thread;
template <>
struct KernelObjectTag<Process> {
static const uint64_t type = KernelObject::PROCESS;
};
class Process : public KernelObject { class Process : public KernelObject {
public: public:
uint64_t TypeTag() override { return KernelObject::PROCESS; }
enum State { enum State {
UNSPECIFIED, UNSPECIFIED,
SETUP, SETUP,
@ -32,16 +39,20 @@ class Process : public KernelObject {
RefPtr<Capability> ReleaseCapability(uint64_t cid); RefPtr<Capability> ReleaseCapability(uint64_t cid);
RefPtr<Capability> GetCapability(uint64_t cid); RefPtr<Capability> GetCapability(uint64_t cid);
// FIXME: We can't reset the cap id here.
uint64_t AddCapability(const RefPtr<Capability>& cap);
uint64_t AddCapability(const RefPtr<Thread>& t);
uint64_t AddCapability(const RefPtr<Process>& p);
uint64_t AddCapability(const RefPtr<AddressSpace>& vmas);
uint64_t AddCapability(const RefPtr<MemoryObject>& vmmo);
uint64_t AddCapability(const RefPtr<Channel>& chan);
uint64_t AddCapability(const RefPtr<Port>& chan);
void AddCapability(uint64_t cap_id, const RefPtr<MemoryObject>& vmmo); template <typename T>
uint64_t AddNewCapability(const RefPtr<T>& obj, uint64_t permissions) {
return caps_.AddNewCapability(obj, permissions);
}
uint64_t AddExistingCapability(const RefPtr<Capability>& cap);
// FIXME: Eliminate reliance on this.
template <typename T>
void AddNewCapabilityWithId(uint64_t id, const RefPtr<T>& obj,
uint64_t permissions) {
return caps_.AddNewCapabilityWithId(id, obj, permissions);
}
// Checks the state of all child threads and transitions to // Checks the state of all child threads and transitions to
// finished if all have finished. // finished if all have finished.
void CheckState(); void CheckState();
@ -63,5 +74,5 @@ class Process : public KernelObject {
uint64_t next_cap_id_ = 0x100; uint64_t next_cap_id_ = 0x100;
LinkedList<RefPtr<Thread>> threads_; LinkedList<RefPtr<Thread>> threads_;
LinkedList<RefPtr<Capability>> caps_; CapabilityTable caps_;
}; };

View File

@ -7,9 +7,16 @@
// Forward decl due to cyclic dependency. // Forward decl due to cyclic dependency.
class Process; class Process;
class Thread;
template <>
struct KernelObjectTag<Thread> {
static const uint64_t type = KernelObject::THREAD;
};
class Thread : public KernelObject { class Thread : public KernelObject {
public: public:
uint64_t TypeTag() override { return KernelObject::THREAD; }
enum State { enum State {
UNSPECIFIED, UNSPECIFIED,
CREATED, CREATED,

View File

@ -16,6 +16,13 @@
#include "scheduler/scheduler.h" #include "scheduler/scheduler.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
@ -46,14 +53,10 @@ void InitSyscall() {
SetMSR(LSTAR, reinterpret_cast<uint64_t>(syscall_enter)); SetMSR(LSTAR, reinterpret_cast<uint64_t>(syscall_enter));
} }
z_err_t ValidateCap(const RefPtr<Capability>& cap, Capability::Type type, z_err_t ValidateCap(const RefPtr<Capability>& cap, uint64_t permissions) {
uint64_t permissions) {
if (!cap) { if (!cap) {
return Z_ERR_CAP_NOT_FOUND; return Z_ERR_CAP_NOT_FOUND;
} }
if (!cap->CheckType(type)) {
return Z_ERR_CAP_TYPE;
}
if (!cap->HasPermissions(permissions)) { if (!cap->HasPermissions(permissions)) {
return Z_ERR_CAP_DENIED; return Z_ERR_CAP_DENIED;
} }
@ -63,13 +66,14 @@ z_err_t ValidateCap(const RefPtr<Capability>& cap, Capability::Type type,
z_err_t ProcessSpawn(ZProcessSpawnReq* req, ZProcessSpawnResp* resp) { z_err_t ProcessSpawn(ZProcessSpawnReq* req, ZProcessSpawnResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->proc_cap); auto cap = curr_proc.GetCapability(req->proc_cap);
RET_ERR(ValidateCap(cap, Capability::PROCESS, ZC_PROC_SPAWN_PROC)); RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_PROC));
RefPtr<Process> proc = Process::Create(); RefPtr<Process> proc = Process::Create();
gProcMan->InsertProcess(proc); gProcMan->InsertProcess(proc);
resp->proc_cap = curr_proc.AddCapability(proc); resp->proc_cap = curr_proc.AddNewCapability(
resp->vmas_cap = curr_proc.AddCapability(proc->vmas()); proc, ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_PROC | ZC_WRITE);
resp->vmas_cap = curr_proc.AddNewCapability(proc->vmas(), ZC_WRITE);
if (req->bootstrap_cap != 0) { if (req->bootstrap_cap != 0) {
auto cap = curr_proc.ReleaseCapability(req->bootstrap_cap); auto cap = curr_proc.ReleaseCapability(req->bootstrap_cap);
@ -77,7 +81,7 @@ z_err_t ProcessSpawn(ZProcessSpawnReq* req, ZProcessSpawnResp* resp) {
return Z_ERR_CAP_NOT_FOUND; return Z_ERR_CAP_NOT_FOUND;
} }
// FIXME: Check permissions. // FIXME: Check permissions.
resp->bootstrap_cap = proc->AddCapability(cap); resp->bootstrap_cap = proc->AddExistingCapability(cap);
} }
return Z_OK; return Z_OK;
@ -86,11 +90,12 @@ z_err_t ProcessSpawn(ZProcessSpawnReq* req, ZProcessSpawnResp* resp) {
z_err_t ThreadCreate(ZThreadCreateReq* req, ZThreadCreateResp* resp) { z_err_t ThreadCreate(ZThreadCreateReq* req, ZThreadCreateResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->proc_cap); auto cap = curr_proc.GetCapability(req->proc_cap);
RET_ERR(ValidateCap(cap, Capability::PROCESS, ZC_PROC_SPAWN_THREAD)); RET_ERR(ValidateCap(cap, ZC_PROC_SPAWN_THREAD));
auto parent_proc = cap->obj<Process>(); auto parent_proc = cap->obj<Process>();
RET_IF_NULL(parent_proc);
auto thread = parent_proc->CreateThread(); auto thread = parent_proc->CreateThread();
resp->thread_cap = curr_proc.AddCapability(thread); resp->thread_cap = curr_proc.AddNewCapability(thread, ZC_WRITE);
return Z_OK; return Z_OK;
} }
@ -98,9 +103,10 @@ z_err_t ThreadCreate(ZThreadCreateReq* req, ZThreadCreateResp* resp) {
z_err_t ThreadStart(ZThreadStartReq* req) { z_err_t ThreadStart(ZThreadStartReq* req) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
auto cap = curr_proc.GetCapability(req->thread_cap); auto cap = curr_proc.GetCapability(req->thread_cap);
RET_ERR(ValidateCap(cap, Capability::THREAD, ZC_WRITE)); RET_ERR(ValidateCap(cap, ZC_WRITE));
auto thread = cap->obj<Thread>(); auto thread = cap->obj<Thread>();
RET_IF_NULL(thread);
// FIXME: validate entry point is in user space. // FIXME: validate entry point is in user space.
thread->Start(req->entry, req->arg1, req->arg2); thread->Start(req->entry, req->arg1, req->arg2);
return Z_OK; return Z_OK;
@ -110,11 +116,14 @@ z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req, ZAddressSpaceMapResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
auto vmas_cap = curr_proc.GetCapability(req->vmas_cap); auto vmas_cap = curr_proc.GetCapability(req->vmas_cap);
auto vmmo_cap = curr_proc.GetCapability(req->vmmo_cap); auto vmmo_cap = curr_proc.GetCapability(req->vmmo_cap);
RET_ERR(ValidateCap(vmas_cap, Capability::ADDRESS_SPACE, ZC_WRITE)); RET_ERR(ValidateCap(vmas_cap, ZC_WRITE));
RET_ERR(ValidateCap(vmmo_cap, Capability::MEMORY_OBJECT, ZC_WRITE)); RET_ERR(ValidateCap(vmmo_cap, ZC_WRITE));
auto vmas = vmas_cap->obj<AddressSpace>(); auto vmas = vmas_cap->obj<AddressSpace>();
auto vmmo = vmmo_cap->obj<MemoryObject>(); auto vmmo = vmmo_cap->obj<MemoryObject>();
RET_IF_NULL(vmas);
RET_IF_NULL(vmmo);
dbgln("Ptr %x, %x", vmas.get(), vmmo.get());
// FIXME: Validation necessary. // FIXME: Validation necessary.
if (req->vmas_offset != 0) { if (req->vmas_offset != 0) {
vmas->MapInMemoryObject(req->vmas_offset, vmmo); vmas->MapInMemoryObject(req->vmas_offset, vmmo);
@ -128,8 +137,8 @@ z_err_t AddressSpaceMap(ZAddressSpaceMapReq* req, ZAddressSpaceMapResp* resp) {
z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req, z_err_t MemoryObjectCreate(ZMemoryObjectCreateReq* req,
ZMemoryObjectCreateResp* resp) { ZMemoryObjectCreateResp* resp) {
auto& curr_proc = gScheduler->CurrentProcess(); auto& curr_proc = gScheduler->CurrentProcess();
resp->vmmo_cap = resp->vmmo_cap = curr_proc.AddNewCapability(
curr_proc.AddCapability(MakeRefCounted<MemoryObject>(req->size)); MakeRefCounted<MemoryObject>(req->size), ZC_WRITE);
return Z_OK; return Z_OK;
} }
@ -141,8 +150,8 @@ z_err_t MemoryObjectCreatePhysical(ZMemoryObjectCreatePhysicalReq* req,
paddr = phys_mem::AllocateContinuous(((req->size - 1) / 0x1000) + 1); paddr = phys_mem::AllocateContinuous(((req->size - 1) / 0x1000) + 1);
} }
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(paddr, req->size); auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(paddr, req->size);
resp->vmmo_cap = resp->vmmo_cap = curr_proc.AddNewCapability(
curr_proc.AddCapability(StaticCastRefPtr<MemoryObject>(vmmo_ref)); StaticCastRefPtr<MemoryObject>(vmmo_ref), ZC_WRITE);
resp->paddr = paddr; resp->paddr = paddr;
return Z_OK; return Z_OK;
} }
@ -152,8 +161,8 @@ z_err_t TempPcieConfigObjectCreate(ZTempPcieConfigObjectCreateResp* resp) {
uint64_t pci_base, pci_size; uint64_t pci_base, pci_size;
RET_ERR(GetPciExtendedConfiguration(&pci_base, &pci_size)); RET_ERR(GetPciExtendedConfiguration(&pci_base, &pci_size));
auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(pci_base, pci_size); auto vmmo_ref = MakeRefCounted<FixedMemoryObject>(pci_base, pci_size);
resp->vmmo_cap = resp->vmmo_cap = curr_proc.AddNewCapability(
curr_proc.AddCapability(StaticCastRefPtr<MemoryObject>(vmmo_ref)); StaticCastRefPtr<MemoryObject>(vmmo_ref), ZC_WRITE);
resp->vmmo_size = pci_size; resp->vmmo_size = pci_size;
return Z_OK; return Z_OK;
} }
@ -161,17 +170,20 @@ z_err_t TempPcieConfigObjectCreate(ZTempPcieConfigObjectCreateResp* resp) {
z_err_t ChannelCreate(ZChannelCreateResp* resp) { z_err_t ChannelCreate(ZChannelCreateResp* resp) {
auto& proc = gScheduler->CurrentProcess(); auto& proc = gScheduler->CurrentProcess();
auto chan_pair = Channel::CreateChannelPair(); auto chan_pair = Channel::CreateChannelPair();
resp->chan_cap1 = proc.AddCapability(chan_pair.first()); resp->chan_cap1 =
resp->chan_cap2 = proc.AddCapability(chan_pair.second()); proc.AddNewCapability(chan_pair.first(), ZC_WRITE | ZC_READ);
resp->chan_cap2 =
proc.AddNewCapability(chan_pair.second(), ZC_WRITE | ZC_READ);
return Z_OK; return Z_OK;
} }
z_err_t ChannelSend(ZChannelSendReq* req) { z_err_t ChannelSend(ZChannelSendReq* req) {
auto& proc = gScheduler->CurrentProcess(); auto& proc = gScheduler->CurrentProcess();
auto chan_cap = proc.GetCapability(req->chan_cap); auto chan_cap = proc.GetCapability(req->chan_cap);
RET_ERR(ValidateCap(chan_cap, Capability::CHANNEL, ZC_WRITE)); RET_ERR(ValidateCap(chan_cap, ZC_WRITE));
auto chan = chan_cap->obj<Channel>(); auto chan = chan_cap->obj<Channel>();
RET_IF_NULL(chan);
chan->Write(req->message); chan->Write(req->message);
return Z_OK; return Z_OK;
} }
@ -179,18 +191,20 @@ z_err_t ChannelSend(ZChannelSendReq* req) {
z_err_t ChannelRecv(ZChannelRecvReq* req) { z_err_t ChannelRecv(ZChannelRecvReq* req) {
auto& proc = gScheduler->CurrentProcess(); auto& proc = gScheduler->CurrentProcess();
auto chan_cap = proc.GetCapability(req->chan_cap); auto chan_cap = proc.GetCapability(req->chan_cap);
RET_ERR(ValidateCap(chan_cap, Capability::CHANNEL, ZC_READ)); RET_ERR(ValidateCap(chan_cap, ZC_READ));
auto chan = chan_cap->obj<Channel>(); auto chan = chan_cap->obj<Channel>();
RET_IF_NULL(chan);
return chan->Read(req->message); return chan->Read(req->message);
} }
z_err_t PortRecv(ZPortRecvReq* req) { z_err_t PortRecv(ZPortRecvReq* req) {
auto& proc = gScheduler->CurrentProcess(); auto& proc = gScheduler->CurrentProcess();
auto port_cap = proc.GetCapability(req->port_cap); auto port_cap = proc.GetCapability(req->port_cap);
RET_ERR(ValidateCap(port_cap, Capability::PORT, ZC_READ)); RET_ERR(ValidateCap(port_cap, ZC_READ));
auto port = port_cap->obj<Port>(); auto port = port_cap->obj<Port>();
RET_IF_NULL(port);
return port->Read(req->message); return port->Read(req->message);
} }
@ -201,7 +215,7 @@ z_err_t IrqRegister(ZIrqRegisterReq* req, ZIrqRegisterResp* resp) {
return Z_ERR_UNIMPLEMENTED; return Z_ERR_UNIMPLEMENTED;
} }
RefPtr<Port> port = MakeRefCounted<Port>(); RefPtr<Port> port = MakeRefCounted<Port>();
resp->port_cap = proc.AddCapability(port); resp->port_cap = proc.AddNewCapability(port, ZC_READ | ZC_WRITE);
RegisterPciPort(port); RegisterPciPort(port);
return Z_OK; return Z_OK;
} }