Spawn Processes using memory primitives rather than and elf loader.

This allows us to remove the temporary syscall for that style of process
spawn.
This commit is contained in:
Drew Galbraith 2023-06-07 00:04:53 -07:00
parent b06c76e477
commit 23895b5c6c
26 changed files with 403 additions and 94 deletions

View file

@ -6,10 +6,10 @@
extern KernelStackManager* gKernelStackManager;
AddressSpace AddressSpace::ForRoot() {
RefPtr<AddressSpace> AddressSpace::ForRoot() {
uint64_t cr3 = 0;
asm volatile("mov %%cr3, %0;" : "=r"(cr3));
return {cr3};
return MakeRefCounted<AddressSpace>(cr3);
}
AddressSpace::AddressSpace() {
@ -22,6 +22,10 @@ uint64_t AddressSpace::AllocateUserStack() {
}
uint64_t AddressSpace::GetNextMemMapAddr(uint64_t size) {
if (size == 0) {
panic("Zero size memmap");
}
size = ((size - 1) & ~0xFFF) + 0x1000;
uint64_t addr = next_memmap_addr_;
next_memmap_addr_ += size;
if (next_memmap_addr_ >= 0x30'00000000) {
@ -35,6 +39,12 @@ void AddressSpace::MapInMemoryObject(uint64_t vaddr,
memory_mappings_.PushBack({.vaddr = vaddr, .mem_obj = mem_obj});
}
uint64_t AddressSpace::MapInMemoryObject(const RefPtr<MemoryObject>& mem_obj) {
uint64_t vaddr = GetNextMemMapAddr(mem_obj->size());
memory_mappings_.PushBack({.vaddr = vaddr, .mem_obj = mem_obj});
return vaddr;
}
uint64_t* AddressSpace::AllocateKernelStack() {
return gKernelStackManager->AllocateKernelStack();
}

View file

@ -24,7 +24,7 @@
// 0xFFFFFFFF 40000000 - 0xFFFFFFFF 7FFFFFFF : KERNEL_HEAP (1 GiB)
// 0xFFFFFFFF 80000000 - 0xFFFFFFFF 80FFFFFF : KERNEL_CODE (16 MiB)
// 0xFFFFFFFF 90000000 - 0xFFFFFFFF 9FFFFFFF : KERNEL_STACK (256 MiB)
class AddressSpace {
class AddressSpace : public KernelObject {
public:
enum MemoryType {
UNSPECIFIED,
@ -40,7 +40,7 @@ class AddressSpace {
KERNEL_STACK,
};
static AddressSpace ForRoot();
static RefPtr<AddressSpace> ForRoot();
AddressSpace();
AddressSpace(const AddressSpace&) = delete;
@ -56,6 +56,8 @@ class AddressSpace {
// Note this is unsafe for now as it may clobber other mappings.
void MapInMemoryObject(uint64_t vaddr, const RefPtr<MemoryObject>& mem_obj);
uint64_t MapInMemoryObject(const RefPtr<MemoryObject>& mem_obj);
// Kernel Mappings.
uint64_t* AllocateKernelStack();
@ -63,6 +65,7 @@ class AddressSpace {
bool HandlePageFault(uint64_t vaddr);
private:
friend class MakeRefCountedFriend<AddressSpace>;
AddressSpace(uint64_t cr3) : cr3_(cr3) {}
uint64_t cr3_ = 0;

View file

@ -25,10 +25,13 @@ RefPtr<Process> Process::Create() {
proc->caps_.PushBack(
new Capability(proc, Capability::PROCESS, Z_INIT_PROC_SELF,
ZC_PROC_SPAWN_PROC | ZC_PROC_SPAWN_THREAD));
proc->caps_.PushBack(new Capability(proc->vmas(), Capability::ADDRESS_SPACE,
Z_INIT_AS_SELF, ZC_WRITE));
return proc;
}
Process::Process() : id_(gNextId++), state_(RUNNING) {}
Process::Process()
: id_(gNextId++), vmm_(MakeRefCounted<AddressSpace>()), state_(RUNNING) {}
RefPtr<Thread> Process::CreateThread() {
RefPtr<Thread> thread = MakeRefCounted<Thread>(*this, next_thread_id_++);
@ -77,3 +80,22 @@ uint64_t Process::AddCapability(const RefPtr<Thread>& thread) {
caps_.PushBack(new Capability(thread, Capability::THREAD, cap_id, ZC_WRITE));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<Process>& p) {
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(new Capability(p, Capability::PROCESS, cap_id,
ZC_WRITE | ZC_PROC_SPAWN_THREAD));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<AddressSpace>& as) {
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(
new Capability(as, Capability::ADDRESS_SPACE, cap_id, ZC_WRITE));
return cap_id;
}
uint64_t Process::AddCapability(const RefPtr<MemoryObject>& mo) {
uint64_t cap_id = next_cap_id_++;
caps_.PushBack(
new Capability(mo, Capability::MEMORY_OBJECT, cap_id, ZC_WRITE));
return cap_id;
}

View file

@ -23,13 +23,16 @@ class Process : public KernelObject {
static RefPtr<Process> Create();
uint64_t id() const { return id_; }
AddressSpace& vmm() { return vmm_; }
RefPtr<AddressSpace> vmas() { return vmm_; }
RefPtr<Thread> CreateThread();
RefPtr<Thread> GetThread(uint64_t tid);
SharedPtr<Capability> GetCapability(uint64_t cid);
uint64_t AddCapability(const RefPtr<Thread>& t);
uint64_t AddCapability(const RefPtr<Process>& p);
uint64_t AddCapability(const RefPtr<AddressSpace>& as);
uint64_t AddCapability(const RefPtr<MemoryObject>& mo);
// Checks the state of all child threads and transitions to
// finished if all have finished.
void CheckState();
@ -41,7 +44,7 @@ class Process : public KernelObject {
Process();
Process(uint64_t id) : id_(id), vmm_(AddressSpace::ForRoot()) {}
uint64_t id_;
AddressSpace vmm_;
RefPtr<AddressSpace> vmm_;
State state_;
uint64_t next_thread_id_ = 0;

View file

@ -29,7 +29,7 @@ RefPtr<Thread> Thread::Create(Process& proc, uint64_t tid) {
}
Thread::Thread(Process& proc, uint64_t tid) : process_(proc), id_(tid) {
uint64_t* stack_ptr = proc.vmm().AllocateKernelStack();
uint64_t* stack_ptr = proc.vmas()->AllocateKernelStack();
// 0: rip
*(stack_ptr) = reinterpret_cast<uint64_t>(thread_init);
// 1-4: rax, rcx, rdx, rbx
@ -37,7 +37,7 @@ Thread::Thread(Process& proc, uint64_t tid) : process_(proc), id_(tid) {
*(stack_ptr - 5) = reinterpret_cast<uint64_t>(stack_ptr + 1);
// 6-15: rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15
// 16: cr3
*(stack_ptr - 16) = proc.vmm().cr3();
*(stack_ptr - 16) = proc.vmas()->cr3();
rsp0_ = reinterpret_cast<uint64_t>(stack_ptr - 16);
rsp0_start_ = reinterpret_cast<uint64_t>(stack_ptr);
}
@ -55,7 +55,7 @@ void Thread::Start(uint64_t entry, uint64_t arg1, uint64_t arg2) {
void Thread::Init() {
dbgln("Thread start.", pid(), id_);
uint64_t rsp = process_.vmm().AllocateUserStack();
uint64_t rsp = process_.vmas()->AllocateUserStack();
SetRsp0(rsp0_start_);
jump_user_space(rip_, rsp, arg1_, arg2_);
}