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 + include/kernel/data/ringbuf.h | 2 +- include/kernel/kmalloc.h | 18 ++++++++++++ kernel/init.c | 6 +++- 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 arch/i386/kernel/kmalloc.c create mode 100644 include/kernel/kmalloc.h 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 \ diff --git a/include/kernel/data/ringbuf.h b/include/kernel/data/ringbuf.h index 4f30874..25a7125 100644 --- a/include/kernel/data/ringbuf.h +++ b/include/kernel/data/ringbuf.h @@ -1,7 +1,7 @@ #ifndef KERNEL_RINGBUF_H #define KERNEL_RINGBUF_H -#include +#include #include #include diff --git a/include/kernel/kmalloc.h b/include/kernel/kmalloc.h new file mode 100644 index 0000000..d8debd1 --- /dev/null +++ b/include/kernel/kmalloc.h @@ -0,0 +1,18 @@ +#ifndef KERNEL_KMALLOC_H +#define KERNEL_KMALLOC_H + +#include +#include + +struct mem_block { + uintptr_t start; + size_t size; + int alloc; + struct mem_block *next; +}; + +void kmalloc_init(void); +void* kmalloc(size_t sz); +void kfree(void *ptr); + +#endif diff --git a/kernel/init.c b/kernel/init.c index 8512988..98ac05c 100644 --- a/kernel/init.c +++ b/kernel/init.c @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -21,7 +22,10 @@ void process_cmd(char *cmdline) { } void kernel_main(char *cmdline) { + kmalloc_init(); kprintf("Box Kernel version %s\n", VERSION); serial_init(); - kmalloc_init(); + sched_init(); + + //jump_userspace(); } -- cgit v1.2.3