From 87e116e2d3caabd2ffcb719c5d10bd9f62b1d5a0 Mon Sep 17 00:00:00 2001 From: Tulio A M Mendes Date: Sun, 15 Feb 2026 04:45:02 -0300 Subject: [PATCH] =?utf8?q?feat:=20vmm=5Ffind=5Ffree=5Farea()=20=E2=80=94?= =?utf8?q?=20page-table-level=20scan=20for=20unmapped=20VA=20regions?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- include/vmm.h | 7 +++++++ src/arch/x86/vmm.c | 38 ++++++++++++++++++++++++++++++++++++++ src/kernel/syscall.c | 16 +--------------- 3 files changed, 46 insertions(+), 15 deletions(-) diff --git a/include/vmm.h b/include/vmm.h index 7895d14..fcd808e 100644 --- a/include/vmm.h +++ b/include/vmm.h @@ -63,4 +63,11 @@ void vmm_protect_range(uint64_t vaddr, uint64_t len, uint32_t flags); */ void vmm_unmap_page(uint64_t virt); +/* + * Find a contiguous free (unmapped) virtual address region. + * Scans page tables from 'start' up to 'end' for 'length' bytes of + * contiguous unmapped pages. Returns the base VA, or 0 on failure. + */ +uintptr_t vmm_find_free_area(uintptr_t start, uintptr_t end, uint32_t length); + #endif diff --git a/src/arch/x86/vmm.c b/src/arch/x86/vmm.c index 4691a3a..7a42ae9 100644 --- a/src/arch/x86/vmm.c +++ b/src/arch/x86/vmm.c @@ -513,6 +513,44 @@ int vmm_handle_cow_fault(uintptr_t fault_addr) { return 1; } +uintptr_t vmm_find_free_area(uintptr_t start, uintptr_t end, uint32_t length) { + if (length == 0) return 0; + uint32_t pages_needed = (length + 0xFFFU) >> 12; + + uintptr_t irqf = spin_lock_irqsave(&vmm_lock); + + uintptr_t run_start = start & ~(uintptr_t)0xFFF; + uint32_t run_len = 0; + + for (uintptr_t va = run_start; va < end; va += 0x1000U) { + uint32_t pi = pae_pdpt_index((uint64_t)va); + uint32_t di = pae_pd_index((uint64_t)va); + uint32_t ti = pae_pt_index((uint64_t)va); + + int mapped = 0; + volatile uint64_t* pd = pae_pd_recursive(pi); + if (pd[di] & X86_PTE_PRESENT) { + volatile uint64_t* pt = pae_pt_recursive(pi, di); + if (pt[ti] & X86_PTE_PRESENT) + mapped = 1; + } + + if (!mapped) { + if (run_len == 0) run_start = va; + run_len++; + if (run_len >= pages_needed) { + spin_unlock_irqrestore(&vmm_lock, irqf); + return run_start; + } + } else { + run_len = 0; + } + } + + spin_unlock_irqrestore(&vmm_lock, irqf); + return 0; +} + void vmm_init(void) { kprintf("[VMM] PAE paging active.\n"); diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index acb5f17..64868a1 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -2267,21 +2267,7 @@ static uintptr_t mmap_find_free(uint32_t length) { const uintptr_t MMAP_BASE = 0x40000000U; const uintptr_t MMAP_END = 0x7FF00000U; - for (uintptr_t candidate = MMAP_BASE; candidate + length <= MMAP_END; candidate += 0x1000U) { - int overlap = 0; - for (int i = 0; i < PROCESS_MAX_MMAPS; i++) { - if (current_process->mmaps[i].length == 0) continue; - uintptr_t mb = current_process->mmaps[i].base; - uint32_t ml = current_process->mmaps[i].length; - if (candidate < mb + ml && candidate + length > mb) { - overlap = 1; - candidate = ((mb + ml + 0xFFFU) & ~(uintptr_t)0xFFFU) - 0x1000U; - break; - } - } - if (!overlap) return candidate; - } - return 0; + return vmm_find_free_area(MMAP_BASE, MMAP_END, length); } __attribute__((noinline)) -- 2.43.0