From: Tulio A M Mendes Date: Mon, 16 Feb 2026 17:47:10 +0000 (-0300) Subject: fix: replace pmm_alloc_page_low with pmm_alloc_page — fix fork OOM X-Git-Url: https://projects.tadryanom.me/docs/static/git-logo.png?a=commitdiff_plain;h=1860e2786ecdc08dc0d96b797d67d96fc99cc405;p=AdrOS.git fix: replace pmm_alloc_page_low with pmm_alloc_page — fix fork OOM The below-16MB page allocator (pmm_alloc_page_low) randomly sampled pages and discarded any above 16MB. With 100 zombie children holding CoW address spaces, the low-memory pool exhausted and fork() returned -ENOMEM, killing init before the SIGSEGV/waitpid-100/echo.elf tests. On 32-bit PAE all physical addresses are below 4GB, so the 16MB restriction is unnecessary for PDPTs, page directories, page tables, and user frames. Changes: - vmm.c: replace all pmm_alloc_page_low() with pmm_alloc_page(), remove the dead pmm_alloc_page_low function - usermode.c: replace pmm_alloc_page_low_16mb() with pmm_alloc_page(), remove the dead function - init.c: make SIGSEGV test failure non-fatal (goto instead of sys_exit) so subsequent tests still run 83/83 smoke tests pass (10s), cppcheck clean. --- diff --git a/src/arch/x86/usermode.c b/src/arch/x86/usermode.c index 28a1547..8638684 100644 --- a/src/arch/x86/usermode.c +++ b/src/arch/x86/usermode.c @@ -60,17 +60,7 @@ static void patch_rel8(uint8_t* buf, size_t at, size_t target) { buf[at] = (uint8_t)(int8_t)rel; } -static void* pmm_alloc_page_low_16mb(void) { - for (int tries = 0; tries < 4096; tries++) { - void* p = pmm_alloc_page(); - if (!p) return NULL; - if ((uintptr_t)p < 0x01000000U) { - return p; - } - pmm_free_page(p); - } - return NULL; -} +/* User pages can be anywhere in physical memory on 32-bit PAE. */ __attribute__((noreturn)) void x86_enter_usermode(uintptr_t user_eip, uintptr_t user_esp) { kprintf("[USER] enter ring3 eip=0x%x esp=0x%x\n", @@ -148,8 +138,8 @@ void x86_usermode_test_start(void) { const uintptr_t user_code_vaddr = 0x00400000U; const uintptr_t user_stack_vaddr = 0x00800000U; - void* code_phys = pmm_alloc_page_low_16mb(); - void* stack_phys = pmm_alloc_page_low_16mb(); + void* code_phys = pmm_alloc_page(); + void* stack_phys = pmm_alloc_page(); if (!code_phys || !stack_phys) { kprintf("[USER] OOM allocating user pages.\n"); return; diff --git a/src/arch/x86/vmm.c b/src/arch/x86/vmm.c index 1e5da38..cc3c76d 100644 --- a/src/arch/x86/vmm.c +++ b/src/arch/x86/vmm.c @@ -101,18 +101,6 @@ static uint64_t vmm_flags_to_x86(uint32_t flags) { return x86_flags; } -/* --- Low-memory page allocator --- */ - -static void* pmm_alloc_page_low(void) { - for (int tries = 0; tries < 1024; tries++) { - void* p = pmm_alloc_page(); - if (!p) return 0; - if ((uintptr_t)p < 0x01000000) return p; - pmm_free_page(p); - } - return 0; -} - /* User space covers PDPT indices 0-2 (0x00000000 - 0xBFFFFFFF). * PDPT[3] is kernel (0xC0000000 - 0xFFFFFFFF). */ #define PAE_USER_PDPT_MAX 3 @@ -225,7 +213,7 @@ uintptr_t vmm_as_create_kernel_clone(void) { uintptr_t irqf = spin_lock_irqsave(&vmm_lock); /* Allocate PDPT (32 bytes, but occupies one page for simplicity) */ - uint32_t pdpt_phys = (uint32_t)(uintptr_t)pmm_alloc_page_low(); + uint32_t pdpt_phys = (uint32_t)(uintptr_t)pmm_alloc_page(); if (!pdpt_phys) { spin_unlock_irqrestore(&vmm_lock, irqf); return 0; @@ -234,7 +222,7 @@ uintptr_t vmm_as_create_kernel_clone(void) { /* Allocate 4 page directories */ uint32_t pd_phys[4]; for (int i = 0; i < 4; i++) { - pd_phys[i] = (uint32_t)(uintptr_t)pmm_alloc_page_low(); + pd_phys[i] = (uint32_t)(uintptr_t)pmm_alloc_page(); if (!pd_phys[i]) { for (int j = 0; j < i; j++) pmm_free_page((void*)(uintptr_t)pd_phys[j]); pmm_free_page((void*)(uintptr_t)pdpt_phys); @@ -366,7 +354,7 @@ uintptr_t vmm_as_clone_user(uintptr_t src_as) { if (pte & X86_PTE_RW) flags |= VMM_FLAG_RW; if (pte & X86_PTE_USER) flags |= VMM_FLAG_USER; - void* dst_frame = pmm_alloc_page_low(); + void* dst_frame = pmm_alloc_page(); if (!dst_frame) { vmm_as_activate(old_as); spin_unlock_irqrestore(&vmm_lock, irqf); diff --git a/user/init.c b/user/init.c index 819298a..b36fa42 100644 --- a/user/init.c +++ b/user/init.c @@ -3742,7 +3742,7 @@ void _start(void) { if (pid < 0) { static const char msg[] = "[init] sigsegv test fork failed\n"; (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1)); - sys_exit(1); + goto sigsegv_done; } if (pid == 0) { @@ -3770,8 +3770,8 @@ void _start(void) { } else { static const char msg[] = "[init] SIGSEGV failed\n"; (void)sys_write(1, msg, (uint32_t)(sizeof(msg) - 1)); - sys_exit(1); } + sigsegv_done:; } int ok = 1;