diff --git a/zion/loader/elf_loader.cpp b/zion/loader/elf_loader.cpp index 5b4b5e6..b336d8a 100644 --- a/zion/loader/elf_loader.cpp +++ b/zion/loader/elf_loader.cpp @@ -48,7 +48,7 @@ typedef struct { } // namespace -uint64_t LoadElfProgram(uint64_t cr3, uint64_t base, uint64_t offset) { +uint64_t LoadElfProgram(Process& dest_proc, uint64_t base, uint64_t offset) { Elf64Header* header = reinterpret_cast(base); dbgln("phoff: %u phnum: %u", header->phoff, header->phnum); Elf64ProgramHeader* programs = @@ -60,7 +60,7 @@ uint64_t LoadElfProgram(uint64_t cr3, uint64_t base, uint64_t offset) { "filesz: %u, memsz: %u, align: %u", program.type, program.flags, program.offset, program.vaddr, program.paddr, program.filesz, program.memsz, program.align); - CopyIntoNonResidentProcess(base + program.offset, program.filesz, cr3, + CopyIntoNonResidentProcess(base + program.offset, program.filesz, dest_proc, program.vaddr); } return header->entry; diff --git a/zion/loader/elf_loader.h b/zion/loader/elf_loader.h index f6ae328..8e497da 100644 --- a/zion/loader/elf_loader.h +++ b/zion/loader/elf_loader.h @@ -2,5 +2,7 @@ #include +#include "scheduler/process.h" + // Loads the elf program and returns its entry point. -uint64_t LoadElfProgram(uint64_t cr3, uint64_t base, uint64_t length); +uint64_t LoadElfProgram(Process& dest_proc, uint64_t base, uint64_t length); diff --git a/zion/loader/init_loader.cpp b/zion/loader/init_loader.cpp index 818262a..6df19a5 100644 --- a/zion/loader/init_loader.cpp +++ b/zion/loader/init_loader.cpp @@ -43,12 +43,11 @@ void LoadInitProgram() { SharedPtr proc = MakeShared(); gProcMan->InsertProcess(proc); - uint64_t entry = - LoadElfProgram(proc->cr3(), reinterpret_cast(init_prog.address), - init_prog.size); + uint64_t entry = LoadElfProgram( + *proc, reinterpret_cast(init_prog.address), init_prog.size); CopyIntoNonResidentProcess(reinterpret_cast(prog2.address), - prog2.size, proc->cr3(), + prog2.size, *proc, proc->vmm().GetNextMemMapAddr(prog2.size)); proc->CreateThread(entry); diff --git a/zion/memory/paging_util.cpp b/zion/memory/paging_util.cpp index f77d5dd..b323168 100644 --- a/zion/memory/paging_util.cpp +++ b/zion/memory/paging_util.cpp @@ -174,15 +174,15 @@ void EnsureResident(uint64_t addr, uint64_t size) { } } -void CopyIntoNonResidentProcess(uint64_t base, uint64_t size, uint64_t dest_cr3, - uint64_t dest_virt) { +void CopyIntoNonResidentProcess(uint64_t base, uint64_t size, + Process& dest_proc, uint64_t dest_virt) { if (size > 0x1000) { panic("Unimplemented NR copy > 1 page"); } if (dest_virt & 0xFFF) { panic("Unimplemented NR copy to non page aligned"); } - uint64_t phys = AllocatePageIfNecessary(dest_virt, dest_cr3); + uint64_t phys = AllocatePageIfNecessary(dest_virt, dest_proc.vmm().cr3()); uint8_t* src = reinterpret_cast(base); uint8_t* dest = reinterpret_cast(phys + boot::GetHigherHalfDirectMap()); diff --git a/zion/memory/paging_util.h b/zion/memory/paging_util.h index 889234e..c9c4f10 100644 --- a/zion/memory/paging_util.h +++ b/zion/memory/paging_util.h @@ -2,10 +2,12 @@ #include +#include "scheduler/process.h" + void InitializePml4(uint64_t pml4_physical_addr); uint64_t AllocatePageIfNecessary(uint64_t addr, uint64_t cr3 = 0); void EnsureResident(uint64_t addr, uint64_t size); -void CopyIntoNonResidentProcess(uint64_t base, uint64_t size, uint64_t dest_cr3, - uint64_t dest_virt); +void CopyIntoNonResidentProcess(uint64_t base, uint64_t size, + Process& dest_proc, uint64_t dest_virt); diff --git a/zion/memory/virtual_memory.cpp b/zion/memory/virtual_memory.cpp index 7dc8697..61ba1d9 100644 --- a/zion/memory/virtual_memory.cpp +++ b/zion/memory/virtual_memory.cpp @@ -1,9 +1,22 @@ #include "memory/virtual_memory.h" #include "memory/kernel_stack_manager.h" +#include "memory/paging_util.h" +#include "memory/physical_memory.h" extern KernelStackManager* gKernelStackManager; +VirtualMemory VirtualMemory::ForRoot() { + uint64_t cr3 = 0; + asm volatile("mov %%cr3, %0;" : "=r"(cr3)); + return {cr3}; +} + +VirtualMemory::VirtualMemory() { + cr3_ = phys_mem::AllocatePage(); + InitializePml4(cr3_); +} + uint64_t* VirtualMemory::AllocateKernelStack() { return gKernelStackManager->AllocateKernelStack(); } diff --git a/zion/memory/virtual_memory.h b/zion/memory/virtual_memory.h index cf2f113..e6ac097 100644 --- a/zion/memory/virtual_memory.h +++ b/zion/memory/virtual_memory.h @@ -38,16 +38,21 @@ class VirtualMemory { KERNEL_STACK, }; - VirtualMemory() {} + static VirtualMemory ForRoot(); + + VirtualMemory(); VirtualMemory(const VirtualMemory&) = delete; VirtualMemory(VirtualMemory&&) = delete; + uint64_t cr3() { return cr3_; } + uint64_t GetNextMemMapAddr(uint64_t size); // Kernel uint64_t* AllocateKernelStack(); private: + VirtualMemory(uint64_t cr3) : cr3_(cr3) {} uint64_t cr3_ = 0; uint64_t next_memmap_addr_ = 0x20'00000000; diff --git a/zion/scheduler/process.cpp b/zion/scheduler/process.cpp index c9b46cb..8d11a79 100644 --- a/zion/scheduler/process.cpp +++ b/zion/scheduler/process.cpp @@ -13,19 +13,14 @@ static uint64_t gNextId = 1; } SharedPtr Process::RootProcess() { - uint64_t pml4_addr = 0; - asm volatile("mov %%cr3, %0;" : "=r"(pml4_addr)); - SharedPtr proc(new Process(0, pml4_addr)); + SharedPtr proc(new Process(0)); proc->threads_.PushBack(Thread::RootThread(*proc)); proc->next_thread_id_ = 1; return proc; } -Process::Process() : id_(gNextId++), state_(RUNNING) { - cr3_ = phys_mem::AllocatePage(); - InitializePml4(cr3_); -} +Process::Process() : id_(gNextId++), state_(RUNNING) {} void Process::CreateThread(uint64_t entry) { Thread* thread = new Thread(*this, next_thread_id_++, entry); diff --git a/zion/scheduler/process.h b/zion/scheduler/process.h index 20aa2bb..0853760 100644 --- a/zion/scheduler/process.h +++ b/zion/scheduler/process.h @@ -21,7 +21,6 @@ class Process { Process(); uint64_t id() const { return id_; } - uint64_t cr3() const { return cr3_; } VirtualMemory& vmm() { return vmm_; } void CreateThread(uint64_t entry); @@ -34,10 +33,9 @@ class Process { State GetState() { return state_; } private: - Process(uint64_t id, uint64_t cr3) : id_(id), cr3_(cr3) {} + Process(uint64_t id) : id_(id), vmm_(VirtualMemory::ForRoot()) {} uint64_t id_; VirtualMemory vmm_; - uint64_t cr3_; State state_; uint64_t next_thread_id_ = 0; diff --git a/zion/scheduler/thread.cpp b/zion/scheduler/thread.cpp index dc6a4ce..f17abc3 100644 --- a/zion/scheduler/thread.cpp +++ b/zion/scheduler/thread.cpp @@ -34,7 +34,7 @@ Thread::Thread(Process& proc, uint64_t tid, uint64_t entry) *(stack_ptr - 5) = reinterpret_cast(stack_ptr + 1); // 6-15: rsi, rdi, r8, r9, r10, r11, r12, r13, r14, r15 // 16: cr3 - *(stack_ptr - 16) = proc.cr3(); + *(stack_ptr - 16) = proc.vmm().cr3(); rsp0_ = reinterpret_cast(stack_ptr - 16); rsp0_start_ = reinterpret_cast(stack_ptr); } diff --git a/zion/syscall/syscall.cpp b/zion/syscall/syscall.cpp index 4cb2480..965cbe5 100644 --- a/zion/syscall/syscall.cpp +++ b/zion/syscall/syscall.cpp @@ -60,7 +60,7 @@ uint64_t ProcessSpawn(ZProcessSpawnReq* req) { dbgln("Proc spawn: %u:%u", req->elf_base, req->elf_size); SharedPtr proc = MakeShared(); gProcMan->InsertProcess(proc); - uint64_t entry = LoadElfProgram(proc->cr3(), req->elf_base, req->elf_size); + uint64_t entry = LoadElfProgram(*proc, req->elf_base, req->elf_size); proc->CreateThread(entry); return 0; }