From 547dfad79dec337106ff7831a7a3ff095f396d86 Mon Sep 17 00:00:00 2001 From: Ebrahim Aleem Date: Thu, 5 Mar 2026 20:43:28 -0800 Subject: [PATCH 1/3] any size pfa --- Makefile | 2 +- drivers/acpi/tables.c | 15 +- drivers/acpica_osl/osl.c | 5 +- drivers/apic/apic_init.c | 8 +- drivers/hpet/hpet_init.c | 11 +- drivers/ioapic/ioapic_init.c | 11 +- kernel/core/alloc.c | 278 ++++++--------- kernel/core/mm.c | 607 +++++++++++++++----------------- kernel/core/paging.c | 6 +- kernel/include/core/alloc.h | 32 -- kernel/include/core/mm.h | 22 +- kernel/include/core/proc_data.h | 2 - 12 files changed, 440 insertions(+), 559 deletions(-) diff --git a/Makefile b/Makefile index cc357d4..bfadf15 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ # Debug options -#export DEBUG = 1 +export DEBUG = 1 export DEBUG_LOGGING = 1 # Global options diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index d1e9deb..d3f3121 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -225,11 +225,17 @@ static void map_header(const volatile void* table) { const volatile struct acpi_gen_header_t* gen = (struct acpi_gen_header_t*)table; uint64_t alloc_base = (uint64_t)gen & PAGE_BASE_MASK; - paging_map(alloc_base, alloc_base, PAGE_PRESENT | PAT_MMIO_4K, PAGE_4K); + if (!paging_map(alloc_base, alloc_base, PAGE_PRESENT | PAT_MMIO_4K, PAGE_4K)) { + logging_log_error("Failed to map ACPI header"); + panic(PANIC_PAGING); + } if ((uint64_t)gen != alloc_base) { alloc_base += PAGE_SIZE_4K; - paging_map(alloc_base, alloc_base, PAGE_PRESENT | PAT_MMIO_4K, PAGE_4K); + if (!paging_map(alloc_base, alloc_base, PAGE_PRESENT | PAT_MMIO_4K, PAGE_4K)) { + logging_log_error("Failed to map ACPI header"); + panic(PANIC_PAGING); + } } } @@ -243,7 +249,10 @@ static void map_table(const volatile void* table) { while (alloc_base < (uint64_t)gen + gen->Length) { alloc_base += PAGE_SIZE_4K; - paging_map(alloc_base, alloc_base, PAGE_PRESENT | PAT_MMIO_4K, PAGE_4K); + if (!paging_map(alloc_base, alloc_base, PAGE_PRESENT | PAT_MMIO_4K, PAGE_4K)) { + logging_log_error("Failed to map ACPI table"); + panic(PANIC_PAGING); + } } } diff --git a/drivers/acpica_osl/osl.c b/drivers/acpica_osl/osl.c index fdc5147..54fb10d 100644 --- a/drivers/acpica_osl/osl.c +++ b/drivers/acpica_osl/osl.c @@ -239,7 +239,10 @@ void* AcpiOsMapMemory(ACPI_PHYSICAL_ADDRESS paddr, ACPI_SIZE len) { } for (uint64_t i = 0; i < len; i += PAGE_SIZE_4K) { - paging_map(vaddr + i, page_base + i, PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K); + if (!paging_map(vaddr + i, page_base + i, PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K)) { + logging_log_error("Failed to map memory for ACPICA"); + return 0; + } } return (void*)(vaddr + adj); diff --git a/drivers/apic/apic_init.c b/drivers/apic/apic_init.c index d8b7902..b0f4e5f 100644 --- a/drivers/apic/apic_init.c +++ b/drivers/apic/apic_init.c @@ -37,6 +37,7 @@ #include #include #include +#include #include @@ -102,8 +103,11 @@ uint8_t* ap_init_locks; void apic_init(void) { apic_base = msr_read(MSR_APIC_BASE) & APIC_BASE_MASK; - paging_map(apic_base, apic_base, - PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K); + if (!paging_map(apic_base, apic_base, + PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K)) { + logging_log_error("Failed to map memory for LAPIC"); + panic(PANIC_PAGING); + } timer_vector = idt_get_vector(); error_vector = idt_get_vector(); diff --git a/drivers/hpet/hpet_init.c b/drivers/hpet/hpet_init.c index ba25577..1f5f0d6 100644 --- a/drivers/hpet/hpet_init.c +++ b/drivers/hpet/hpet_init.c @@ -77,11 +77,18 @@ void hpet_init(void) { if (hpet_reg_bases[i]) { logging_log_debug("Found HPET register base @ 0x%lx", hpet_reg_bases[i]); const uint64_t temp = mm_alloc_v(PAGE_SIZE_4K); - paging_map( + if (!temp) { + logging_log_error("Failed to allocate memory for hpet"); + panic(PANIC_NO_MEM); + } + if(!paging_map( temp, (uint64_t)hpet_reg_bases[i], PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, - PAGE_4K); + PAGE_4K)) { + logging_log_error("Failed to map memory for HPET"); + panic(PANIC_PAGING); + } hpet_reg_bases[i] = (void*)temp; // disable all interrupts diff --git a/drivers/ioapic/ioapic_init.c b/drivers/ioapic/ioapic_init.c index 524d93b..a1eab5d 100644 --- a/drivers/ioapic/ioapic_init.c +++ b/drivers/ioapic/ioapic_init.c @@ -27,6 +27,7 @@ #include #include #include +#include #define IOAPIC_OFF_IOREGSEL 0x00 #define IOAPIC_OFF_IOWIN 0x10 @@ -58,7 +59,10 @@ void ioapic_init(void) { logging_log_info("Initializing IO APIC 0x%lX", (uint64_t)ioapic->IOAPICID); const uint64_t ioapic_base = ioapic->IOAPICAddress; - paging_map(ioapic_base, ioapic_base, PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K); + if (!paging_map(ioapic_base, ioapic_base, PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K)) { + logging_log_error("Failed to map memory for IOAPIC"); + panic(PANIC_PAGING); + } *(volatile uint32_t*)(ioapic_base + IOAPIC_OFF_IOREGSEL) = IOAPIC_IOAPICVER; const uint64_t num_redir = 1 + (MAX_REDIR_ENTRY_MSK & @@ -74,7 +78,10 @@ void ioapic_init(void) { for (uint64_t mapping_base = ioapic_base + PAGE_SIZE_4K; mapping_base < ioapic_base + IOAPIC_REDIR_ST + num_redir * 2; mapping_base += PAGE_SIZE_4K) { - paging_map(mapping_base, mapping_base, PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K); + if (!paging_map(mapping_base, mapping_base, PAGE_PRESENT | PAGE_RW | PAT_MMIO_4K, PAGE_4K)) { + logging_log_error("Failed to map memory for IOAPIC"); + panic(PANIC_PAGING); + } } } diff --git a/kernel/core/alloc.c b/kernel/core/alloc.c index d229f3d..192e828 100644 --- a/kernel/core/alloc.c +++ b/kernel/core/alloc.c @@ -23,217 +23,149 @@ #include #include #include +#include +#include -#define SLAB_SIZE_1 0x1 -#define SLAB_SIZE_2 0x2 -#define SLAB_SIZE_4 0x4 -#define SLAB_SIZE_8 0x8 -#define SLAB_SIZE_16 0x10 -#define SLAB_SIZE_32 0x20 -#define SLAB_SIZE_64 0x40 -#define SLAB_SIZE_128 0x80 -#define SLAB_SIZE_256 0x100 -#define SLAB_SIZE_512 0x200 -#define SLAB_SIZE_1K 0x400 -#define SLAB_SIZE_2K 0x800 -#define SLAB_SIZE_4K 0x1000 -#define SLAB_SIZE_8K 0x2000 -#define SLAB_SIZE_16K 0x4000 -#define SLAB_SIZE_32K 0x8000 -#define SLAB_SIZE_64K 0x10000 -#define SLAB_SIZE_128K 0x20000 -#define SLAB_SIZE_256K 0x40000 -#define SLAB_SIZE_512K 0x80000 -#define SLAB_SIZE_1M 0x100000 -#define SLAB_SIZE_2M 0x200000 - -struct cache_node_t { +#define HEADER_SIZE_MASK 0xFFFFFFFFFFFFFFF8 +#define HEADER_USED 0x1 + +struct free_node_t { uint64_t base; - struct cache_node_t* next; + size_t size; + struct free_node_t* next; }; -static struct cache_node_t* create_node_block(struct cache_node_t** tail) { - uint64_t i; - - struct cache_node_t* list = (struct cache_node_t*)paging_ident(mm_alloc_p2m()); +struct alloc_header_t { + uint64_t header; +} __attribute__((packed)); - for (i = 0; i < SIZE_2M / sizeof(struct cache_node_t) - 1; i++) { - list[i].next = &list[i+1]; - *tail = &list[i+1]; - } +static struct free_node_t* free_list; +static struct free_node_t* node_pool; +static uint8_t alloc_lock; - return list; +void alloc_init(void) { + lock_init(&alloc_lock); + free_list = 0; + node_pool = 0; } -static struct cache_node_t* alloc_cache_node(void) { - struct proc_data_t* data = proc_data_get(); - struct cache_node_t* t; +static struct free_node_t* alloc_node(void) { + struct free_node_t* ret = 0; + uint64_t addr, i; - lock_acquire(&data->alloc_caches.lock); - t = data->alloc_caches.avl; - if (t) { - data->alloc_caches.avl = t->next; + lock_acquire(&alloc_lock); + if (node_pool) { + ret = node_pool; + node_pool = node_pool->next; } - lock_release(&data->alloc_caches.lock); + lock_release(&alloc_lock); - if (t) { - return t; - } + if (!ret) { + addr = mm_alloc_p(PAGE_SIZE_4K); + if (!addr) { + logging_log_error("Failed to allocate free list pointers for heap"); + panic(PANIC_NO_MEM); + } - struct cache_node_t* tail; - t = create_node_block(&tail); - if (t) { - lock_acquire(&data->alloc_caches.lock); - tail->next = data->alloc_caches.avl; - data->alloc_caches.avl = t->next; - lock_release(&data->alloc_caches.lock); + addr = paging_ident(addr); + ret = (struct free_node_t*)addr; + for (i = 1; i < PAGE_SIZE_4K / sizeof(struct free_node_t) - 1; i++) { + ret[i].next = &ret[i+1]; + } + + lock_acquire(&alloc_lock); + ret[PAGE_SIZE_4K / sizeof(struct free_node_t)].next = node_pool; + node_pool = &ret[1]; + lock_release(&alloc_lock); } - return t; + return ret; } -static enum slab_t min_slab(size_t size) { - if (size <= SLAB_SIZE_1) { - return SLAB_1; - } - if (size <= SLAB_SIZE_2) { - return SLAB_2; - } - if (size <= SLAB_SIZE_4) { - return SLAB_4; - } - if (size <= SLAB_SIZE_8) { - return SLAB_8; - } - if (size <= SLAB_SIZE_16) { - return SLAB_16; - } - if (size <= SLAB_SIZE_32) { - return SLAB_32; - } - if (size <= SLAB_SIZE_64) { - return SLAB_64; - } - if (size <= SLAB_SIZE_128) { - return SLAB_128; - } - if (size <= SLAB_SIZE_256) { - return SLAB_256; - } - if (size <= SLAB_SIZE_512) { - return SLAB_512; - } - if (size <= SLAB_SIZE_1K) { - return SLAB_1K; - } - if (size <= SLAB_SIZE_2K) { - return SLAB_2K; - } - if (size <= SLAB_SIZE_4K) { - return SLAB_4K; - } - if (size <= SLAB_SIZE_8K) { - return SLAB_8K; - } - if (size <= SLAB_SIZE_16K) { - return SLAB_16K; - } - if (size <= SLAB_SIZE_32K) { - return SLAB_32K; - } - if (size <= SLAB_SIZE_64K) { - return SLAB_64K; - } - if (size <= SLAB_SIZE_128K) { - return SLAB_128K; - } - if (size <= SLAB_SIZE_256K) { - return SLAB_256K; - } - if (size <= SLAB_SIZE_512K) { - return SLAB_512K; - } - if (size <= SLAB_SIZE_1M) { - return SLAB_1M; - } - if (size <= SLAB_SIZE_2M) { - return SLAB_2M; - } - return SLAB_MAX; +static void free_node(struct free_node_t* node) { + lock_acquire(&alloc_lock); + node->next = free_list; + free_list = node; + lock_release(&alloc_lock); } -static struct cache_node_t* create_cache(enum slab_t slab, struct cache_node_t** tail) { - uint64_t i; - - uint64_t slab_base = paging_ident(mm_alloc_p2m()); - - struct cache_node_t* cache = 0, * t; +void* kmalloc(size_t size) { + struct free_node_t* node, **next; + uint64_t ret = 0, adj; + + size += sizeof(struct alloc_header_t); - for (i = 0; i < SIZE_2M; i += (1 << (uint64_t)slab)) { - t = alloc_cache_node(); - if (!t) { - break; - } - t->next = cache; - t->base = i + slab_base; - if (!cache) { - *tail = t; - } - cache = t; + adj = size % 16; + if (adj) { + size += 16 - adj; } - return cache; -} + lock_acquire(&alloc_lock); + node = free_list; + next = &free_list; -void alloc_init(void) { - struct proc_data_t* data = proc_data_get(); - uint64_t i; + while (node) { + if (node->size >= size) { + ret = node->base; + node->size -= size; + node->base += size; - data->alloc_caches.avl = 0; - lock_init(&data->alloc_caches.lock); + if (!node->size) { + *next = node->next; + node->next = node_pool; + node_pool = node; + } - for (i = 0; i < SLAB_MAX; i++) { - data->alloc_caches.slabs[i] = 0; - } -} + break; + } -void* kmalloc(size_t size) { - enum slab_t slab = min_slab(size); - if (slab == SLAB_MAX) { - return 0; + next = &node->next; + node = node->next; } - uint64_t ret; - struct proc_data_t* data = proc_data_get(); - lock_acquire(&data->alloc_caches.lock); - struct cache_node_t* cache = data->alloc_caches.slabs[slab], * tail; - if (cache) { - ret = cache->base; - data->alloc_caches.slabs[slab] = cache->next; + lock_release(&alloc_lock); - //TODO: track cache for freeing - lock_release(&data->alloc_caches.lock); + if (ret) { + ((struct alloc_header_t*)ret)->header = (size - sizeof(struct alloc_header_t)) | HEADER_USED; + ret += sizeof(struct alloc_header_t); } else { - lock_release(&data->alloc_caches.lock); - cache = create_cache(slab, &tail); - if (!cache) { - return 0; + adj = size % PAGE_SIZE_4K; + if (adj) { + size += PAGE_SIZE_4K - adj; } - lock_acquire(&data->alloc_caches.lock); - tail->next = data->alloc_caches.slabs[slab]; - data->alloc_caches.slabs[slab] = cache->next; + ret = mm_alloc_p(size); // aligness does not matter for ident + if (!ret) { + logging_log_error("Failed to allocate memory for heap"); + return 0; + } - ret = cache->base; + ret = paging_ident(ret); - //TODO: track cache for freeing - lock_release(&data->alloc_caches.lock); + ((struct alloc_header_t*)ret)->header = (size - sizeof(struct alloc_header_t)) | HEADER_USED; + ret += sizeof(struct alloc_header_t); } return (void*)ret; } void kfree(void* ptr) { - (void)ptr; + if (!ptr) { + return; + } + + struct alloc_header_t* header = (struct alloc_header_t*)((uint64_t)ptr - sizeof(struct alloc_header_t)); + if (!(header->header & HEADER_USED)) { + logging_log_warning("Double free @ 0x%lx", ptr); + return; + } + + header->header ^= HEADER_USED; + + struct free_node_t* node = alloc_node(); + node->size = header->header & HEADER_SIZE_MASK; + node->base = (uint64_t)header; + + free_node(node); } diff --git a/kernel/core/mm.c b/kernel/core/mm.c index 8cc97ba..737b46e 100644 --- a/kernel/core/mm.c +++ b/kernel/core/mm.c @@ -23,422 +23,373 @@ #include #include #include +#include #include #define PAGE_4K_MASK 0xFFFFFFFFFFFFF000 #define SIZE_GIB (1024 * 1024 * 1024) -#define MAX_BLOCKS 64 +#define MAX_INIT_NODES 64 +#define WITHIN_NODE(base, b, l) (base >= b && base < b + l) -struct frame_list_t { +struct mm_tree_node_t { + struct mm_tree_node_t* less; + struct mm_tree_node_t* more; uint64_t base; uint64_t limit; - struct frame_list_t* next; }; +static struct mm_tree_node_t* p_tree; +static struct mm_tree_node_t* v_tree; + extern uint8_t _kernel_pend; -static void (*early_first_segment)(uint64_t* handle); -static void (*early_next_segment)(uint64_t* handle, struct mem_segment_t* seg); static uint64_t kernel_limit; -static struct frame_list_t init_v_frame; +static uint8_t p_lock; +static uint8_t v_lock; +static uint8_t n_lock; + +static struct mm_tree_node_t node_pool[MAX_INIT_NODES]; +static struct mm_tree_node_t* free_nodes; + +static struct mm_tree_node_t* alloc_node(void) { + struct mm_tree_node_t* next; + lock_acquire(&n_lock); + if (free_nodes) { + next = free_nodes; + free_nodes = free_nodes->less; + lock_release(&n_lock); + } + else { + lock_release(&n_lock); + next = kmalloc(sizeof(struct mm_tree_node_t)); + } -static struct frame_list_t* p_list; -static struct frame_list_t* v_list; + next->less = 0; + next->more = 0; + return next; +} -static struct frame_list_t* p_2m_list; -static struct frame_list_t* v_2m_list; +static void free_node(struct mm_tree_node_t* node) { + lock_acquire(&n_lock); + node->less = free_nodes; + free_nodes = node; + lock_release(&n_lock); +} -static uint8_t p_lock; -static uint8_t v_lock; +static struct mm_tree_node_t* find_base_node(uint64_t base, struct mm_tree_node_t* root, struct mm_tree_node_t* parent) { + if (!root) { + return parent; + } -static uint8_t p_2m_lock; -static uint8_t v_2m_lock; + if (WITHIN_NODE(base, root->base, root->limit)) { + return root; + } + + if (base < root->base) { + return find_base_node(base, root->less, root); + } + + return find_base_node(base, root->more, root); +} -static struct frame_list_t init_p_array[3 * MAX_BLOCKS]; +static void attach_node(struct mm_tree_node_t* root, struct mm_tree_node_t* node) { + if (node->base > root->base) { + if (root->more) { + attach_node(root->more, node); + } + else { + root->more = node; + } + } + else { + if (root->less) { + attach_node(root->less, node); + } + else { + root->less = node; + } + } +} -static uint64_t mm_alloc(size_t size, struct frame_list_t** list, void** tofree) { - struct frame_list_t* prev = 0; +static uint64_t mm_alloc( + uint64_t limit, + struct mm_tree_node_t* root, + uint64_t max, + struct mm_tree_node_t* parent) { uint64_t ret; - *tofree = 0; - - for (struct frame_list_t* i = *list; i != 0; i = i->next) { - if (i->limit == size) { - if (prev) { - prev->next = i->next; - ret = i->base; - *tofree = i; - return ret; + + if (!root) { + return 0; + } + + if (root->base + limit > max) { + return mm_alloc(limit, root->less, max, root); + } + + ret = mm_alloc(limit, root->more, max, root); + if (ret) { + return ret; + } + + if (limit <= root->limit) { + root->limit -= limit; + ret = root->base; + root->base += limit; + + if (root->limit == 0) { + if (root == parent->less) { + parent->less = 0; + } + else { + parent->more = 0; + } + + if (root->less) { + attach_node(parent, root->less); + } + if (root->more) { + attach_node(parent, root->more); } - ret = i->base; - *list = i->next; - return ret; + free_node(root); } - if (i->limit > size) { - ret = i->base; - i->base += size; - i->limit -= size; - return ret; + + return ret; + } + + return mm_alloc(limit, root->less, max, root); +} + +static void mm_free(uint64_t base, uint64_t size, struct mm_tree_node_t* root, uint8_t* lock) { + uint64_t adj; + struct mm_tree_node_t* node; + + adj = size % PAGE_SIZE_4K; + if (adj) { + size += PAGE_SIZE_4K - adj; + } + + lock_acquire(lock); + + node = find_base_node(base, root->more, root); + + if (WITHIN_NODE(base, node->base, node->limit)) { + if (root == p_tree) { + logging_log_warning("Double free @ 0x%lx on p_tree", base); } + else { + logging_log_warning("Double free @ 0x%lx on v_tree", base); + } + } + else if (base < node->base) { + node->less = alloc_node(); + node->base = base; + node->limit = size; + } + else { + node->more = alloc_node(); + node->base = base; + node->limit = size; } - logging_log_error("Out of contigious memory"); - return 0; + //TODO: coallese + + lock_release(lock); } -void mm_init( +static uint64_t mm_alloc_max(size_t size, uint64_t align, uint64_t max, struct mm_tree_node_t* root, uint8_t* lock) { + uint64_t ret; + uint64_t adj; + struct mm_tree_node_t* padding; + + adj = size % PAGE_SIZE_4K; + if (adj) { + size += PAGE_SIZE_4K - adj; + } + + adj = align % PAGE_SIZE_4K; + if (adj) { + align += PAGE_SIZE_4K - adj; + } + + lock_acquire(lock); + ret = mm_alloc(size + align, root->more, max, root); + lock_release(lock); + + if (align) { + adj = ret % align; + if (adj) { + adj = align - adj; + + padding = alloc_node(); + padding->base = ret; + padding->limit = adj; + + lock_acquire(lock); + attach_node(root, padding); + lock_release(lock); + } + } + + return ret + adj; +} + +extern void mm_init( void (*first_segment)(uint64_t* handle), void (*next_segment)(uint64_t* handle, struct mem_segment_t* seg)) { - kernel_limit = (uint64_t)&_kernel_pend; - early_first_segment = first_segment; - early_next_segment = next_segment; - - // initial vmem is always 2m aligned - v_2m_list = &init_v_frame; - init_v_frame.base = CANON_HIGH; - init_v_frame.limit = VIRTUAL_LIMIT - CANON_HIGH + 1; - - v_list = 0; - p_list = 0; - p_2m_list = 0; lock_init(&p_lock); lock_init(&v_lock); + lock_init(&n_lock); + + uint64_t blocks; + + for (blocks = 0; blocks < MAX_INIT_NODES - 1; blocks++) { + node_pool[blocks].less = &node_pool[blocks + 1]; + } + node_pool[MAX_INIT_NODES - 1].less = 0; + free_nodes = &node_pool[0]; - lock_init(&p_2m_lock); - lock_init(&v_2m_lock); // find memory limit uint64_t mem_limit = 0; - uint64_t blocks = 0; + blocks = 0; + uint64_t handle; struct mem_segment_t seg; + struct mm_tree_node_t* node; + uint64_t adj; + + p_tree = alloc_node(); + p_tree->base = 0; + p_tree->limit = 0; + p_tree->less = 0; + p_tree->more = 0; + first_segment(&handle); - for (early_next_segment(&handle, &seg); seg.size || seg.base; next_segment(&handle, &seg)) { + for (next_segment(&handle, &seg); seg.size || seg.base; next_segment(&handle, &seg)) { logging_log_debug("Memory segment 0x%lX (base) 0x%lX (size) 0x%lX (type)", (uint64_t)seg.base, (uint64_t)seg.size, (uint64_t)seg.type); if (seg.type == MEM_AVL && seg.base + seg.size > mem_limit) { mem_limit = seg.base + seg.size; blocks++; } - } - logging_log_info("Detected 0x%lX bytes (0x%lX GiB) of memory across %ld blocks", - mem_limit, (uint64_t)(mem_limit / SIZE_GIB), blocks); - - logging_log_debug("Initializing heap allocator"); - alloc_init(); - logging_log_debug("Heap allocator init done"); - - logging_log_debug("Initializing paging"); - paging_init(); - logging_log_debug("Paging init done"); - - struct frame_list_t* init_p = &init_p_array[0]; - - uint64_t skip = 0; - if (blocks > MAX_BLOCKS) { - skip = blocks - MAX_BLOCKS; // prefer later blocks as they are larger - } - uint64_t rem; - first_segment(&handle); - for (early_next_segment(&handle, &seg); seg.size || seg.base; ) { - if (seg.type != MEM_AVL || seg.size < PAGE_SIZE_4K || skip) { - goto next_seg; - } - - if (skip) { - skip--; + if (seg.type != MEM_AVL) { + continue; } - - if (seg.base <= kernel_limit) { + + while (seg.size > PAGE_SIZE_4K && seg.base < kernel_limit) { seg.base += PAGE_SIZE_4K; seg.size -= PAGE_SIZE_4K; - continue; } - // align base to 4K - rem = seg.base % PAGE_SIZE_4K; - - if (rem) { - seg.base += PAGE_SIZE_4K - rem; - seg.size -= PAGE_SIZE_4K - rem; + if (seg.size < PAGE_SIZE_4K || seg.base < kernel_limit) { + continue; } - // try 2m first - if (seg.size >= 2 * SIZE_2M) { - // pre padding - rem = seg.base % SIZE_2M ; - uint64_t base = seg.base; - if (rem) { - init_p->base = seg.base; - init_p->limit = SIZE_2M - rem; - init_p->next = p_list; - p_list = init_p++; - - base += SIZE_2M - rem; - } - - // post padding - rem = seg.size % SIZE_2M ; - uint64_t limit = seg.size; - if (rem > PAGE_SIZE_4K) { - init_p->base = seg.base + seg.size - rem; - init_p->limit = rem & PAGE_4K_MASK; - init_p->next = p_list; - p_list = init_p++; - - limit -= rem & PAGE_4K_MASK; - } - - init_p->base = base; - init_p->limit = limit; - init_p->next = p_2m_list; - p_2m_list = init_p++; - goto next_seg; + // align base + adj = seg.base % PAGE_SIZE_4K; + if (adj) { + adj = PAGE_SIZE_4K - adj; + seg.base += adj; + seg.size -= adj; } - // otherwise add 4K - init_p->base = seg.base; - init_p->limit = seg.size & PAGE_4K_MASK; - init_p->next = p_list; - p_list = init_p++; - -next_seg: - next_segment(&handle, &seg); - } -} - -uint64_t mm_alloc_p(size_t size) { - if (size % PAGE_SIZE_4K) { - size += PAGE_SIZE_4K - (size % PAGE_SIZE_4K); - } + if (seg.size < PAGE_SIZE_4K) { + continue; + } - void* tofree; - lock_acquire(&p_lock); - if (!p_list) { - lock_release(&p_lock); - lock_acquire(&p_2m_lock); - if (!p_2m_list) { - logging_log_error("Out of physical memory"); - return 0; + // trim limit + adj = seg.size % PAGE_SIZE_4K; + if (adj) { + seg.size -= adj; } - struct frame_list_t* temp = p_2m_list; - p_2m_list = p_2m_list->next; - lock_release(&p_2m_lock); - lock_acquire(&p_lock); - temp->next = p_list; - p_list = temp; - } - const uint64_t ret = mm_alloc(size, &p_list, &tofree); - lock_release(&p_lock); - if (tofree) { - kfree(tofree); - } - return ret; -} + if (seg.size < PAGE_SIZE_4K) { + continue; + } -uint64_t mm_alloc_v(size_t size) { - if (size % PAGE_SIZE_4K) { - size += PAGE_SIZE_4K - (size % PAGE_SIZE_4K); - } + node = find_base_node(seg.base, p_tree->more, p_tree); + if (WITHIN_NODE(seg.base, node->base, node->limit)) { + logging_log_error("Overlapping memory regions 0x%lx into 0x%lx-0x%lx", + seg.base, node->base, node->base + node->limit); + panic(PANIC_STATE); + } - void* tofree; - lock_acquire(&v_lock); - if (!v_list) { - lock_release(&v_lock); - lock_acquire(&v_2m_lock); - if (!v_2m_list) { - logging_log_error("Out of virtual memory"); - return 0; + if (seg.base < node->base) { + node->less = alloc_node(); + node = node->less; + } + else { + node->more = alloc_node(); + node = node->more; } - struct frame_list_t* temp = v_2m_list; - v_2m_list = v_2m_list->next; - lock_release(&v_2m_lock); - lock_acquire(&v_lock); - temp->next = v_list; - v_list = temp; - } - const uint64_t ret = mm_alloc(size, &v_list, &tofree); - lock_release(&v_lock); - if (tofree) { - kfree(tofree); - } - return ret; -} + node->base = seg.base; + node->limit = seg.size; + } -uint64_t mm_alloc_p2m(void) { - void* tofree; - lock_acquire(&p_2m_lock); - const uint64_t ret = mm_alloc(SIZE_2M , &p_2m_list, &tofree); - lock_release(&p_2m_lock); + logging_log_info("Detected 0x%lX bytes (0x%lX GiB) of memory across %ld blocks", + mem_limit, (uint64_t)(mem_limit / SIZE_GIB), blocks); - if (tofree) { - kfree(tofree); - } + v_tree = alloc_node(); + v_tree->base = 0; + v_tree->limit = 0; + v_tree->less = 0; + v_tree->more = alloc_node(); - return ret; -} + v_tree->more->base = CANON_HIGH; + v_tree->more->limit = VIRTUAL_LIMIT - CANON_HIGH + 1; + v_tree->more->less = 0; + v_tree->more->more = 0; -uint64_t mm_alloc_v2m(void) { - void* tofree; - lock_acquire(&v_2m_lock); - const uint64_t ret = mm_alloc(SIZE_2M , &v_2m_list, &tofree); - lock_release(&v_2m_lock); + logging_log_debug("Virtual space 0x%lx-0x%lx", + v_tree->more->base, v_tree->more->base + v_tree->more->limit); - if (tofree) { - kfree(tofree); - } + logging_log_debug("Initializing heap allocator"); + alloc_init(); + logging_log_debug("Heap allocator init done"); - return ret; + logging_log_debug("Initializing paging"); + paging_init(); + logging_log_debug("Paging init done"); } -void mm_free_p(uint64_t addr, size_t size) { - struct frame_list_t* prepend = kmalloc(sizeof(struct frame_list_t)); - prepend->base = addr; - prepend->limit = size; - lock_acquire(&p_lock); - prepend->next = p_list; - p_list = prepend; - lock_release(&p_lock); +uint64_t mm_alloc_p(size_t size) { + return mm_alloc_max(size, 0, ~0uLL, p_tree, &p_lock); } -void mm_free_v(uint64_t addr, size_t size) { - struct frame_list_t* prepend = kmalloc(sizeof(struct frame_list_t)); - prepend->base = addr; - prepend->limit = size; - lock_acquire(&v_lock); - prepend->next = v_list; - v_list = prepend; - lock_release(&v_lock); +uint64_t mm_alloc_v(size_t size) { + return mm_alloc_max(size, 0, ~0uLL, v_tree, &v_lock); } -void mm_free_p2m(uint64_t addr) { - struct frame_list_t* prepend = kmalloc(sizeof(struct frame_list_t)); - prepend->base = addr; - prepend->limit = SIZE_2M ; - lock_acquire(&p_2m_lock); - prepend->next = p_2m_list; - p_2m_list = prepend; - lock_release(&p_2m_lock); +uint64_t mm_alloc_palign(size_t size, uint64_t align) { + return mm_alloc_max(size, align, ~0uLL, p_tree, &p_lock); } -void mm_free_v2m(uint64_t addr) { - struct frame_list_t* prepend = kmalloc(sizeof(struct frame_list_t)); - prepend->base = addr; - prepend->limit = SIZE_2M ; - lock_acquire(&v_2m_lock); - prepend->next = v_2m_list; - v_2m_list = prepend; - lock_release(&v_2m_lock); +uint64_t mm_alloc_valign(size_t size, uint64_t align) { + return mm_alloc_max(size, align, ~0uLL, v_tree, &v_lock); } -static void** sort_next(void* _node) { - struct frame_list_t* node = _node; - return (void**)&node->next; +uint64_t mm_alloc_pmax(size_t size, uint64_t align, uint64_t max) { + return mm_alloc_max(size, align, max, p_tree, &p_lock); } -static uint64_t sort_value(void* _node) { - struct frame_list_t* node = _node; - return node->base; +uint64_t mm_alloc_vmax(size_t size, uint64_t align, uint64_t max) { + return mm_alloc_max(size, align, max, v_tree, &v_lock); } -static void defrag( - struct frame_list_t** list, - struct frame_list_t** m_list, - uint8_t* lock, - uint8_t* m_lock, - struct frame_list_t** tofree) { - - struct frame_list_t* promote = 0; - struct frame_list_t* i, * t, *prev = 0; - - lock_acquire(m_lock); - lock_acquire(lock); - *list = mergesort_ll_inplace_ul(*list, sort_next, sort_value); - - for (i = *list; i && i->next; ) { - if (i->base + i->limit == i->next->base) { - t = i->next; - i->next = t->next; - i->limit += t->limit; - - if (i->limit >= SIZE_2M && i->base % SIZE_2M == 0) { - t->base = i->base; - t->limit = i->limit - (i->limit % SIZE_2M); - t->next = promote; - promote = t; - - i->limit -= t->limit; - if (i->limit) { - i->base += t->limit; - } - else if (prev){ - prev->next = i->next; - i->next = *tofree; - *tofree = i; - i = prev->next; - continue; - } - else { - *list = (*list)->next; - i->next = *tofree; - *tofree = i; - i = *list; - continue; - } - } - else { - t->next = *tofree; - *tofree = t; - } - continue; - } - - prev = i; - i = i->next; - } - - for (; promote; promote = t) { - t = promote->next; - promote->next = *m_list; - *m_list = promote; - } - - *m_list = mergesort_ll_inplace_ul(*m_list, sort_next, sort_value); - for (i = *m_list; i && i->next; ) { - if (i->base + i->limit == i->next->base) { - t = i->next; - i->next = t->next; - i->limit += t->limit; - - t->next = *tofree; - *tofree = t; - continue; - } - - i = i->next; - } - lock_release(lock); - lock_release(m_lock); +void mm_free_p(uint64_t base, size_t size) { + mm_free(base, size, p_tree, &p_lock); } -void mm_defrag(void) { - struct frame_list_t* tofree = 0, * t; - - defrag(&p_list, &p_2m_list, &p_lock, &p_2m_lock, &tofree); - defrag(&v_list, &v_2m_list, &v_lock, &v_2m_lock, &tofree); - - for (; tofree; tofree = t) { - t = tofree->next; - kfree(tofree); - } +void mm_free_v(uint64_t base, size_t size) { + mm_free(base, size, v_tree, &v_lock); } diff --git a/kernel/core/paging.c b/kernel/core/paging.c index 47bf506..6f15452 100644 --- a/kernel/core/paging.c +++ b/kernel/core/paging.c @@ -99,7 +99,11 @@ uint64_t paging_map(uint64_t vaddr, uint64_t paddr, uint8_t flg, enum page_size_ } for (; lvl > page_size; lvl--) { - *access = mm_alloc_p(0x1000) | PAGE_PRESENT | PAGE_RW; + *access = mm_alloc_p(0x1000); + if (!access) { + return 0; + } + *access |= PAGE_PRESENT | PAGE_RW; access = (uint64_t*)paging_ident((*access & PAGE_ADDR_MASK)); kmemset(access, 0, 0x1000); diff --git a/kernel/include/core/alloc.h b/kernel/include/core/alloc.h index 676f811..d40651b 100644 --- a/kernel/include/core/alloc.h +++ b/kernel/include/core/alloc.h @@ -21,38 +21,6 @@ #include #include -enum slab_t { - SLAB_1, - SLAB_2, - SLAB_4, - SLAB_8, - SLAB_16, - SLAB_32, - SLAB_64, - SLAB_128, - SLAB_256, - SLAB_512, - SLAB_1K, - SLAB_2K, - SLAB_4K, - SLAB_8K, - SLAB_16K, - SLAB_32K, - SLAB_64K, - SLAB_128K, - SLAB_256K, - SLAB_512K, - SLAB_1M, - SLAB_2M, - SLAB_MAX -}; - -struct proc_alloc_caches_t { - uint8_t lock; - struct cache_node_t* avl; - struct cache_node_t* slabs[SLAB_MAX]; -}; - extern void alloc_init(void); extern void* kmalloc(size_t size); diff --git a/kernel/include/core/mm.h b/kernel/include/core/mm.h index 16ed60a..2dc0273 100644 --- a/kernel/include/core/mm.h +++ b/kernel/include/core/mm.h @@ -23,7 +23,6 @@ #define CANON_HIGH 0xFFFF800000000000 #define VIRTUAL_LIMIT IDENT_BASE -#define SIZE_2M 0x200000 struct mem_segment_t { uint64_t base; @@ -35,24 +34,23 @@ struct mem_segment_t { } type; }; +struct mm_tree_node_t; + extern void mm_init( void (*first_segment)(uint64_t* handle), void (*next_segment)(uint64_t* handle, struct mem_segment_t* seg)); -extern uint64_t mm_early_alloc_2m(void); - -uint64_t mm_alloc_p(size_t size); -uint64_t mm_alloc_v(size_t size); -uint64_t mm_alloc_p2m(void); -uint64_t mm_alloc_v2m(void); +extern uint64_t mm_alloc_p(size_t size); +extern uint64_t mm_alloc_v(size_t size); -void mm_free_p(uint64_t addr, size_t size); -void mm_free_v(uint64_t addr, size_t size); +extern uint64_t mm_alloc_palign(size_t size, uint64_t align); +extern uint64_t mm_alloc_valign(size_t size, uint64_t align); -void mm_free_p2m(uint64_t addr); -void mm_free_v2m(uint64_t addr); +extern uint64_t mm_alloc_pmax(size_t size, uint64_t align, uint64_t max); +extern uint64_t mm_alloc_vmax(size_t size, uint64_t align, uint64_t max); -void mm_defrag(void); +extern void mm_free_p(uint64_t base, size_t size); +extern void mm_free_v(uint64_t base, size_t size); #endif /* KERNEL_CORE_MM_H */ diff --git a/kernel/include/core/proc_data.h b/kernel/include/core/proc_data.h index 65caf7a..8c0068b 100644 --- a/kernel/include/core/proc_data.h +++ b/kernel/include/core/proc_data.h @@ -20,13 +20,11 @@ #include -#include #include #include struct proc_data_t { uint8_t arb_id; - struct proc_alloc_caches_t alloc_caches; volatile struct tss_t* tss; struct pcb_t* current_process; }; From be5ac0d0f658bab69a4b208a47873c2ecd73ccc0 Mon Sep 17 00:00:00 2001 From: Ebrahim Aleem Date: Thu, 5 Mar 2026 21:19:03 -0800 Subject: [PATCH 2/3] fixed double free bug in process ap init --- Makefile | 2 +- kernel/core/alloc.c | 36 ++++++++++++++++-------------------- kernel/core/kentry.c | 2 +- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/Makefile b/Makefile index bfadf15..cc357d4 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ # Debug options -export DEBUG = 1 +#export DEBUG = 1 export DEBUG_LOGGING = 1 # Global options diff --git a/kernel/core/alloc.c b/kernel/core/alloc.c index 192e828..eb155ea 100644 --- a/kernel/core/alloc.c +++ b/kernel/core/alloc.c @@ -26,8 +26,8 @@ #include #include -#define HEADER_SIZE_MASK 0xFFFFFFFFFFFFFFF8 -#define HEADER_USED 0x1 +#define HEADER_SIZE_MASK 0xFFFFFFFFFFFFFFF8uLL +#define HEADER_USED 0x1uLL struct free_node_t { uint64_t base; @@ -37,8 +37,11 @@ struct free_node_t { struct alloc_header_t { uint64_t header; + uint64_t resv; } __attribute__((packed)); +_Static_assert(sizeof(struct alloc_header_t) == 16, "struct alloc_header_t must be 16 bytes wide"); + static struct free_node_t* free_list; static struct free_node_t* node_pool; static uint8_t alloc_lock; @@ -74,21 +77,15 @@ static struct free_node_t* alloc_node(void) { } lock_acquire(&alloc_lock); - ret[PAGE_SIZE_4K / sizeof(struct free_node_t)].next = node_pool; + ret[PAGE_SIZE_4K / sizeof(struct free_node_t) - 1].next = node_pool; node_pool = &ret[1]; lock_release(&alloc_lock); } + ret->next = 0; return ret; } -static void free_node(struct free_node_t* node) { - lock_acquire(&alloc_lock); - node->next = free_list; - free_list = node; - lock_release(&alloc_lock); -} - void* kmalloc(size_t size) { struct free_node_t* node, **next; uint64_t ret = 0, adj; @@ -125,11 +122,7 @@ void* kmalloc(size_t size) { lock_release(&alloc_lock); - if (ret) { - ((struct alloc_header_t*)ret)->header = (size - sizeof(struct alloc_header_t)) | HEADER_USED; - ret += sizeof(struct alloc_header_t); - } - else { + if (!ret) { adj = size % PAGE_SIZE_4K; if (adj) { size += PAGE_SIZE_4K - adj; @@ -142,11 +135,11 @@ void* kmalloc(size_t size) { } ret = paging_ident(ret); - - ((struct alloc_header_t*)ret)->header = (size - sizeof(struct alloc_header_t)) | HEADER_USED; - ret += sizeof(struct alloc_header_t); } + ((struct alloc_header_t*)ret)->header = (size) | HEADER_USED; + ret += sizeof(struct alloc_header_t); + return (void*)ret; } @@ -161,11 +154,14 @@ void kfree(void* ptr) { return; } - header->header ^= HEADER_USED; + header->header &= ~HEADER_USED; struct free_node_t* node = alloc_node(); node->size = header->header & HEADER_SIZE_MASK; node->base = (uint64_t)header; - free_node(node); + lock_acquire(&alloc_lock); + node->next = free_list; + free_list = node; + lock_release(&alloc_lock); } diff --git a/kernel/core/kentry.c b/kernel/core/kentry.c index 94777f3..a0fba4a 100644 --- a/kernel/core/kentry.c +++ b/kernel/core/kentry.c @@ -104,7 +104,7 @@ void kapentry(uint64_t arb_id) { logging_log_debug("AP TSS and IDT init"); tss_init(ap_gdts[proc_data_get()->arb_id]); - process_init_ap(init_stacks[arb_id]); + process_init_ap(init_stacks[arb_id] - INIT_STACK_SIZE); idt_init_ap(); logging_log_debug("AP TSS and IDT init done"); From 0fc53c34d27663af860af38094553f93969705a5 Mon Sep 17 00:00:00 2001 From: Ebrahim Aleem Date: Fri, 6 Mar 2026 09:32:34 -0800 Subject: [PATCH 3/3] runtime allocator test --- Makefile | 3 +- kernel/Makefile | 4 + kernel/core/kentry.c | 11 ++ kernel/include/mem_test/alloc_test.h | 23 ++++ kernel/mem_test/alloc_test.c | 175 +++++++++++++++++++++++++++ 5 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 kernel/include/mem_test/alloc_test.h create mode 100644 kernel/mem_test/alloc_test.c diff --git a/Makefile b/Makefile index cc357d4..5856b4e 100644 --- a/Makefile +++ b/Makefile @@ -30,11 +30,12 @@ export BUILD_BOOT_MULTIBOOT2 = 1 # Optional core modules export BUILD_KERNEL_GRAPHICSBASE = 1 +export BUILD_KERNEL_MEM_TEST = 1 + # Optional driver modules export BUILD_DRIVERS_SERIAL = 1 - export BUILD_DRIVERS_HPET = 1 # End of options diff --git a/kernel/Makefile b/kernel/Makefile index 3c648af..ad1fca9 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -26,6 +26,10 @@ ifdef BUILD_KERNEL_GRAPHICSBASE $(call add_directory,graphicsbase,GRAPHICSBASE) endif +ifdef BUILD_KERNEL_MEM_TEST +$(call add_directory,mem_test,MEM_TEST) +endif + ifdef BUILD_DRIVERS_SERIAL DEFINES := $(DEFINES) -DSERIAL endif diff --git a/kernel/core/kentry.c b/kernel/core/kentry.c index a0fba4a..16b2fb8 100644 --- a/kernel/core/kentry.c +++ b/kernel/core/kentry.c @@ -33,6 +33,10 @@ #include +#ifdef MEM_TEST +#include +#endif /* MEM_TEST */ + #include #include #include @@ -50,6 +54,13 @@ extern uint8_t* ap_init_locks; void kentry(void) { logging_log_debug("Kernel Entry"); + +#ifdef MEM_TEST + logging_log_debug("Allocator test"); + alloc_test_assert(); + logging_log_debug("Allocator test pass"); +#endif /* MEM_TEST */ + logging_log_debug("TSS and IDT init"); tss_init((void*)paging_ident((uint64_t)boot_context.gdt)); process_init(0); diff --git a/kernel/include/mem_test/alloc_test.h b/kernel/include/mem_test/alloc_test.h new file mode 100644 index 0000000..8a68803 --- /dev/null +++ b/kernel/include/mem_test/alloc_test.h @@ -0,0 +1,23 @@ +/* alloc_test.h - heap allocator runtime testing interface */ +/* Copyright (C) 2026 Ebrahim Aleem +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +*/ + +#ifndef KERNEL_MEM_TEST_ALLOC_TEST_H +#define KERNEL_MEM_TEST_ALLOC_TEST_H + +extern void alloc_test_assert(void); + +#endif /* KERNEL_MEM_TEST_ALLOC_TEST_H */ diff --git a/kernel/mem_test/alloc_test.c b/kernel/mem_test/alloc_test.c new file mode 100644 index 0000000..ffaefbf --- /dev/null +++ b/kernel/mem_test/alloc_test.c @@ -0,0 +1,175 @@ +/* alloc_test.c - heap allocator runtime testing implementation */ +/* Copyright (C) 2026 Ebrahim Aleem +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see +*/ + +#include + +#include + +#include +#include +#include + +#define NUM_BATCH 16 + +#define INTEGRITY_NUM (((i * 131) ^ (j * 17) ^ alloc_size) & 0xFF) + +void alloc_test_assert(void) { + uint8_t* batch0[NUM_BATCH]; + uint8_t* batch1[NUM_BATCH]; + uint8_t* batch2[NUM_BATCH]; + + uint64_t alloc_size, i, j; + + /* populate batch0 */ + alloc_size = 1; + for (i = 0; i < NUM_BATCH; i++) { + batch0[i] = kmalloc(alloc_size); + + if (!batch0[i]) { + logging_log_error("Allocator assert failed - failed to allocate"); + panic(PANIC_STATE); + } + + for (j = 0; j < alloc_size; j++) { + batch0[i][j] = INTEGRITY_NUM; + } + + alloc_size += 7 + alloc_size; + } + + /* populate batch1 */ + alloc_size = 2; + for (i = 0; i < NUM_BATCH; i++) { + batch1[i] = kmalloc(alloc_size); + + if (!batch1[i]) { + logging_log_error("Allocator assert failed - failed to allocate"); + panic(PANIC_STATE); + } + + for (j = 0; j < alloc_size; j++) { + batch1[i][j] = INTEGRITY_NUM; + } + + alloc_size += 7 + alloc_size; + } + + /* free and assert batch0 */ + alloc_size = 1; + for (i = 0; i < NUM_BATCH; i++) { + for (j = 0; j < alloc_size; j++) { + if (batch0[i][j] != INTEGRITY_NUM) { + logging_log_error("Allocator assert failed - inconsistent data"); + panic(PANIC_STATE); + } + } + + kfree(batch0[i]); + alloc_size += 7 + alloc_size; + } + + /* assert batch1 */ + alloc_size = 2; + for (i = 0; i < NUM_BATCH; i++) { + for (j = 0; j < alloc_size; j++) { + if (batch1[i][j] != INTEGRITY_NUM) { + logging_log_error("Allocator assert failed - inconsistent data"); + panic(PANIC_STATE); + } + } + + alloc_size += 7 + alloc_size; + } + + /* populate batch2 */ + alloc_size = 3; + for (i = 0; i < NUM_BATCH; i++) { + batch2[i] = kmalloc(alloc_size); + + if (!batch2[i]) { + logging_log_error("Allocator assert failed - failed to allocate"); + panic(PANIC_STATE); + } + + for (j = 0; j < alloc_size; j++) { + batch2[i][j] = INTEGRITY_NUM; + } + + alloc_size += 7 + alloc_size; + } + + /* populate batch0 */ + alloc_size = 7; + for (i = 0; i < NUM_BATCH; i++) { + batch0[i] = kmalloc(alloc_size); + + if (!batch0[i]) { + logging_log_error("Allocator assert failed - failed to allocate"); + panic(PANIC_STATE); + } + + for (j = 0; j < alloc_size; j++) { + batch0[i][j] = INTEGRITY_NUM; + } + + alloc_size += 7 + alloc_size; + } + + /* free and assert batch2 */ + alloc_size = 3; + for (i = 0; i < NUM_BATCH; i++) { + for (j = 0; j < alloc_size; j++) { + if (batch2[i][j] != INTEGRITY_NUM) { + logging_log_error("Allocator assert failed - inconsistent data"); + panic(PANIC_STATE); + } + } + + kfree(batch2[i]); + alloc_size += 7 + alloc_size; + } + + /* free and assert batch1 */ + alloc_size = 2; + for (i = 0; i < NUM_BATCH; i++) { + for (j = 0; j < alloc_size; j++) { + if (batch1[i][j] != INTEGRITY_NUM) { + logging_log_error("Allocator assert failed - inconsistent data"); + panic(PANIC_STATE); + } + } + + kfree(batch1[i]); + alloc_size += 7 + alloc_size; + } + + /* free and assert batch0 */ + alloc_size = 7; + for (i = 0; i < NUM_BATCH; i++) { + for (j = 0; j < alloc_size; j++) { + if (batch0[i][j] != INTEGRITY_NUM) { + logging_log_error("Allocator assert failed - inconsistent data"); + panic(PANIC_STATE); + } + } + + kfree(batch0[i]); + alloc_size += 7 + alloc_size; + } + + logging_log_info("All allocation tests passed"); +}