pmm: Rework conventional memory allocator

This commit is contained in:
mintsuki 2021-04-15 02:21:38 +02:00
parent d9466f3d25
commit 4e4017fb13
14 changed files with 78 additions and 160 deletions

View File

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

View File

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

View File

@ -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) {

View File

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

View File

@ -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,

View File

@ -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))

View File

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

View File

@ -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);
return ret;
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;
}
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);
}
void *ext_mem_alloc_type(size_t count, uint32_t type) {
return ext_mem_alloc_aligned_type(count, 4, type);
}
// 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) {
void *ext_mem_alloc_type(size_t count, uint32_t type) {
count = ALIGN_UP(count, 4096);
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;

View File

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

View File

@ -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++;
}
///////////////////////////////////////

View File

@ -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;

View File

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

View File

@ -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

View File

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