:: commit 4e4017fb134412d95643c77e0dcd95b5188da159

mintsuki <mintsuki@protonmail.com> — 2021-04-15 00:21

parents: d9466f3d25

pmm: Rework conventional memory allocator

diff --git a/stage23/drivers/disk.s2.c b/stage23/drivers/disk.s2.c
index d3a41c06..a5ca3d7f 100644
--- a/stage23/drivers/disk.s2.c
+++ b/stage23/drivers/disk.s2.c
@@ -32,7 +32,7 @@ struct dap {
     uint64_t lba;
 };
 
-static struct dap *dap = NULL;
+static struct dap dap = {0};
 
 #define XFER_BUF_SIZE 16384
 static void *xfer_buf = NULL;
@@ -42,24 +42,19 @@ bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t
         panic("XFER");
 
     if (xfer_buf == NULL)
-        xfer_buf = conv_mem_alloc_aligned(XFER_BUF_SIZE, 16);
+        xfer_buf = conv_mem_alloc(XFER_BUF_SIZE);
 
-    if (dap == NULL) {
-        dap = conv_mem_alloc(sizeof(struct dap));
-        dap->size = 16;
-    }
-
-    dap->count = count;
-
-    dap->segment = rm_seg(xfer_buf);
-    dap->offset  = rm_off(xfer_buf);
-    dap->lba     = block;
+    dap.size    = 16;
+    dap.count   = count;
+    dap.segment = rm_seg(xfer_buf);
+    dap.offset  = rm_off(xfer_buf);
+    dap.lba     = block;
 
     struct rm_regs r = {0};
     r.eax = 0x4200;
     r.edx = volume->drive;
-    r.esi = (uint32_t)rm_off(dap);
-    r.ds  = rm_seg(dap);
+    r.esi = (uint32_t)rm_off(&dap);
+    r.ds  = rm_seg(&dap);
 
     rm_int(0x13, &r, &r);
 
@@ -70,7 +65,7 @@ bool disk_read_sectors(struct volume *volume, void *buf, uint64_t block, size_t
                 return false;
             default:
                 panic("Disk error %x. Drive %x, LBA %x.",
-                      ah, volume->drive, dap->lba);
+                      ah, volume->drive, dap.lba);
         }
     }
 
