:: commit d28e93f2575a2ee4e8748222b2d1b20d2aa56055

mintsuki <mintsuki@protonmail.com> — 2021-11-03 01:32

parents: dc1d6a3c61

pmm: Better handling of creating new memmap entries

diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 11bfbeba..0b924f85 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -419,6 +419,15 @@ void pmm_reclaim_uefi_mem(void) {
         for (size_t j = 0; j < entry_count; j++) {
             EFI_MEMORY_DESCRIPTOR *entry = (void *)efi_mmap + j * efi_desc_size;
 
+            switch (entry->Type) {
+                case EfiBootServicesCode:
+                case EfiBootServicesData:
+                case EfiConventionalMemory:
+                    break;
+                default:
+                    continue;
+            }
+
             uintptr_t base = memmap[i].base;
             uintptr_t top = base + memmap[i].length;
             uintptr_t efi_base = entry->PhysicalStart;
@@ -429,12 +438,7 @@ void pmm_reclaim_uefi_mem(void) {
                && top  >  efi_base && top  <= efi_top))
                 continue;
 
-            switch (entry->Type) {
-                case EfiBootServicesCode:
-                case EfiBootServicesData:
-                case EfiConventionalMemory:
-                    memmap[i].type = MEMMAP_USABLE; break;
-            }
+            memmap[i].type = MEMMAP_USABLE;
         }
     }
 
@@ -674,6 +678,73 @@ struct meminfo mmap_get_info(size_t mmap_count, struct e820_entry_t *mmap) {
     return info;
 }
 
+static bool pmm_new_entry(uint64_t base, uint64_t length, uint32_t type) {
+    uint64_t top = base + length;
+
+    // Handle overlapping new entries.
+    for (size_t i = 0; i < memmap_entries; i++) {
+        uint64_t entry_base = memmap[i].base;
+        uint64_t entry_top  = memmap[i].base + memmap[i].length;
+
+        // Full overlap
+        if (base <= entry_base && top >= entry_top) {
+            // Remove overlapped entry
+            for (size_t j = i + 1; j < memmap_entries; j++) {
+                memmap[j - 1] = memmap[j];
+            }
+            memmap_entries--;
+            i--;
+            continue;
+        }
+
+        // Partial overlap (bottom)
+        if (base <= entry_base && top < entry_top && top > entry_base) {
+            // Entry gets bottom shaved off
+            memmap[i].base += top - entry_base;
+            memmap[i].length -= top - entry_base;
+            continue;
+        }
+
+        // Partial overlap (top)
+        if (base > entry_base && base < entry_top && top >= entry_top) {
+            // Entry gets top shaved off
+            memmap[i].length -= entry_top - base;
+            continue;
+        }
+
+        // Nested (pain)
+        if (base > entry_base && top < entry_top) {
+            // Entry gets top shaved off first
+            memmap[i].length -= entry_top - base;
+
+            // Now we need to create a new entry
+            if (memmap_entries >= memmap_max_entries)
+                panic("Memory map exhausted.");
+
+            struct e820_entry_t *new_entry = &memmap[memmap_entries++];
+
+            new_entry->type = memmap[i].type;
+            new_entry->base = top;
+            new_entry->length = entry_top - top;
+
+            continue;
+        }
+    }
+
+    if (memmap_entries >= memmap_max_entries)
+        panic("Memory map exhausted.");
+
+    struct e820_entry_t *target = &memmap[memmap_entries++];
+
+    target->type = type;
+    target->base = base;
+    target->length = length;
+
+    sanitise_entries(memmap, &memmap_entries, false);
+
+    return true;
+}
+
 bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free_only, bool do_panic, bool simulation, bool new_entry) {
     if (length == 0)
         return true;
@@ -730,18 +801,7 @@ bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free
         panic("Memory allocation failure.");
 
     if (new_entry) {
-        if (memmap_entries >= memmap_max_entries)
-            panic("Memory map exhausted.");
-
-        struct e820_entry_t *target = &memmap[memmap_entries++];
-
-        target->type = type;
-        target->base = base;
-        target->length = length;
-
-        sanitise_entries(memmap, &memmap_entries, false);
-
-        return true;
+        return pmm_new_entry(base, length, type);
     }
 
     return false;
tab: 248 wrap: offon