add a class to allocate and manage user space stacks

This commit is contained in:
Drew Galbraith 2023-05-30 22:35:57 -07:00
parent 1db93e5b12
commit 2eefda6114
6 changed files with 67 additions and 7 deletions

View File

@ -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

View File

@ -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_);
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <stdint.h>
// 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;
};

View File

@ -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();
}

View File

@ -3,6 +3,7 @@
#include <stdint.h>
#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;
};

View File

@ -26,7 +26,6 @@ SharedPtr<Thread> 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<uint64_t>(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);
}