#include "hv/allocator.h" #include "hv/config.h" #include "hv/panic.h" #include "hv/string.h" #include "hv/uart.h" #define MAX_ALLOC_PAGES 1024u static paddr_t g_base; static uint64_t g_size; static uint8_t g_used[MAX_ALLOC_PAGES]; static uint64_t g_pages; void allocator_init(paddr_t base, uint64_t size) { BUG_ON(!hv_is_aligned_u64(base, CONFIG_PAGE_SIZE)); BUG_ON(!hv_is_aligned_u64(size, CONFIG_PAGE_SIZE)); g_base = base; g_size = size; g_pages = size / CONFIG_PAGE_SIZE; BUG_ON(g_pages > MAX_ALLOC_PAGES); hv_memset(g_used, 0, sizeof(g_used)); } void *alloc_page(void) { for (uint64_t i = 0; i < g_pages; i++) { if (g_used[i] == 0u) { g_used[i] = 1u; return (void *)(uintptr_t)(g_base + (i * CONFIG_PAGE_SIZE)); } } return (void *)0; } bool allocator_owns(paddr_t addr, uint64_t size) { uint64_t end; uint64_t alloc_end; if (hv_add_overflow_u64(addr, size, &end) || hv_add_overflow_u64(g_base, g_size, &alloc_end)) { return false; } return addr >= g_base && end <= alloc_end; } bool allocator_selftest(void) { if (!hv_is_aligned_u64(g_base, CONFIG_PAGE_SIZE) || g_pages == 0u) { return false; } uint64_t free_count = 0; for (uint64_t i = 0; i < g_pages; i++) { if (g_used[i] == 0u) { free_count++; } } return free_count != 0u && allocator_owns(g_base, CONFIG_PAGE_SIZE); } void allocator_dump(void) { uint64_t used = 0; for (uint64_t i = 0; i < g_pages; i++) { if (g_used[i] != 0u) { used++; } } uart_puts("allocator base="); uart_put_hex64(g_base); uart_puts(" size="); uart_put_hex64(g_size); uart_puts(" pages="); uart_put_dec64(g_pages); uart_puts(" used="); uart_put_dec64(used); uart_puts("\n"); }