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