diff --git a/stage23/drivers/edid.c b/stage23/drivers/edid.c
index 27b29617..398561d8 100644
--- a/stage23/drivers/edid.c
+++ b/stage23/drivers/edid.c
@@ -11,7 +11,10 @@
 #include <lib/real.h>
 
 struct edid_info_struct *get_edid_info(void) {
-    struct edid_info_struct *buf = conv_mem_alloc(sizeof(struct edid_info_struct));
+    static struct edid_info_struct *buf = NULL;
+
+    if (buf == NULL)
+        buf = conv_mem_alloc(sizeof(struct edid_info_struct));
 
     struct rm_regs r = {0};
 
diff --git a/stage23/entry.s2.c b/stage23/entry.s2.c
index a4dbb0de..5efa5760 100644
--- a/stage23/entry.s2.c
+++ b/stage23/entry.s2.c
@@ -70,6 +70,9 @@ enum {
 
 __attribute__((noreturn))
 void entry(uint8_t boot_drive, int boot_from) {
+    init_e820();
+    init_memmap();
+
     term_textmode();
 
     print("Limine " LIMINE_VERSION "\n\n");
@@ -79,9 +82,6 @@ void entry(uint8_t boot_drive, int boot_from) {
 
     init_idt();
 
-    init_e820();
-    init_memmap();
-
     disk_create_index();
 
     if (boot_from == BOOTED_FROM_HDD || boot_from == BOOTED_FROM_CD) {
diff --git a/stage23/fs/file.s2.c b/stage23/fs/file.s2.c
index 1e651390..503490b4 100644
--- a/stage23/fs/file.s2.c
+++ b/stage23/fs/file.s2.c
@@ -116,7 +116,7 @@ void *freadall(struct file_handle *fd, uint32_t type) {
         memmap_alloc_range((uint64_t)(size_t)fd->fd, fd->size, type, false, true, false, false);
         return fd->fd;
     } else {
-        void *ret = ext_mem_alloc_aligned_type(fd->size, 4096, type);
+        void *ret = ext_mem_alloc_type(fd->size, type);
         if (fd->read(fd->fd, ret, 0, fd->size)) {
             panic("freadall error");
         }
diff --git a/stage23/lib/part.s2.c b/stage23/lib/part.s2.c
index 860d5073..d2850b24 100644
--- a/stage23/lib/part.s2.c
+++ b/stage23/lib/part.s2.c
@@ -26,8 +26,7 @@ static bool cache_block(struct volume *volume, uint64_t block) {
 
     if (volume->cache == NULL)
         volume->cache =
-            ext_mem_alloc_aligned(BLOCK_SIZE_IN_SECTORS * volume->sector_size,
-                                  4096);
+            ext_mem_alloc(BLOCK_SIZE_IN_SECTORS * volume->sector_size);
 
     if (!disk_read_sectors(volume, volume->cache,
                            volume->first_sect + block * BLOCK_SIZE_IN_SECTORS,
diff --git a/stage23/lib/uri.c b/stage23/lib/uri.c
index cd311a5c..a0237079 100644
--- a/stage23/lib/uri.c
+++ b/stage23/lib/uri.c
@@ -162,7 +162,7 @@ static bool uri_tftp_dispatch(struct file_handle *fd, char *root, char *path) {
         print("\nip: %x\n", ip);
     }
 
-    struct tftp_file_handle *cfg = conv_mem_alloc(sizeof(struct tftp_file_handle));
+    struct tftp_file_handle *cfg = ext_mem_alloc(sizeof(struct tftp_file_handle));
     if(tftp_open(cfg, ip, 69, path)) {
         return false;
     }
@@ -242,7 +242,7 @@ bool uri_open(struct file_handle *fd, char *uri) {
     if (compressed && ret) {
         struct file_handle compressed_fd = {0};
         fread(fd, &compressed_fd.size, fd->size - 4, sizeof(uint32_t));
-        compressed_fd.fd = ext_mem_alloc_aligned(compressed_fd.size, 4096);
+        compressed_fd.fd = ext_mem_alloc(compressed_fd.size);
         void *src = ext_mem_alloc(fd->size);
         fread(fd, src, 0, fd->size);
         if (tinf_gzip_uncompress(compressed_fd.fd, src, fd->size))
diff --git a/stage23/mm/pmm.h b/stage23/mm/pmm.h
index 251c4aa1..871cd095 100644
--- a/stage23/mm/pmm.h
+++ b/stage23/mm/pmm.h
@@ -17,9 +17,6 @@
 #define MEMMAP_FRAMEBUFFER            0x1002
 #define MEMMAP_EFI_RECLAIMABLE        0x2000
 
-extern size_t bump_allocator_base;
-extern size_t bump_allocator_limit;
-
 extern struct e820_entry_t memmap[];
 extern size_t memmap_entries;
 
@@ -30,11 +27,8 @@ bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free
 
 void *ext_mem_alloc(size_t count);
 void *ext_mem_alloc_type(size_t count, uint32_t type);
-void *ext_mem_alloc_aligned(size_t count, size_t alignment);
-void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type);
 
 void *conv_mem_alloc(size_t count);
-void *conv_mem_alloc_aligned(size_t count, size_t alignment);
 
 #if defined (uefi)
 void pmm_reclaim_uefi_mem(void);
diff --git a/stage23/mm/pmm.s2.c b/stage23/mm/pmm.s2.c
index 1f54e2d7..2d968221 100644
--- a/stage23/mm/pmm.s2.c
+++ b/stage23/mm/pmm.s2.c
@@ -11,39 +11,40 @@
 #endif
 
 #define PAGE_SIZE   4096
-#define MEMMAP_BASE ((size_t)0x100000)
 #define MEMMAP_MAX_ENTRIES 256
 
-#define BUMP_ALLOC_LIMIT_HIGH 0x70000
-#define BUMP_ALLOC_LIMIT_LOW  0x1000
-
 #if defined (bios)
 extern symbol bss_end;
-size_t bump_allocator_base = (size_t)bss_end;
-size_t bump_allocator_limit = BUMP_ALLOC_LIMIT_HIGH;
 #endif
 
-#if defined (uefi)
-size_t bump_allocator_base = BUMP_ALLOC_LIMIT_HIGH;
-size_t bump_allocator_limit = BUMP_ALLOC_LIMIT_HIGH;
-#endif
+static bool allocations_disallowed = true;
+static void sanitise_entries(bool align_entries);
 
 void *conv_mem_alloc(size_t count) {
-    return conv_mem_alloc_aligned(count, 4);
-}
+    static uintptr_t base = 4096;
 
-void *conv_mem_alloc_aligned(size_t count, size_t alignment) {
-    size_t new_base = ALIGN_UP(bump_allocator_base, alignment);
-    void *ret = (void *)new_base;
-    new_base += count;
-    if (new_base >= bump_allocator_limit)
-        panic("Memory allocation failed");
-    bump_allocator_base = new_base;
+    if (allocations_disallowed)
+        panic("Memory allocations disallowed");
 
-    // Zero out allocated space
-    memset(ret, 0, count);
+    count = ALIGN_UP(count, 4096);
+
+    for (;;) {
+        if (base + count > 0x100000)
+            panic("Conventional memory allocation failed");
+
+        if (memmap_alloc_range(base, count, MEMMAP_BOOTLOADER_RECLAIMABLE, true, false, false, false)) {
+            void *ret = (void *)base;
+            // Zero out allocated space
+            memset(ret, 0, count);
+            base += count;
+
+            sanitise_entries(false);
+
+            return ret;
+        }
 
-    return ret;
+        base += 4096;
+    }
 }
 
 struct e820_entry_t memmap[MEMMAP_MAX_ENTRIES];
@@ -96,17 +97,6 @@ static bool align_entry(uint64_t *base, uint64_t *length) {
     if (!length)
         return false;
 
-    uint64_t top = *base + *length;
-
-    if (*base < MEMMAP_BASE) {
-        if (top > MEMMAP_BASE) {
-            *length -= MEMMAP_BASE - *base;
-            *base    = MEMMAP_BASE;
-        } else {
-            return false;
-        }
-    }
-
     return true;
 }
 
@@ -209,8 +199,6 @@ static void sanitise_entries(bool align_entries) {
     }
 }
 
-static bool allocations_disallowed = true;
-
 struct e820_entry_t *get_memmap(size_t *entries) {
     sanitise_entries(true);
 
@@ -231,9 +219,15 @@ void init_memmap(void) {
         memmap[memmap_entries++] = e820_map[i];
     }
 
+    // Allocate bootloader itself
+    memmap_alloc_range(4096,
+        ALIGN_UP((uintptr_t)bss_end, 4096) - 4096, MEMMAP_BOOTLOADER_RECLAIMABLE, true, true, false, false);
+
     sanitise_entries(false);
 
     allocations_disallowed = false;
+
+    print_memmap(memmap, memmap_entries);
 }
 #endif
 
@@ -293,30 +287,6 @@ void init_memmap(void) {
         memmap[memmap_entries].length = entry->NumberOfPages * 4096;
 
         memmap_entries++;
-
-        static size_t bump_alloc_pool_size = 0;
-
-        if (our_type != MEMMAP_USABLE || entry->PhysicalStart >= BUMP_ALLOC_LIMIT_HIGH)
-            continue;
-
-        size_t entry_pool_limit = entry->PhysicalStart + entry->NumberOfPages * 4096;
-        if (entry_pool_limit > BUMP_ALLOC_LIMIT_HIGH)
-            entry_pool_limit = BUMP_ALLOC_LIMIT_HIGH;
-
-        size_t entry_pool_start = entry->PhysicalStart;
-        if (entry_pool_start < BUMP_ALLOC_LIMIT_LOW)
-            entry_pool_start = BUMP_ALLOC_LIMIT_LOW;
-
-        if (entry_pool_start > entry_pool_limit)
-            continue;
-
-        size_t entry_pool_size = entry_pool_limit - entry_pool_start;
-
-        if (entry_pool_size > bump_alloc_pool_size) {
-            bump_allocator_base = entry_pool_start;
-            bump_allocator_limit = entry_pool_limit;
-            bump_alloc_pool_size = entry_pool_size;
-        }
     }
 
     sanitise_entries(false);
@@ -324,7 +294,7 @@ void init_memmap(void) {
     allocations_disallowed = false;
 
     // Let's leave 64MiB to the firmware
-    ext_mem_alloc_aligned_type(65536, 4096, MEMMAP_EFI_RECLAIMABLE);
+    ext_mem_alloc_type(65536, MEMMAP_EFI_RECLAIMABLE);
 
     // Now own all the usable entries
     for (size_t i = 0; i < memmap_entries; i++) {
@@ -339,13 +309,6 @@ void init_memmap(void) {
         if (status)
             panic("AllocatePages %x", status);
     }
-
-    memmap_alloc_range(bump_allocator_base,
-                       bump_allocator_limit - bump_allocator_base,
-                       MEMMAP_REMOVE_RANGE, true, true, false, false);
-
-    print("pmm: Conventional mem allocator base:  %X\n", bump_allocator_base);
-    print("pmm: Conventional mem allocator limit: %X\n", bump_allocator_limit);
 }
 
 void pmm_reclaim_uefi_mem(void) {
@@ -364,18 +327,12 @@ void *ext_mem_alloc(size_t count) {
     return ext_mem_alloc_type(count, MEMMAP_BOOTLOADER_RECLAIMABLE);
 }
 
-void *ext_mem_alloc_aligned(size_t count, size_t alignment) {
-    return ext_mem_alloc_aligned_type(count, alignment, MEMMAP_BOOTLOADER_RECLAIMABLE);
-}
-
+// Allocate memory top down, hopefully without bumping into kernel or modules
 void *ext_mem_alloc_type(size_t count, uint32_t type) {
-    return ext_mem_alloc_aligned_type(count, 4, type);
-}
+    count = ALIGN_UP(count, 4096);
 
-// Allocate memory top down, hopefully without bumping into kernel or modules
-void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type) {
     if (allocations_disallowed)
-        panic("Extended memory allocations disallowed");
+        panic("Memory allocations disallowed");
 
     for (int i = memmap_entries - 1; i >= 0; i--) {
         if (memmap[i].type != 1)
@@ -391,7 +348,7 @@ void *ext_mem_alloc_aligned_type(size_t count, size_t alignment, uint32_t type)
                 continue;
         }
 
-        int64_t alloc_base = ALIGN_DOWN(entry_top - (int64_t)count, alignment);
+        int64_t alloc_base = ALIGN_DOWN(entry_top - (int64_t)count, 4096);
 
         // This entry is too small for us.
         if (alloc_base < entry_base)
@@ -420,18 +377,6 @@ bool memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type, bool free
 
     uint64_t top = base + length;
 
-#if defined (bios)
-    if (base < 0x100000) {
-        if (do_panic) {
-            // We don't do allocations below 1 MiB
-            panic("Attempt to allocate memory below 1 MiB (%X-%X)",
-                  base, base + length);
-        } else {
-            return false;
-        }
-    }
-#endif
-
     for (size_t i = 0; i < memmap_entries; i++) {
         if (free_only && memmap[i].type != MEMMAP_USABLE)
             continue;
diff --git a/stage23/mm/vmm.c b/stage23/mm/vmm.c
index ef681d50..7bdbfd28 100644
--- a/stage23/mm/vmm.c
+++ b/stage23/mm/vmm.c
@@ -16,7 +16,7 @@ static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) {
         ret = (pt_entry_t *)(size_t)(current_level[entry] & ~((pt_entry_t)0xfff));
     } else {
         // Allocate a table for the next level
-        ret = ext_mem_alloc_aligned(PT_SIZE, PT_SIZE);
+        ret = ext_mem_alloc(PT_SIZE);
         // Present + writable + user (0b111)
         current_level[entry] = (pt_entry_t)(size_t)ret | 0b111;
     }
@@ -27,7 +27,7 @@ static pt_entry_t *get_next_level(pt_entry_t *current_level, size_t entry) {
 pagemap_t new_pagemap(int lv) {
     pagemap_t pagemap;
     pagemap.levels    = lv;
-    pagemap.top_level = ext_mem_alloc_aligned(PT_SIZE, PT_SIZE);
+    pagemap.top_level = ext_mem_alloc(PT_SIZE);
     return pagemap;
 }
 
diff --git a/stage23/protos/linux.c b/stage23/protos/linux.c
index 7eed3285..6f2c9b6d 100644
--- a/stage23/protos/linux.c
+++ b/stage23/protos/linux.c
@@ -538,23 +538,12 @@ void linux_load(char *config, char *cmdline) {
     size_t memmap_entries;
     struct e820_entry_t *memmap = get_memmap(&memmap_entries);
 
-    boot_params->e820_entries = memmap_entries + 1;
+    boot_params->e820_entries = memmap_entries;
 
-    size_t i = 0;
-
-    e820_table[i].addr = bump_allocator_base;
-    e820_table[i].size = bump_allocator_limit - bump_allocator_base;
-    e820_table[i].type = MEMMAP_USABLE;
-
-    i++;
-
-    for (size_t j = 0; j < memmap_entries; j++) {
-        if (memmap[j].type == MEMMAP_FRAMEBUFFER)
-            continue;
-
-        e820_table[i].addr = memmap[j].base;
-        e820_table[i].size = memmap[j].length;
-        e820_table[i].type = memmap[j].type;
+    for (size_t i = 0; i < memmap_entries; i++) {
+        e820_table[i].addr = memmap[i].base;
+        e820_table[i].size = memmap[i].length;
+        e820_table[i].type = memmap[i].type;
 
         switch (e820_table[i].type) {
             case MEMMAP_BOOTLOADER_RECLAIMABLE:
@@ -562,8 +551,6 @@ void linux_load(char *config, char *cmdline) {
                 e820_table[i].type = MEMMAP_USABLE;
                 break;
         }
-
-        i++;
     }
 
     ///////////////////////////////////////
diff --git a/stage23/protos/stivale2.c b/stage23/protos/stivale2.c
index a2547687..12c32d53 100644
--- a/stage23/protos/stivale2.c
+++ b/stage23/protos/stivale2.c
@@ -440,13 +440,13 @@ skip_modeset:;
     // Create memmap struct tag
     //////////////////////////////////////////////
     {
+    struct stivale2_struct_tag_memmap *tag =
+        ext_mem_alloc(sizeof(struct stivale2_struct_tag_memmap) +
+                       sizeof(struct e820_entry_t) * 256);
+
     size_t memmap_entries;
     struct e820_entry_t *memmap = get_memmap(&memmap_entries);
 
-    struct stivale2_struct_tag_memmap *tag =
-        conv_mem_alloc(sizeof(struct stivale2_struct_tag_memmap) +
-                       sizeof(struct e820_entry_t) * memmap_entries);
-
     tag->tag.identifier = STIVALE2_STRUCT_TAG_MEMMAP_ID;
     tag->entries = (uint64_t)memmap_entries;
 
diff --git a/stage23/sys/e820.h b/stage23/sys/e820.h
index 525d33a2..ae0fb9e9 100644
--- a/stage23/sys/e820.h
+++ b/stage23/sys/e820.h
@@ -11,7 +11,7 @@ struct e820_entry_t {
     uint32_t unused;
 } __attribute__((packed));
 
-extern struct e820_entry_t *e820_map;
+extern struct e820_entry_t e820_map[];
 extern size_t e820_entries;
 
 void init_e820(void);
diff --git a/stage23/sys/e820.s2.c b/stage23/sys/e820.s2.c
index 3fe10629..ae86646d 100644
--- a/stage23/sys/e820.s2.c
+++ b/stage23/sys/e820.s2.c
@@ -8,15 +8,15 @@
 #include <lib/print.h>
 #include <mm/pmm.h>
 
-struct e820_entry_t *e820_map = NULL;
-size_t e820_entries;
+#define MAX_E820_ENTRIES 256
+
+struct e820_entry_t e820_map[MAX_E820_ENTRIES];
+size_t e820_entries = 0;
 
 void init_e820(void) {
     struct rm_regs r = {0};
 
-load_up:
-    // Figure out the number of entries
-    for (size_t i = 0; ; i++) {
+    for (size_t i = 0; i < MAX_E820_ENTRIES; i++) {
         struct e820_entry_t entry;
 
         r.eax = 0xe820;
@@ -27,23 +27,18 @@ load_up:
 
         if (r.eflags & EFLAGS_CF) {
             e820_entries = i;
-            break;
+            return;
         }
 
-        if (e820_map)
-            e820_map[i] = entry;
+        e820_map[i] = entry;
 
         if (!r.ebx) {
             e820_entries = ++i;
-            break;
+            return;
         }
     }
 
-    if (e820_map)
-        return;
-
-    e820_map = conv_mem_alloc(sizeof(struct e820_entry_t) * e820_entries);
-    goto load_up;
+    panic("Too many E820 entries!");
 }
 
 #endif
diff --git a/stage23/sys/smp.c b/stage23/sys/smp.c
index 41056f49..805de7e4 100644
--- a/stage23/sys/smp.c
+++ b/stage23/sys/smp.c
@@ -65,7 +65,7 @@ static bool smp_start_ap(uint32_t lapic_id, struct gdtr *gdtr,
     // Prepare the trampoline
     static void *trampoline = NULL;
     if (trampoline == NULL) {
-        trampoline = conv_mem_alloc_aligned(trampoline_size, 4096);
+        trampoline = conv_mem_alloc(trampoline_size);
 
         memcpy(trampoline, _binary_smp_trampoline_bin_start, trampoline_size);
     }
tab: 248 wrap: offon