From dd5d9e1d48396cbc226ff14fe557a55613c91fcb Mon Sep 17 00:00:00 2001 From: Jon Santmyer Date: Fri, 15 Mar 2024 13:16:02 -0400 Subject: better buddy memory allocator --- mem/zone.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 mem/zone.c (limited to 'mem/zone.c') diff --git a/mem/zone.c b/mem/zone.c new file mode 100644 index 0000000..489383a --- /dev/null +++ b/mem/zone.c @@ -0,0 +1,97 @@ +#include "zone.h" +#include "memory.h" +#include "boot/boot.h" +#include "lib/string.h" +#include "io/log.h" + +#define MEM_ZONE_STANDARD_PAGES (MEM_ZONE_STANDARD_LIMIT >> 12) + +static uintmax_t + s_zone_standard_freemap_blocks_flat[BUDDY_BLOCKS_FOR(MEM_ZONE_STANDARD_PAGES)]; +static uintmax_t* + s_zone_standard_freemap_blocks[MEM_BUDDY_ORDERS]; + +static struct PhysicalMemoryZone s_zones[MEM_ZONE_COUNT] = +{ + { + .name = "Standard", + .base = MEM_ZONE_STANDARD_BASE, + .limit = MEM_ZONE_STANDARD_LIMIT, + .npages_total = MEM_ZONE_STANDARD_PAGES, + .npages_free = 0, + .freemap = { + .orders = MEM_BUDDY_ORDERS, + .bits = MEM_ZONE_STANDARD_PAGES, + .free = 0, + .blocks = s_zone_standard_freemap_blocks + } + }, + { + .name = "Higher", + .base = MEM_ZONE_HIGHER_BASE, + .limit = -1, + .freemap = { + .orders = MEM_BUDDY_ORDERS + } + } +}; + +void +mem_zone_resv(size_t zone, uintptr_t base, uintptr_t limit) +{ + size_t base_off = base % PAGESIZE; + size_t limit_off = limit % PAGESIZE; + + if(base_off > 0) base += (PAGESIZE - base_off); + limit -= limit_off; + + buddy_mark_range(&s_zones[zone].freemap, base >> 12, limit >> 12); +} + +void +mem_zone_free(size_t zone, uintptr_t base, uintptr_t limit) +{ + size_t base_off = base % PAGESIZE; + size_t limit_off = limit % PAGESIZE; + + if(base_off > 0) base += (PAGESIZE - base_off); + limit -= limit_off; + + size_t npages = (limit - base) >> 12; + s_zones[zone].npages_free += npages; + buddy_free_range(&s_zones[zone].freemap, base >> 12, limit >> 12); +} + +uintptr_t +mem_zone_alloc(size_t zone, size_t pages) +{ + struct PhysicalMemoryZone *pmz = &s_zones[zone]; + intmax_t pagei = buddy_alloc(&pmz->freemap, pages); + if(pagei < 0) return 0; + + return (((uintmax_t)pagei) << 12) + pmz->base; +} + +void +mem_zone_setup_standard(void) +{ + struct PhysicalMemoryZone *standard_zone = &s_zones[MEM_ZONE_STANDARD]; + uintmax_t *map_block_layer_base = s_zone_standard_freemap_blocks_flat; + for(size_t i = 0; i < MEM_BUDDY_ORDERS; i++) { + size_t layer_entries = (standard_zone->freemap.bits / BUDDY_BLOCK_BITS) >> i; + standard_zone->freemap.blocks[i] = map_block_layer_base; + memset(map_block_layer_base, 0xFF, layer_entries * sizeof(uintmax_t)); + map_block_layer_base = &map_block_layer_base[layer_entries]; + } + + for(int i = 0; i < boot_memorymap.count; i++) { + struct MemoryMapEntry *entry = &boot_memorymap.entries[i]; + klogf("%2i\t%#016X -> %#016X (%i)\n", + i, entry->base, entry->base + entry->length, entry->usable); + if(entry->base > MEM_ZONE_STANDARD_LIMIT) continue; + size_t limit = entry->base + entry->length; + if(limit > MEM_ZONE_STANDARD_LIMIT) limit = MEM_ZONE_STANDARD_LIMIT; + if(entry->usable) + mem_zone_free(MEM_ZONE_STANDARD, entry->base, limit); + } +} -- cgit v1.2.1