From 7184f527a0a880349a9697666c6d26db2d984706 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Mon, 29 May 2023 12:44:26 -0700 Subject: [PATCH] Jump to user mode. This instantly creates a page fault as we always map pages with ring 0 permissions. --- zion/CMakeLists.txt | 1 + zion/common/gdt.cpp | 2 ++ zion/common/gdt.h | 4 ++++ zion/loader/elf_loader.cpp | 3 ++- zion/loader/elf_loader.h | 3 ++- zion/scheduler/jump_user_space.s | 16 ++++++++++++++++ zion/scheduler/thread.cpp | 15 ++++++++++----- 7 files changed, 37 insertions(+), 7 deletions(-) create mode 100644 zion/scheduler/jump_user_space.s diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 4cf3ba1..2b35ec3 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -11,6 +11,7 @@ add_executable(zion memory/paging_util.cpp memory/physical_memory.cpp scheduler/context_switch.s + scheduler/jump_user_space.s scheduler/process.cpp scheduler/scheduler.cpp scheduler/thread.cpp diff --git a/zion/common/gdt.cpp b/zion/common/gdt.cpp index 2e0f7cf..b2f31a0 100644 --- a/zion/common/gdt.cpp +++ b/zion/common/gdt.cpp @@ -90,3 +90,5 @@ void InitGdt() { "ltr %%ax;" :: : "rax"); } + +void SetRsp0(uint64_t rsp0) { gTaskStateSegment.rsp0 = rsp0; } diff --git a/zion/common/gdt.h b/zion/common/gdt.h index df0b364..5cee0fd 100644 --- a/zion/common/gdt.h +++ b/zion/common/gdt.h @@ -1,3 +1,7 @@ #pragma once +#include + void InitGdt(); + +void SetRsp0(uint64_t rsp0); diff --git a/zion/loader/elf_loader.cpp b/zion/loader/elf_loader.cpp index 44474fe..2a7ed6a 100644 --- a/zion/loader/elf_loader.cpp +++ b/zion/loader/elf_loader.cpp @@ -56,7 +56,7 @@ void badmemcpy(uint64_t base, uint64_t offset, uint64_t dest) { } // namespace -void LoadElfProgram(uint64_t base, uint64_t offset) { +uint64_t LoadElfProgram(uint64_t base, uint64_t offset) { Elf64Header* header = reinterpret_cast(base); dbgln("phoff: %u phnum: %u", header->phoff, header->phnum); Elf64ProgramHeader* programs = @@ -71,4 +71,5 @@ void LoadElfProgram(uint64_t base, uint64_t offset) { EnsureResident(program.vaddr, program.memsz); badmemcpy(base + program.offset, program.filesz, program.vaddr); } + return header->entry; } diff --git a/zion/loader/elf_loader.h b/zion/loader/elf_loader.h index 4feac5e..1c6c7e3 100644 --- a/zion/loader/elf_loader.h +++ b/zion/loader/elf_loader.h @@ -2,4 +2,5 @@ #include -void LoadElfProgram(uint64_t base, uint64_t length); +// Loads the elf program and returns its entry point. +uint64_t LoadElfProgram(uint64_t base, uint64_t length); diff --git a/zion/scheduler/jump_user_space.s b/zion/scheduler/jump_user_space.s new file mode 100644 index 0000000..da077f9 --- /dev/null +++ b/zion/scheduler/jump_user_space.s @@ -0,0 +1,16 @@ +.global jump_user_space +// rdi - entry point, rsi - user stack +jump_user_space: + cli + mov $0x23, %ax + mov %ax, %ds + mov %ax, %es + mov %ax, %fs + mov %ax, %gs + + pushq $0x23 # ss + pushq %rsi + pushf # Can we just push 0 for flags? + pushq $0x1B # cs + pushq %rdi + iretq diff --git a/zion/scheduler/thread.cpp b/zion/scheduler/thread.cpp index 75753a5..fb4fef7 100644 --- a/zion/scheduler/thread.cpp +++ b/zion/scheduler/thread.cpp @@ -1,12 +1,16 @@ #include "scheduler/thread.h" +#include "common/gdt.h" #include "debug/debug.h" #include "loader/elf_loader.h" +#include "memory/paging_util.h" #include "scheduler/process.h" #include "scheduler/scheduler.h" namespace { +extern "C" void jump_user_space(uint64_t rip, uint64_t rsp); + extern "C" void thread_init() { asm("sti"); sched::CurrentThread().Init(); @@ -36,9 +40,10 @@ Thread::Thread(Process* proc, uint64_t tid, uint64_t elf_ptr) uint64_t Thread::pid() { return process_->id(); } void Thread::Init() { - LoadElfProgram(elf_ptr_, 0); - while (true) { - dbgln("[%u.%u]", pid(), id_); - sched::Yield(); - } + dbgln("[%u.%u]", pid(), id_); + uint64_t rip = LoadElfProgram(elf_ptr_, 0); + uint64_t rsp = 0x80000000; + EnsureResident(rsp - 1, 1); + SetRsp0(rsp0_start_); + jump_user_space(rip, rsp); }