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);
}
