:: commit 18e39282e0fa3f91a891125e5ed1ebcbcf8f0b8f

Mintsuki <mintsuki@protonmail.com> — 2026-02-07 08:03

parents: 190283949c

mm/pmm: Stop mmap_get_info() at first memory hole per Multiboot spec

diff --git a/common/mm/pmm.s2.c b/common/mm/pmm.s2.c
index 55d12ef9..a309dbb5 100644
--- a/common/mm/pmm.s2.c
+++ b/common/mm/pmm.s2.c
@@ -690,25 +690,35 @@ void *ext_mem_alloc_type_aligned_mode(uint64_t count, uint32_t type, size_t alig
 struct meminfo mmap_get_info(size_t mmap_count, struct memmap_entry *mmap) {
     struct meminfo info = {0};
 
-    for (size_t i = 0; i < mmap_count; i++) {
-        if (mmap[i].type == MEMMAP_USABLE) {
-            // NOTE: Upper memory starts at address 1MiB and the
-            // value of uppermem is the address of the first upper memory
-            // hole minus 1MiB.
-            if (mmap[i].base < 0x100000) {
-                if (mmap[i].base + mmap[i].length > 0x100000) {
-                    size_t low_len = 0x100000 - mmap[i].base;
-
-                    info.lowermem += low_len;
-                    info.uppermem += mmap[i].length - low_len;
-                } else {
-                    info.lowermem += mmap[i].length;
-                }
-            } else {
-                info.uppermem += mmap[i].length;
+    // Find contiguous usable memory from address 0 (lower) and 1 MiB (upper)
+    // by iteratively extending a frontier. Handles unsorted entries.
+    uint64_t lower_end = 0;
+    uint64_t upper_end = 0x100000;
+    bool progress;
+
+    do {
+        progress = false;
+        for (size_t i = 0; i < mmap_count; i++) {
+            if (mmap[i].type != MEMMAP_USABLE)
+                continue;
+            uint64_t base = mmap[i].base;
+            uint64_t top = base + mmap[i].length;
+            if (base <= lower_end && top > lower_end) {
+                lower_end = top;
+                progress = true;
+            }
+            if (base <= upper_end && top > upper_end) {
+                upper_end = top;
+                progress = true;
             }
         }
-    }
+    } while (progress);
+
+    if (lower_end > 0x100000)
+        lower_end = 0x100000;
+
+    info.lowermem = lower_end;
+    info.uppermem = upper_end - 0x100000;
 
     return info;
 }
tab: 248 wrap: offon