Make extended memory allocator allocate top down and mark the allocated areas as bootloader reclaimable
diff --git a/limine.bin b/limine.bin
index 5e7ae201..8f0c09de 100644
Binary files a/limine.bin and b/limine.bin differ
diff --git a/stage2/drivers/vbe.c b/stage2/drivers/vbe.c
index c96eeb35..d3da1003 100644
--- a/stage2/drivers/vbe.c
+++ b/stage2/drivers/vbe.c
@@ -22,7 +22,7 @@ static void vga_font_retrieve(void) {
r.ebx = 0x0600;
rm_int(0x10, &r, &r);
- vga_font = ext_mem_balloc(VGA_FONT_MAX);
+ vga_font = ext_mem_balloc(VGA_FONT_MAX, MEMMAP_BOOTLOADER_RECLAIMABLE);
memcpy(vga_font, (void *)rm_desegment(r.es, r.ebp), VGA_FONT_MAX);
}
@@ -222,7 +222,7 @@ void vbe_tty_init(int *_rows, int *_cols) {
vga_font_retrieve();
*_cols = cols = vbe_width / VGA_FONT_WIDTH;
*_rows = rows = vbe_height / VGA_FONT_HEIGHT;
- grid = ext_mem_balloc(rows * cols * sizeof(struct vbe_char));
+ grid = ext_mem_balloc(rows * cols * sizeof(struct vbe_char), MEMMAP_BOOTLOADER_RECLAIMABLE);
vbe_clear(true);
}
diff --git a/stage2/lib/memmap.c b/stage2/lib/memmap.c
index 696e7e0c..15fffa0b 100644
--- a/stage2/lib/memmap.c
+++ b/stage2/lib/memmap.c
@@ -10,14 +10,6 @@
#define MEMMAP_BASE ((size_t)0x100000)
#define MEMMAP_MAX_ENTRIES 256
-#define MEMMAP_USABLE 1
-#define MEMMAP_RESERVED 2
-#define MEMMAP_ACPI_RECLAIMABLE 3
-#define MEMMAP_ACPI_NVS 4
-#define MEMMAP_BAD_MEMORY 5
-#define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000
-#define MEMMAP_KERNEL_AND_MODULES 0x1001
-
static struct e820_entry_t memmap[MEMMAP_MAX_ENTRIES];
static size_t memmap_entries = 0;
@@ -165,29 +157,39 @@ void init_memmap(void) {
sanitise_entries();
}
-static size_t ext_mem_balloc_base = 0x100000;
-
-void *ext_mem_balloc(size_t count) {
- return ext_mem_balloc_aligned(count, 4);
+void *ext_mem_balloc(size_t count, uint32_t type) {
+ return ext_mem_balloc_aligned(count, 4, type);
}
// TODO: this basically only works for the 1st extended memory entry in the
// memmap and allocates until the first hole following it. Fix that.
-void *ext_mem_balloc_aligned(size_t count, size_t alignment) {
- uint64_t base = ALIGN_UP(ext_mem_balloc_base, alignment);
- uint64_t top = base + count;
-
- for (size_t i = 0; i < memmap_entries; i++) {
+void *ext_mem_balloc_aligned(size_t count, size_t alignment, uint32_t type) {
+ for (int i = memmap_entries - 1; i >= 0; i--) {
if (memmap[i].type != 1)
continue;
- uint64_t entry_base = memmap[i].base;
- uint64_t entry_top = memmap[i].base + memmap[i].length;
- if (base >= entry_base && base < entry_top &&
- top >= entry_base && top < entry_top) {
- ext_mem_balloc_base = base + count;
- return (void *)(size_t)base;
+ int64_t entry_base = (int64_t)(memmap[i].base);
+ int64_t entry_top = (int64_t)(memmap[i].base + memmap[i].length);
+
+ // Let's make sure the entry is not > 4GiB
+ if (entry_base >= 0x100000000 || entry_top >= 0x100000000) {
+ // Theoretically there could be an entry which crosses the 4GiB
+ // boundary, but realistically this does not happen as far as I
+ // have seen. Let's just discard the entry.
+ continue;
}
+
+ int64_t alloc_base = ALIGN_DOWN(entry_top - (int64_t)count, alignment);
+
+ // This entry is too small for us.
+ if (alloc_base < entry_base)
+ continue;
+
+ // We now reserve the range we need.
+ int64_t aligned_length = entry_top - alloc_base;
+ memmap_alloc_range((uint64_t)alloc_base, (uint64_t)aligned_length, type);
+
+ return (void *)(size_t)alloc_base;
}
panic("High memory allocator: Out of memory");
@@ -202,8 +204,8 @@ void memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type) {
uint64_t entry_base = memmap[i].base;
uint64_t entry_top = memmap[i].base + memmap[i].length;
- if (base >= entry_base && base < entry_top &&
- top >= entry_base && top < entry_top) {
+ if (base >= entry_base && base < entry_top &&
+ top >= entry_base && top <= entry_top) {
memmap[i].length = base - entry_base;
diff --git a/stage2/lib/memmap.h b/stage2/lib/memmap.h
index f80e6d88..48fee95b 100644
--- a/stage2/lib/memmap.h
+++ b/stage2/lib/memmap.h
@@ -4,9 +4,17 @@
#include <stdint.h>
#include <sys/e820.h>
+#define MEMMAP_USABLE 1
+#define MEMMAP_RESERVED 2
+#define MEMMAP_ACPI_RECLAIMABLE 3
+#define MEMMAP_ACPI_NVS 4
+#define MEMMAP_BAD_MEMORY 5
+#define MEMMAP_BOOTLOADER_RECLAIMABLE 0x1000
+#define MEMMAP_KERNEL_AND_MODULES 0x1001
+
void init_memmap(void);
-void *ext_mem_balloc(size_t count);
-void *ext_mem_balloc_aligned(size_t count, size_t alignment);
+void *ext_mem_balloc(size_t count, uint32_t type);
+void *ext_mem_balloc_aligned(size_t count, size_t alignment, uint32_t type);
void memmap_alloc_range(uint64_t base, uint64_t length, uint32_t type);
struct e820_entry_t *get_memmap(size_t *entries);
void print_memmap(struct e820_entry_t *mm, size_t size);
