summaryrefslogtreecommitdiff
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
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>
-rw-r--r--arch/i386/kernel/kmalloc.c66
-rw-r--r--arch/i386/make.config1
-rw-r--r--include/kernel/data/ringbuf.h2
-rw-r--r--include/kernel/kmalloc.h18
-rw-r--r--kernel/init.c6
5 files changed, 91 insertions, 2 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 \
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 <kernel/mem.h>
+#include <kernel/kmalloc.h>
#include <kernel/string.h>
#include <stdint.h>
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 <stdint.h>
+#include <stddef.h>
+
+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 <kernel/io.h>
+#include <kernel/sched.h>
#include <kernel/kmalloc.h>
#include <kernel/string.h>
#include <kernel/serial.h>
@@ -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();
}