From 2eefda61143701d43bf97d2d871a0879b5e0ea63 Mon Sep 17 00:00:00 2001 From: Drew Galbraith Date: Tue, 30 May 2023 22:35:57 -0700 Subject: [PATCH] add a class to allocate and manage user space stacks --- zion/CMakeLists.txt | 1 + zion/memory/user_stack_manager.cpp | 23 +++++++++++++++++++++++ zion/memory/user_stack_manager.h | 30 ++++++++++++++++++++++++++++++ zion/memory/virtual_memory.cpp | 8 ++++++-- zion/memory/virtual_memory.h | 8 ++++++-- zion/scheduler/thread.cpp | 4 +--- 6 files changed, 67 insertions(+), 7 deletions(-) create mode 100644 zion/memory/user_stack_manager.cpp create mode 100644 zion/memory/user_stack_manager.h diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 8b65123..cfc5cfa 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -12,6 +12,7 @@ add_executable(zion memory/kernel_stack_manager.cpp memory/paging_util.cpp memory/physical_memory.cpp + memory/user_stack_manager.cpp memory/virtual_memory.cpp scheduler/context_switch.s scheduler/jump_user_space.s diff --git a/zion/memory/user_stack_manager.cpp b/zion/memory/user_stack_manager.cpp new file mode 100644 index 0000000..b6f1dc2 --- /dev/null +++ b/zion/memory/user_stack_manager.cpp @@ -0,0 +1,23 @@ +#include "memory/user_stack_manager.h" + +#include "debug/debug.h" +#include "memory/paging_util.h" + +uint64_t UserStackManager::NewUserStack() { + uint64_t stack = next_stack_; + next_stack_ -= kStackSize; + if (stack <= kStackMin) { + panic("Out of user stacks!"); + } + if (stack == kStackMax) { + // Add a additional page boudary between kernel and user space. + stack -= 0x1000; + } + EnsureResident(stack - 1, 1); + return stack; +} + +void UserStackManager::FreeUserStack(uint64_t stack_ptr) { + freed_stacks_++; + dbgln("%u freed user stacks", freed_stacks_); +} diff --git a/zion/memory/user_stack_manager.h b/zion/memory/user_stack_manager.h new file mode 100644 index 0000000..ebd47bf --- /dev/null +++ b/zion/memory/user_stack_manager.h @@ -0,0 +1,30 @@ +#pragma once + +#include + +// Per-process class to manage user stacks. +// +// User stacks live at +// 0x00007FF0 00000000 - 0x00007FFF FFFFFFFF +// and grow downwards. +// +// Each user stack gets 1 MiB (0x100000 bytes) +// less a page boundary. +// with 1 page allocated at a time. +// TODO: consider increasing this. +class UserStackManager { + public: + UserStackManager() {} + UserStackManager(const UserStackManager&) = delete; + + uint64_t NewUserStack(); + void FreeUserStack(uint64_t stack_ptr); + + private: + const uint64_t kStackMax = 0x00008000'00000000; + const uint64_t kStackMin = 0x00007FF0'00000000; + const uint64_t kStackSize = 0x100000; + + uint64_t next_stack_ = kStackMax; + uint64_t freed_stacks_ = 0; +}; diff --git a/zion/memory/virtual_memory.cpp b/zion/memory/virtual_memory.cpp index 61ba1d9..b780a7c 100644 --- a/zion/memory/virtual_memory.cpp +++ b/zion/memory/virtual_memory.cpp @@ -17,8 +17,8 @@ VirtualMemory::VirtualMemory() { InitializePml4(cr3_); } -uint64_t* VirtualMemory::AllocateKernelStack() { - return gKernelStackManager->AllocateKernelStack(); +uint64_t VirtualMemory::AllocateUserStack() { + return user_stacks_.NewUserStack(); } uint64_t VirtualMemory::GetNextMemMapAddr(uint64_t size) { @@ -29,3 +29,7 @@ uint64_t VirtualMemory::GetNextMemMapAddr(uint64_t size) { } return addr; } + +uint64_t* VirtualMemory::AllocateKernelStack() { + return gKernelStackManager->AllocateKernelStack(); +} diff --git a/zion/memory/virtual_memory.h b/zion/memory/virtual_memory.h index e6ac097..4ab68f0 100644 --- a/zion/memory/virtual_memory.h +++ b/zion/memory/virtual_memory.h @@ -3,6 +3,7 @@ #include #include "debug/debug.h" +#include "memory/user_stack_manager.h" // VirtualMemory class holds a memory space for an individual process. // @@ -15,7 +16,7 @@ // 0x00000010 00000000 - 0x0000001F FFFFFFFF : USER_HEAP (64 GiB) // 0x00000020 00000000 - 0x0000002F FFFFFFFF : MEM_MAP (64 GiB) // 0x00000040 00000000 - 0x0000004F FFFFFFFF : IPC_BUF (64 GiB) -// 0x00007FFF 00000000 - 0x00007FFF FFFFFFFF : USER_STACK (64 GiB) +// 0x00007FF0 00000000 - 0x00007FFF FFFFFFFF : USER_STACK (64 GiB) // // Kernel Regions (Shared across processes): // 0xFFFF8000 00000000 - 0xFFFF800F FFFFFFFF : HHDM (64 GiB) @@ -46,14 +47,17 @@ class VirtualMemory { uint64_t cr3() { return cr3_; } + // User Mappings. + uint64_t AllocateUserStack(); uint64_t GetNextMemMapAddr(uint64_t size); - // Kernel + // Kernel Mappings. uint64_t* AllocateKernelStack(); private: VirtualMemory(uint64_t cr3) : cr3_(cr3) {} uint64_t cr3_ = 0; + UserStackManager user_stacks_; uint64_t next_memmap_addr_ = 0x20'00000000; }; diff --git a/zion/scheduler/thread.cpp b/zion/scheduler/thread.cpp index f17abc3..6db84de 100644 --- a/zion/scheduler/thread.cpp +++ b/zion/scheduler/thread.cpp @@ -26,7 +26,6 @@ SharedPtr Thread::RootThread(Process& root_proc) { Thread::Thread(Process& proc, uint64_t tid, uint64_t entry) : process_(proc), id_(tid), rip_(entry) { uint64_t* stack_ptr = proc.vmm().AllocateKernelStack(); - dbgln("Kernel Stack at: %m", stack_ptr); // 0: rip *(stack_ptr) = reinterpret_cast(thread_init); // 1-4: rax, rcx, rdx, rbx @@ -43,8 +42,7 @@ uint64_t Thread::pid() const { return process_.id(); } void Thread::Init() { dbgln("[%u.%u] thread start.", pid(), id_); - uint64_t rsp = 0x80000000; - EnsureResident(rsp - 1, 1); + uint64_t rsp = process_.vmm().AllocateUserStack(); SetRsp0(rsp0_start_); jump_user_space(rip_, rsp); }