summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorDanny Holman <dholman@gymli.org>2024-03-28 21:55:33 -0500
committerDanny Holman <dholman@gymli.org>2024-03-28 21:55:33 -0500
commit3b66779d9a8325c77c6cfbf1565885f98da5378f (patch)
tree38a1359cbaa1357479a8d57b7c206b190012e783 /arch
parentcbe2690cd5d1b290633c466ebb4df7b64b09b037 (diff)
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 <dholman@gymli.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/i386/kernel/kmalloc.c66
-rw-r--r--arch/i386/make.config1
2 files changed, 67 insertions, 0 deletions
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 <kernel/kmalloc.h>
+#include <kernel/paging.h>
+#include <kernel/pmem.h>
+#include <kernel/asm.h>
+#include <kernel/errno.h>
+#include <kernel/panic.h>
+#include <stdint.h>
+
+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 \