From 6374144f4a826e56d77380486b9764f5a2bcd959 Mon Sep 17 00:00:00 2001 From: Kevin Alavik Date: Thu, 15 May 2025 19:52:40 +0200 Subject: [PATCH] feat/kernel: Added First-Fit algorithm for kernel heap --- .vscode/settings.json | 6 ++- kernel/src/boot/emk.h | 2 + kernel/src/emk.c | 17 ++++++++- kernel/src/mm/heap.h | 11 ++++++ kernel/src/mm/heap/ff.c | 82 +++++++++++++++++++++++++++++++++++++++++ kernel/src/mm/heap/ff.h | 18 +++++++++ 6 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 kernel/src/mm/heap.h create mode 100644 kernel/src/mm/heap/ff.c create mode 100644 kernel/src/mm/heap/ff.h diff --git a/.vscode/settings.json b/.vscode/settings.json index f25c33f..ef55fb4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -9,6 +9,10 @@ "typeinfo": "c", "log.h": "c", "pmm.h": "c", - "paging.h": "c" + "paging.h": "c", + "emk.h": "c", + "heap.h": "c", + "vmm.h": "c", + "align.h": "c" } } \ No newline at end of file diff --git a/kernel/src/boot/emk.h b/kernel/src/boot/emk.h index 0e747c7..a083268 100644 --- a/kernel/src/boot/emk.h +++ b/kernel/src/boot/emk.h @@ -4,12 +4,14 @@ #include #include +#include extern uint64_t hhdm_offset; extern struct limine_memmap_response *memmap; extern uint64_t kvirt; extern uint64_t kphys; extern uint64_t kstack_top; +extern vctx_t *kvm_ctx; #define HIGHER_HALF(ptr) ((void *)((uint64_t)(ptr) < hhdm_offset ? (uint64_t)(ptr) + hhdm_offset : (uint64_t)(ptr))) #define PHYSICAL(ptr) ((void *)((uint64_t)(ptr) >= hhdm_offset ? (uint64_t)(ptr) - hhdm_offset : (uint64_t)(ptr))) diff --git a/kernel/src/emk.c b/kernel/src/emk.c index 7780903..7eab3cf 100644 --- a/kernel/src/emk.c +++ b/kernel/src/emk.c @@ -12,6 +12,7 @@ #include #include #include +#include __attribute__((used, section(".limine_requests"))) static volatile LIMINE_BASE_REVISION(3); __attribute__((used, section(".limine_requests"))) static volatile struct limine_memmap_request memmap_request = { @@ -31,6 +32,7 @@ struct limine_memmap_response *memmap = NULL; uint64_t kvirt = 0; uint64_t kphys = 0; uint64_t kstack_top = 0; +vctx_t *kvm_ctx = NULL; void emk_entry(void) { @@ -91,7 +93,7 @@ void emk_entry(void) log_early("Initialized paging"); /* Kernel Virtual Memory Context, not to be confused with KVM */ - vctx_t *kvm_ctx = vinit(kernel_pagemap, 0x1000); + kvm_ctx = vinit(kernel_pagemap, 0x1000); if (!kvm_ctx) { kpanic(NULL, "Failed to create kernel VMM context"); @@ -108,5 +110,18 @@ void emk_entry(void) vfree(kvm_ctx, b); log_early("Initialized virtual page manager"); + /* Setup kernel heap */ + heap_init(); + char *c = kmalloc(1); + if (!c) + { + kpanic(NULL, "Failed to allocate single byte on heap"); + } + + *c = 32; + log_early("Allocated 1 byte @ %llx", (uint64_t)c); + kfree(c); + log_early("Initialized kernel heap"); + hlt(); } \ No newline at end of file diff --git a/kernel/src/mm/heap.h b/kernel/src/mm/heap.h new file mode 100644 index 0000000..208633e --- /dev/null +++ b/kernel/src/mm/heap.h @@ -0,0 +1,11 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#ifndef HEAP_H +#define HEAP_H + +#include + +void heap_init(); +void *kmalloc(size_t size); +void kfree(void *ptr); + +#endif // HEAP_H \ No newline at end of file diff --git a/kernel/src/mm/heap/ff.c b/kernel/src/mm/heap/ff.c new file mode 100644 index 0000000..85386c0 --- /dev/null +++ b/kernel/src/mm/heap/ff.c @@ -0,0 +1,82 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#include +#include +#include +#include +#include +#include +#include + +void *pool; +block_t *freelist = NULL; + +void heap_init() +{ + pool = valloc(kvm_ctx, FF_POOL_SIZE, VALLOC_RW); + if (!pool) + kpanic(NULL, "Failed to alloc memory for the heap pool"); + freelist = (block_t *)pool; + freelist->size = (FF_POOL_SIZE * PAGE_SIZE) - sizeof(block_t); + freelist->next = NULL; +} + +void *kmalloc(size_t size) +{ + if (size == 0) + return NULL; + + size = ALIGN_UP(size, 8); + + block_t *prev = NULL; + block_t *cur = freelist; + + while (cur) + { + if (cur->size >= size) + { + size_t tot_size = sizeof(block_t) + size; + + if (cur->size >= ALIGN_UP(tot_size + sizeof(block_t), 8)) + { + /* do splitting */ + block_t *new_block = (block_t *)((uint8_t *)cur + tot_size); + new_block->size = cur->size - tot_size; + new_block->next = cur->next; + + cur->size = size; + + if (prev) + prev->next = new_block; + else + freelist = new_block; + } + else + { + /* use entire block */ + if (prev) + prev->next = cur->next; + else + freelist = cur->next; + } + + return (void *)((uint8_t *)cur + sizeof(block_t)); + } + prev = cur; + cur = cur->next; + } + + return NULL; +} + +void kfree(void *ptr) +{ + if (!ptr) + return; + + /* get block header */ + block_t *block = (block_t *)((uint8_t *)ptr - sizeof(block_t)); + + /* insert freed block at head of freelist */ + block->next = freelist; + freelist = block; +} \ No newline at end of file diff --git a/kernel/src/mm/heap/ff.h b/kernel/src/mm/heap/ff.h new file mode 100644 index 0000000..9ed39c1 --- /dev/null +++ b/kernel/src/mm/heap/ff.h @@ -0,0 +1,18 @@ +/* EMK 1.0 Copyright (c) 2025 Piraterna */ +#ifndef FF_H +#define FF_H + +/* Kevin's simple First-Fit allocator */ + +#include +#include + +#define FF_POOL_SIZE 512 // 2MB, in pages + +typedef struct block +{ + size_t size; + struct block *next; +} block_t; + +#endif // FF_H \ No newline at end of file