diff --git a/zion/loader/elf_loader.cpp b/zion/loader/elf_loader.cpp index 2a7ed6a..5b4b5e6 100644 --- a/zion/loader/elf_loader.cpp +++ b/zion/loader/elf_loader.cpp @@ -46,17 +46,9 @@ typedef struct { uint64_t align; } Elf64ProgramHeader; -void badmemcpy(uint64_t base, uint64_t offset, uint64_t dest) { - uint8_t* ptr = reinterpret_cast(base); - uint8_t* dest_ptr = reinterpret_cast(dest); - for (uint64_t i = 0; i < offset; i++) { - dest_ptr[i] = ptr[i]; - } -} - } // namespace -uint64_t LoadElfProgram(uint64_t base, uint64_t offset) { +uint64_t LoadElfProgram(uint64_t cr3, uint64_t base, uint64_t offset) { Elf64Header* header = reinterpret_cast(base); dbgln("phoff: %u phnum: %u", header->phoff, header->phnum); Elf64ProgramHeader* programs = @@ -68,8 +60,8 @@ uint64_t LoadElfProgram(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); - EnsureResident(program.vaddr, program.memsz); - badmemcpy(base + program.offset, program.filesz, program.vaddr); + CopyIntoNonResidentProcess(base + program.offset, program.filesz, cr3, + program.vaddr); } return header->entry; } diff --git a/zion/loader/elf_loader.h b/zion/loader/elf_loader.h index 1c6c7e3..f6ae328 100644 --- a/zion/loader/elf_loader.h +++ b/zion/loader/elf_loader.h @@ -3,4 +3,4 @@ #include // Loads the elf program and returns its entry point. -uint64_t LoadElfProgram(uint64_t base, uint64_t length); +uint64_t LoadElfProgram(uint64_t cr3, uint64_t base, uint64_t length); diff --git a/zion/loader/init_loader.cpp b/zion/loader/init_loader.cpp index a10da9c..79bb7cf 100644 --- a/zion/loader/init_loader.cpp +++ b/zion/loader/init_loader.cpp @@ -25,6 +25,11 @@ const limine_file& GetInitProgram() { void LoadInitProgram() { const limine_file& init_prog = GetInitProgram(); - gProcMan->InsertProcess( - new Process(reinterpret_cast(init_prog.address))); + SharedPtr proc = MakeShared(); + gProcMan->InsertProcess(proc); + + uint64_t entry = + LoadElfProgram(proc->cr3(), reinterpret_cast(init_prog.address), + init_prog.size); + proc->CreateThread(entry); } diff --git a/zion/memory/paging_util.cpp b/zion/memory/paging_util.cpp index c8d2c27..f77d5dd 100644 --- a/zion/memory/paging_util.cpp +++ b/zion/memory/paging_util.cpp @@ -69,7 +69,7 @@ uint64_t* PageTableEntry(uint64_t pt_phys, uint64_t addr) { ShiftForEntryIndexing(addr, PT_OFFSET)); } -bool IsPageResident(uint64_t cr3, uint64_t virt) { +uint64_t PagePhysIfResident(uint64_t cr3, uint64_t virt) { uint64_t* pml4_entry = Pml4Entry(cr3, virt); if (!(*pml4_entry & PRESENT_BIT)) { return false; @@ -86,10 +86,10 @@ bool IsPageResident(uint64_t cr3, uint64_t virt) { if (!(*pt_entry & PRESENT_BIT)) { return false; } - return true; + return *pt_entry & ~0xFFF; } -void MapPage(uint64_t cr3, uint64_t virt) { +uint64_t MapPage(uint64_t cr3, uint64_t virt) { uint64_t access_bits = PRESENT_BIT | READ_WRITE_BIT; uint64_t higher_half = 0xffff8000'00000000; if ((virt & higher_half) != higher_half) { @@ -121,8 +121,10 @@ void MapPage(uint64_t cr3, uint64_t virt) { *pt_entry = PageAlign(phys) | access_bits; ZeroOutPage(reinterpret_cast(boot::GetHigherHalfDirectMap() + PageAlign(phys))); + return phys; } else { panic("Page already allocated."); + return 0; } } @@ -152,14 +154,15 @@ void InitializePml4(uint64_t pml4_physical_addr) { pml4_virtual[Pml4Index(hhdm)] = *Pml4Entry(curr_cr3, hhdm); } -void AllocatePageIfNecessary(uint64_t addr, uint64_t cr3) { +uint64_t AllocatePageIfNecessary(uint64_t addr, uint64_t cr3) { if (cr3 == 0) { cr3 = CurrCr3(); } - if (IsPageResident(cr3, addr)) { - return; + uint64_t phys = PagePhysIfResident(cr3, addr); + if (phys) { + return phys; } - MapPage(cr3, addr); + return MapPage(cr3, addr); } void EnsureResident(uint64_t addr, uint64_t size) { @@ -170,3 +173,21 @@ void EnsureResident(uint64_t addr, uint64_t size) { addr += 0x1000; } } + +void CopyIntoNonResidentProcess(uint64_t base, uint64_t size, uint64_t dest_cr3, + 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); + uint8_t* src = reinterpret_cast(base); + uint8_t* dest = + reinterpret_cast(phys + boot::GetHigherHalfDirectMap()); + + for (uint64_t i = 0; i < size; i++) { + dest[i] = src[i]; + } +} diff --git a/zion/memory/paging_util.h b/zion/memory/paging_util.h index 055eb3e..889234e 100644 --- a/zion/memory/paging_util.h +++ b/zion/memory/paging_util.h @@ -4,5 +4,8 @@ void InitializePml4(uint64_t pml4_physical_addr); -void AllocatePageIfNecessary(uint64_t addr, uint64_t cr3 = 0); +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); diff --git a/zion/scheduler/process.cpp b/zion/scheduler/process.cpp index 32f6a08..07c7282 100644 --- a/zion/scheduler/process.cpp +++ b/zion/scheduler/process.cpp @@ -22,14 +22,13 @@ SharedPtr Process::RootProcess() { return proc; } -Process::Process(uint64_t elf_ptr) : id_(gNextId++), state_(RUNNING) { +Process::Process() : id_(gNextId++), state_(RUNNING) { cr3_ = phys_mem::AllocatePage(); InitializePml4(cr3_); - CreateThread(elf_ptr); } -void Process::CreateThread(uint64_t elf_ptr) { - Thread* thread = new Thread(this, next_thread_id_++, elf_ptr); +void Process::CreateThread(uint64_t entry) { + Thread* thread = new Thread(this, next_thread_id_++, entry); threads_.PushBack(thread); gScheduler->Enqueue(thread); } diff --git a/zion/scheduler/process.h b/zion/scheduler/process.h index 3014b3e..80a669d 100644 --- a/zion/scheduler/process.h +++ b/zion/scheduler/process.h @@ -17,12 +17,12 @@ class Process { FINISHED, }; static SharedPtr RootProcess(); - Process(uint64_t elf_ptr); + Process(); uint64_t id() const { return id_; } uint64_t cr3() const { return cr3_; } - void CreateThread(uint64_t elf_ptr); + void CreateThread(uint64_t entry); SharedPtr GetThread(uint64_t tid); // Checks the state of all child threads and transitions to diff --git a/zion/scheduler/thread.cpp b/zion/scheduler/thread.cpp index 4851478..b1f6af5 100644 --- a/zion/scheduler/thread.cpp +++ b/zion/scheduler/thread.cpp @@ -23,8 +23,8 @@ SharedPtr Thread::RootThread(Process* root_proc) { return new Thread(root_proc); } -Thread::Thread(const SharedPtr& proc, uint64_t tid, uint64_t elf_ptr) - : process_(proc), id_(tid), elf_ptr_(elf_ptr) { +Thread::Thread(const SharedPtr& proc, uint64_t tid, uint64_t entry) + : process_(proc), id_(tid), rip_(entry) { uint64_t* stack = new uint64_t[512]; uint64_t* stack_ptr = stack + 511; // 0: rip @@ -42,12 +42,11 @@ Thread::Thread(const SharedPtr& proc, uint64_t tid, uint64_t elf_ptr) uint64_t Thread::pid() { return process_->id(); } void Thread::Init() { - dbgln("[%u.%u]", pid(), id_); - uint64_t rip = LoadElfProgram(elf_ptr_, 0); + dbgln("[%u.%u] thread start.", pid(), id_); uint64_t rsp = 0x80000000; EnsureResident(rsp - 1, 1); SetRsp0(rsp0_start_); - jump_user_space(rip, rsp); + jump_user_space(rip_, rsp); } void Thread::Exit() { diff --git a/zion/scheduler/thread.h b/zion/scheduler/thread.h index da8036b..2f5e102 100644 --- a/zion/scheduler/thread.h +++ b/zion/scheduler/thread.h @@ -11,16 +11,13 @@ class Thread { public: enum State { UNSPECIFIED, - CREATED, RUNNING, RUNNABLE, - BLOCKED, FINISHED, }; static SharedPtr RootThread(Process* root_proc); - explicit Thread(const SharedPtr& proc, uint64_t tid, - uint64_t elf_ptr); + explicit Thread(const SharedPtr& proc, uint64_t tid, uint64_t entry); uint64_t tid() { return id_; }; uint64_t pid(); @@ -45,7 +42,8 @@ class Thread { uint64_t id_; State state_ = RUNNABLE; - uint64_t elf_ptr_; + // Startup Context for the thread. + uint64_t rip_; // Stack pointer to take on resume. // Stack will contain the full thread context.