From: Tulio A M Mendes Date: Sun, 15 Feb 2026 07:45:02 +0000 (-0300) Subject: feat: vmm_find_free_area() — page-table-level scan for unmapped VA regions X-Git-Url: https://projects.tadryanom.me/sitemap.xml?a=commitdiff_plain;h=87e116e2d3caabd2ffcb719c5d10bd9f62b1d5a0;p=AdrOS.git feat: vmm_find_free_area() — page-table-level scan for unmapped VA regions --- 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))