pmm: Rework conventional memory allocator
This commit is contained in:
parent
d9466f3d25
commit
4e4017fb13
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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))
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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++;
|
||||
}
|
||||
|
||||
///////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user