From 3b66779d9a8325c77c6cfbf1565885f98da5378f Mon Sep 17 00:00:00 2001 From: Danny Holman Date: Thu, 28 Mar 2024 21:55:33 -0500 Subject: arch: i386: kernel: implement a kmalloc function Add a basic kmalloc implementation. This allows the kernel to allocate blocks smaller than a whole page. Signed-off-by: Danny Holman --- arch/i386/kernel/kmalloc.c | 66 ++++++++++++++++++++++++++++++++++++++++++++++ arch/i386/make.config | 1 + 2 files changed, 67 insertions(+) create mode 100644 arch/i386/kernel/kmalloc.c (limited to 'arch') diff --git a/arch/i386/kernel/kmalloc.c b/arch/i386/kernel/kmalloc.c new file mode 100644 index 0000000..183545a --- /dev/null +++ b/arch/i386/kernel/kmalloc.c @@ -0,0 +1,66 @@ +#include +#include +#include +#include +#include +#include +#include + +static uintptr_t heap_start = KEND + 0xC0001000; +static uintptr_t heap_end = 0xFFFFF000; + +static void *kbrk = NULL; +static struct mem_block *first = NULL; + +void _request_page(void) { + uintptr_t paddr = pfa_alloc(); + if (paddr == PFA_ALLOC_ERR) + panic("Out of physical memory"); + + uintptr_t vaddr = PGROUNDDN((uintptr_t)kbrk + PAGE_SIZE); + kbrk += PAGE_SIZE; + map_page(NULL, paddr, vaddr, PD_PRES | PD_RW); +} + +void kmalloc_init(void) { + kbrk = (void*)(heap_start & 0xFFFFF000); + _request_page(); + first = (struct mem_block*)kbrk; + first->start = (uintptr_t)kbrk + sizeof(struct mem_block); + first->size = 0; + first->alloc = 1; + first->next = NULL; +} + +void* kmalloc(size_t sz) { + if (kbrk == NULL) + panic("Attmpted to malloc before initialization"); + if ((uintptr_t)kbrk >= heap_end) + return NULL; + + struct mem_block *temp = first; + while (temp->next != NULL) { + if (temp->size <= sz && temp->alloc == 0) + return (void*)temp->start; + temp = temp->next; + } + + temp->next = (struct mem_block*)((uintptr_t)temp + sizeof(struct mem_block) + temp->size); + temp = temp->next; + temp->start = (uintptr_t)(temp + sizeof(struct mem_block)); + temp->size = sz; + temp->alloc = 1; + temp->next = NULL; + return (void*)temp->start; +} + +void kfree(void *ptr) { + struct mem_block *temp = first; + while (temp->next != NULL) { + if (temp->start == (uintptr_t)ptr) { + temp->alloc = 0; + return; + } + } + panic("Attempted to free memory not alloc'd"); +} diff --git a/arch/i386/make.config b/arch/i386/make.config index 1ffe8be..8499f1a 100644 --- a/arch/i386/make.config +++ b/arch/i386/make.config @@ -16,3 +16,4 @@ KERNEL_ARCH_OBJS=$(ARCHDIR)/boot/boot.o \ $(ARCHDIR)/kernel/syscall.o \ $(ARCHDIR)/kernel/paging.o \ $(ARCHDIR)/kernel/pmem.o \ + $(ARCHDIR)/kernel/kmalloc.o \ -- cgit v1.2.3