diff --git a/kernel/src/main.cpp b/kernel/src/main.cpp index 2b3e3ffc..b743d553 100644 --- a/kernel/src/main.cpp +++ b/kernel/src/main.cpp @@ -97,12 +97,27 @@ Result init() CPU::idle_loop(); } -// FIXME: Add a guard page to make sure the stack doesn't end up in random kernel memory. Also reclaim this memory after -// leaving the init task. +static constexpr u64 BOOTSTRAP_STACK_PAGES = 8; + +// FIXME: Reclaim this memory as soon as we leave the init task (so as soon as the Scheduler runs a task switch) +static u64 allocate_initial_kernel_stack() +{ + u64 address = MemoryManager::alloc_for_kernel(BOOTSTRAP_STACK_PAGES + 1, MMU::ReadWrite | MMU::NoExecute).value(); + // First page is a guard page, the rest is stack. + MMU::unmap(address); // Unmap (without deallocating VM) one guard page so that attempts to access it fail with a + // non-present page fault. + kdbgln("stack guard page: %p", (void*)address); + + // The actual stack. + Stack stack { address + ARCH_PAGE_SIZE, BOOTSTRAP_STACK_PAGES * ARCH_PAGE_SIZE }; + + return stack.top(); +} + extern "C" [[noreturn]] void _start() { Init::check_magic(); Init::early_init(); - Stack stack { MemoryManager::alloc_for_kernel(8, MMU::ReadWrite | MMU::NoExecute).value(), 8 * ARCH_PAGE_SIZE }; - CPU::bootstrap_switch_stack(stack.top(), (void*)init_wrapper); + u64 bootstrap_stack_top = allocate_initial_kernel_stack(); + CPU::bootstrap_switch_stack(bootstrap_stack_top, (void*)init_wrapper); }