diff --git a/boredos.iso b/boredos.iso index f61673b..4ac2914 100644 Binary files a/boredos.iso and b/boredos.iso differ diff --git a/build/main.o b/build/main.o index b06f10a..257cc76 100644 Binary files a/build/main.o and b/build/main.o differ diff --git a/disk.img b/disk.img index ad3faaa..b819479 100644 Binary files a/disk.img and b/disk.img differ diff --git a/src/kernel/paging.c b/src/kernel/paging.c index 9143534..1394068 100644 --- a/src/kernel/paging.c +++ b/src/kernel/paging.c @@ -22,16 +22,10 @@ static void write_cr3(uint64_t cr3) { // Helper to allocate a page table and clear it static uint64_t alloc_page_table_phys(void) { - void* ptr = kmalloc(PAGE_SIZE * 2); + void *ptr = kmalloc_aligned(PAGE_SIZE, PAGE_SIZE); if (!ptr) return 0; - // Align to PAGE_SIZE virtually - uintptr_t addr = (uintptr_t)ptr; - if (addr % PAGE_SIZE != 0) { - addr = (addr + PAGE_SIZE) & ~(PAGE_SIZE - 1); - } - - page_table_t* table = (page_table_t*)addr; + page_table_t* table = (page_table_t*)ptr; // Clear table for (int i = 0; i < 512; i++) { @@ -120,3 +114,44 @@ uint64_t paging_create_user_pml4_phys(void) { // The lower half (0-255) is left empty for the user process to use return new_pml4_phys; } + +void paging_destroy_user_pml4_phys(uint64_t pml4_phys) { + if (!pml4_phys) return; + page_table_t* pml4 = (page_table_t*)p2v(pml4_phys); + + // Only traverse lower half (user space, indices 0-255) + for (int pml4_idx = 0; pml4_idx < 256; pml4_idx++) { + if (pml4->entries[pml4_idx] & PT_PRESENT) { + page_table_t* pdpt = (page_table_t*)p2v(pml4->entries[pml4_idx] & PT_ADDR_MASK); + + for (int pdpt_idx = 0; pdpt_idx < 512; pdpt_idx++) { + if (pdpt->entries[pdpt_idx] & PT_PRESENT) { + page_table_t* pd = (page_table_t*)p2v(pdpt->entries[pdpt_idx] & PT_ADDR_MASK); + + for (int pd_idx = 0; pd_idx < 512; pd_idx++) { + if (pd->entries[pd_idx] & PT_PRESENT) { + page_table_t* pt = (page_table_t*)p2v(pd->entries[pd_idx] & PT_ADDR_MASK); + + for (int pt_idx = 0; pt_idx < 512; pt_idx++) { + if (pt->entries[pt_idx] & PT_PRESENT) { + uint64_t phys_addr = pt->entries[pt_idx] & PT_ADDR_MASK; + extern void kfree(void* ptr); + kfree((void*)p2v(phys_addr)); + } + } + extern void kfree(void* ptr); + kfree((void*)pt); + } + } + extern void kfree(void* ptr); + kfree((void*)pd); + } + } + extern void kfree(void* ptr); + kfree((void*)pdpt); + } + } + // Finally free the pml4 itself + extern void kfree(void* ptr); + kfree((void*)pml4); +} diff --git a/src/kernel/paging.h b/src/kernel/paging.h index a8f42a1..be2ff1d 100644 --- a/src/kernel/paging.h +++ b/src/kernel/paging.h @@ -27,19 +27,16 @@ typedef struct { uint64_t entries[512]; } __attribute__((aligned(PAGE_SIZE))) page_table_t; -// Get the current PML4 physical address uint64_t paging_get_pml4_phys(void); -// Map a physical address to a virtual address void paging_map_page(uint64_t pml4_phys, uint64_t virtual_addr, uint64_t physical_addr, uint64_t flags); -// Create a new, isolated PML4 for a user process (returns physical address) uint64_t paging_create_user_pml4_phys(void); -// Switch the active page table (takes physical address) void paging_switch_directory(uint64_t pml4_phys); -// Initialize paging system (if needed beyond Limine's setup) +void paging_destroy_user_pml4_phys(uint64_t pml4_phys); + void paging_init(void); #endif // PAGING_H diff --git a/src/kernel/process.c b/src/kernel/process.c index 5337624..2e37864 100644 --- a/src/kernel/process.c +++ b/src/kernel/process.c @@ -19,6 +19,7 @@ process_t processes[MAX_PROCESSES] __attribute__((aligned(16))); int process_count = 0; static process_t* current_process = NULL; static uint32_t next_pid = 0; +static void *free_kernel_stack_later = NULL; void process_init(void) { for (int i = 0; i < MAX_PROCESSES; i++) { @@ -329,6 +330,11 @@ process_t* process_get_current(void) { } uint64_t process_schedule(uint64_t current_rsp) { + if (free_kernel_stack_later) { + kfree(free_kernel_stack_later); + free_kernel_stack_later = NULL; + } + if (!current_process || !current_process->next || current_process == current_process->next) return current_rsp; @@ -433,9 +439,22 @@ void process_terminate(process_t *to_delete) { to_delete->pid = 0xFFFFFFFF; if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc); - if (to_delete->kernel_stack_alloc) kfree(to_delete->kernel_stack_alloc); + if (to_delete->kernel_stack_alloc) { + if (to_delete == current_process) { + free_kernel_stack_later = to_delete->kernel_stack_alloc; + } else { + kfree(to_delete->kernel_stack_alloc); + } + } + + extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys); + if (to_delete->pml4_phys && to_delete->is_user) { + paging_destroy_user_pml4_phys(to_delete->pml4_phys); + } + to_delete->user_stack_alloc = NULL; to_delete->kernel_stack_alloc = NULL; + to_delete->pml4_phys = 0; asm volatile("push %0; popfq" : : "r"(rflags)); } @@ -486,9 +505,16 @@ uint64_t process_terminate_current(void) { // kernel stack is unsafe while we are still running on it. if (to_delete->user_stack_alloc) kfree(to_delete->user_stack_alloc); + extern void paging_destroy_user_pml4_phys(uint64_t pml4_phys); + if (to_delete->pml4_phys && to_delete->is_user) { + paging_destroy_user_pml4_phys(to_delete->pml4_phys); + } + // Clear pointers to avoid double-free during slot reuse to_delete->user_stack_alloc = NULL; + free_kernel_stack_later = to_delete->kernel_stack_alloc; to_delete->kernel_stack_alloc = NULL; // Leak the small kernel stack for safety + to_delete->pml4_phys = 0; uint64_t next_rsp = current_process->rsp; asm volatile("push %0; popfq" : : "r"(rflags));