]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commitdiff
feat: vmm_find_free_area() — page-table-level scan for unmapped VA regions
authorTulio A M Mendes <[email protected]>
Sun, 15 Feb 2026 07:45:02 +0000 (04:45 -0300)
committerTulio A M Mendes <[email protected]>
Sun, 15 Feb 2026 07:45:02 +0000 (04:45 -0300)
include/vmm.h
src/arch/x86/vmm.c
src/kernel/syscall.c

index 7895d14e0fcde65027271a5542561956b1376ac3..fcd808eeb7f8b0d9a38a92570f176ed0998cee6f 100644 (file)
@@ -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
index 4691a3a6c5a6b5887cc613dd231854e53db85495..7a42ae9b90575ab498ad27ec6dd58b2da7fa572b 100644 (file)
@@ -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");
 
index acb5f172d2ac1bfe5ce617b3be898274c740ea29..64868a16f7d29fa883c12db33510cc010ea82aed 100644 (file)
@@ -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))