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/?a=commitdiff_plain;h=cbdef4a3aea5918900524c178d6a0c915b42ce9a;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 585d53f2..9da314f3 100644 --- a/src/arch/x86/usermode.c +++ b/src/arch/x86/usermode.c @@ -69,17 +69,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", @@ -157,8 +147,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 51fe28a1..8bb7ad55 100644 --- a/src/arch/x86/vmm.c +++ b/src/arch/x86/vmm.c @@ -110,18 +110,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 @@ -234,7 +222,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; @@ -243,7 +231,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); @@ -375,7 +363,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 d2cd7a83..d515fe90 100644 --- a/user/init.c +++ b/user/init.c @@ -3751,7 +3751,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) { @@ -3779,8 +3779,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;