From 24272c57ef9f2439bc21f4fb4d51dd1099e035d4 Mon Sep 17 00:00:00 2001 From: apio Date: Thu, 13 Oct 2022 21:55:51 +0200 Subject: [PATCH] Almost there! --- kernel/include/memory/VMM.h | 4 ++++ kernel/src/main.cpp | 8 ++++---- kernel/src/memory/VMM.cpp | 21 +++++++++++++++++++++ kernel/src/sys/Syscall.cpp | 3 +++ kernel/src/sys/elf/ELFLoader.cpp | 6 ++++++ kernel/src/thread/Scheduler.cpp | 9 ++++++++- 6 files changed, 46 insertions(+), 5 deletions(-) diff --git a/kernel/include/memory/VMM.h b/kernel/include/memory/VMM.h index 15736615..ad736def 100644 --- a/kernel/include/memory/VMM.h +++ b/kernel/include/memory/VMM.h @@ -13,8 +13,12 @@ namespace VMM void init(); // Fetch page table from cr3 void switch_to_user_address_space(AddressSpace& space); + void switch_to_previous_user_address_space(); void switch_back_to_kernel_address_space(); + void enter_syscall_context(); + void exit_syscall_context(); + void apply_address_space(); bool is_using_kernel_address_space(); diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 459eced6..1d1fa288 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -57,6 +57,10 @@ extern "C" void _start() kinfoln("Loaded IDT"); + PIT::initialize(1000); // 1000 times per second + + kinfoln("Prepared PIT"); + Scheduler::init(); kinfoln("Prepared scheduler"); @@ -78,10 +82,6 @@ extern "C" void _start() Init::finish_kernel_boot(); - PIT::initialize(1000); // 1000 times per second - - kinfoln("Prepared PIT"); - PIC::remap(); PIC::enable_master(0b11111100); // enable keyboard and PIT PIC::enable_slave(0b11111111); diff --git a/kernel/src/memory/VMM.cpp b/kernel/src/memory/VMM.cpp index 8f706812..05c3a7ce 100644 --- a/kernel/src/memory/VMM.cpp +++ b/kernel/src/memory/VMM.cpp @@ -22,6 +22,27 @@ void VMM::switch_to_user_address_space(AddressSpace& space) current_pml4 = user_address_space->get_pml4(); } +void VMM::switch_to_previous_user_address_space() +{ + current_pml4 = user_address_space->get_pml4(); +} + +void VMM::enter_syscall_context() +{ + if (current_pml4 != kernel_pml4) + { + current_pml4 = kernel_pml4; + apply_address_space(); + switch_to_previous_user_address_space(); + } +} + +void VMM::exit_syscall_context() +{ + if (current_pml4 != user_address_space->get_pml4()) { switch_to_previous_user_address_space(); } + apply_address_space(); +} + void VMM::apply_address_space() { asm volatile("mov %0, %%cr3" : : "r"(current_pml4)); diff --git a/kernel/src/sys/Syscall.cpp b/kernel/src/sys/Syscall.cpp index 8a3434b9..f47dc227 100644 --- a/kernel/src/sys/Syscall.cpp +++ b/kernel/src/sys/Syscall.cpp @@ -1,11 +1,13 @@ #include "sys/Syscall.h" #include "errno.h" #include "io/Serial.h" +#include "memory/VMM.h" #include "thread/Scheduler.h" void Syscall::entry(Context* context) { asm volatile("cli"); + VMM::enter_syscall_context(); switch (context->rax) { case SYS_exit: sys_exit(context, (int)context->rdi); break; @@ -24,4 +26,5 @@ void Syscall::entry(Context* context) case SYS_exec: sys_exec(context, (const char*)context->rdi); break; default: context->rax = -ENOSYS; break; } + VMM::exit_syscall_context(); } \ No newline at end of file diff --git a/kernel/src/sys/elf/ELFLoader.cpp b/kernel/src/sys/elf/ELFLoader.cpp index 91d6d554..a9d4bb2e 100644 --- a/kernel/src/sys/elf/ELFLoader.cpp +++ b/kernel/src/sys/elf/ELFLoader.cpp @@ -94,9 +94,15 @@ ELFImage* ELFLoader::load_elf_from_vfs(VFS::Node* node) Utilities::round_down_to_nearest_page(phdr.p_vaddr), pages, MAP_READ_WRITE) + (phdr.p_vaddr % PAGE_SIZE)); + VMM::apply_address_space(); + VFS::read(node, phdr.p_offset, phdr.p_filesz, (char*)buffer); memset((void*)((uint64_t)buffer + phdr.p_filesz), 0, phdr.p_memsz - phdr.p_filesz); + VMM::switch_back_to_kernel_address_space(); + VMM::apply_address_space(); + VMM::switch_to_previous_user_address_space(); + MemoryManager::protect(buffer, pages, phdr.p_flags & 2 ? MAP_READ_WRITE | MAP_USER : MAP_USER); image = (ELFImage*)krealloc(image, (sizeof(ELFImage) - sizeof(ELFSection)) + diff --git a/kernel/src/thread/Scheduler.cpp b/kernel/src/thread/Scheduler.cpp index 3eb48255..9e4855cd 100644 --- a/kernel/src/thread/Scheduler.cpp +++ b/kernel/src/thread/Scheduler.cpp @@ -55,6 +55,7 @@ void Scheduler::init() // the other registers will be saved next task switch frequency = 1000 / PIT::frequency(); + kdbgln("frequency: %ld", frequency); } void Scheduler::add_kernel_task(void (*task)(void)) @@ -182,7 +183,12 @@ void Scheduler::reap_task(Task* task) task_num--; Task* exiting_task = task; ASSERT(task->id != 0); // WHY IN THE WORLD WOULD WE BE REAPING THE IDLE TASK? - if (exiting_task->is_user_task()) { VMM::switch_to_user_address_space(exiting_task->address_space); } + if (exiting_task->is_user_task()) + { + VMM::switch_back_to_kernel_address_space(); + VMM::apply_address_space(); + VMM::switch_to_user_address_space(exiting_task->address_space); + } kinfoln("reaping task %ld, exited with code %ld", exiting_task->id, exiting_task->exit_status); if (exiting_task->allocated_stack) MemoryManager::release_pages((void*)exiting_task->allocated_stack, TASK_PAGES_IN_STACK); @@ -194,6 +200,7 @@ void Scheduler::reap_task(Task* task) if (exiting_task->is_user_task()) { VMM::switch_back_to_kernel_address_space(); + VMM::apply_address_space(); Interrupts::push_and_enable(); exiting_task->address_space.destroy(); Interrupts::pop();