From 0be35869d226aa2edc47dea07e0aca1c73f677d5 Mon Sep 17 00:00:00 2001 From: dzwdz Date: Mon, 15 Jul 2024 12:56:25 +0200 Subject: kernel: split the page allocator and kmalloc --- src/kernel/malloc.c | 101 --------------------------------------------- src/kernel/pagealloc.c | 108 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 101 deletions(-) create mode 100644 src/kernel/pagealloc.c diff --git a/src/kernel/malloc.c b/src/kernel/malloc.c index 0d5cba3..7385cf3 100644 --- a/src/kernel/malloc.c +++ b/src/kernel/malloc.c @@ -20,78 +20,12 @@ struct Allocation { static Allocation *malloc_last = NULL; -extern uint8_t pbitmap[]; /* linker.ld */ -static size_t pbitmap_len; /* in bytes */ -static void *firstfreepage; /* not necessarily actually free */ -static void *memtop; - -static size_t -toindex(void *p) -{ - assert((void*)pbitmap <= p); - return ((uintptr_t)p - (uintptr_t)pbitmap) / PAGE_SIZE; -} - -static bool -pbitmap_get(void *p) -{ - size_t i = toindex(p); - size_t b = i / 8; - uint8_t m = 1 << (i&7); - assert(b < pbitmap_len); // TODO the bitmap should be a tad longer - return (pbitmap[b]&m) != 0; -} - -static bool -pbitmap_set(void *p, bool v) -{ - size_t i = toindex(p); - size_t b = i / 8; - uint8_t m = 1 << (i&7); - assert(b < pbitmap_len); - bool prev = (pbitmap[b]&m) != 0; - if (v) { - pbitmap[b] |= m; - } else { - pbitmap[b] &= ~m; - } - return prev; -} - static size_t page_amt(size_t bytes) { return (bytes + PAGE_SIZE - 1) / PAGE_SIZE; } -void -mem_init(void *p) -{ - memtop = p; - kprintf("memory %8x -> %8x\n", &_bss_end, memtop); - pbitmap_len = toindex(memtop) / 8; - memset(pbitmap, 0, pbitmap_len); - mem_reserve(pbitmap, pbitmap_len); - firstfreepage = pbitmap; -} - -void -mem_reserve(void *addr, size_t len) -{ - kprintf("reserved %8x -> %8x\n", addr, addr + len); - - void *top = min(addr + len, memtop); - addr = (void*)((uintptr_t)addr & ~PAGE_MASK); /* round down to page */ - for (void *p = max(addr, (void*)pbitmap); p < top; p += PAGE_SIZE) { - /* this doesn't allow overlapping reserved regions, but, more - * importantly, it prevents reserving an already allocated page */ - if (pbitmap_get(p)) { - panic_invalid_state(); - } - pbitmap_set(p, true); - } -} - void mem_debugprint(void) { @@ -119,41 +53,6 @@ mem_debugprint(void) ); } -void * -page_alloc(size_t pages) -{ - assert(pages == 1); - for (void *p = firstfreepage; p < memtop; p += PAGE_SIZE) { - if (!pbitmap_get(p)) { - pbitmap_set(p, true); - firstfreepage = p + PAGE_SIZE; - return p; - } - } - kprintf("we ran out of memory :(\ngoodbye.\n"); - panic_unimplemented(); -} - -void * -page_zalloc(size_t pages) -{ - void *p = page_alloc(pages); - memset(p, 0, pages * PAGE_SIZE); - return p; -} - -void -page_free(void *addr, size_t pages) -{ - assert((void*)pbitmap <= addr); - for (size_t i = 0; i < pages; i++) { - if (pbitmap_set(addr + i*PAGE_SIZE, false) == false) { - panic_invalid_state(); - } - } - firstfreepage = min(firstfreepage, addr); -} - static void kmalloc_sanity(const void *addr) { diff --git a/src/kernel/pagealloc.c b/src/kernel/pagealloc.c new file mode 100644 index 0000000..f01c295 --- /dev/null +++ b/src/kernel/pagealloc.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include +#include +#include +#include + +extern uint8_t pbitmap[]; /* linker.ld */ +static size_t pbitmap_len; /* in bytes */ +static void *memtop; +static void *firstfreepage; /* not necessarily actually free */ + +static size_t +toindex(void *p) +{ + assert((void*)pbitmap <= p); + return ((uintptr_t)p - (uintptr_t)pbitmap) / PAGE_SIZE; +} + +static bool +pbitmap_get(void *p) +{ + size_t i = toindex(p); + size_t b = i / 8; + uint8_t m = 1 << (i&7); + assert(b < pbitmap_len); // TODO the bitmap should be a tad longer + return (pbitmap[b]&m) != 0; +} + +static bool +pbitmap_set(void *p, bool v) +{ + size_t i = toindex(p); + size_t b = i / 8; + uint8_t m = 1 << (i&7); + assert(b < pbitmap_len); + bool prev = (pbitmap[b]&m) != 0; + if (v) { + pbitmap[b] |= m; + } else { + pbitmap[b] &= ~m; + } + return prev; +} + +void +mem_init(void *p) +{ + memtop = p; + kprintf("memory %8x -> %8x\n", &_bss_end, memtop); + pbitmap_len = toindex(memtop) / 8; + memset(pbitmap, 0, pbitmap_len); + mem_reserve(pbitmap, pbitmap_len); + firstfreepage = pbitmap; +} + +void +mem_reserve(void *addr, size_t len) +{ + kprintf("reserved %8x -> %8x\n", addr, addr + len); + + void *top = min(addr + len, memtop); + addr = (void*)((uintptr_t)addr & ~PAGE_MASK); /* round down to page */ + for (void *p = max(addr, (void*)pbitmap); p < top; p += PAGE_SIZE) { + /* this doesn't allow overlapping reserved regions, but, more + * importantly, it prevents reserving an already allocated page */ + if (pbitmap_get(p)) { + panic_invalid_state(); + } + pbitmap_set(p, true); + } +} + +void * +page_zalloc(size_t pages) +{ + void *p = page_alloc(pages); + memset(p, 0, pages * PAGE_SIZE); + return p; +} + +void * +page_alloc(size_t pages) +{ + assert(pages == 1); + for (void *p = firstfreepage; p < memtop; p += PAGE_SIZE) { + if (!pbitmap_get(p)) { + pbitmap_set(p, true); + firstfreepage = p + PAGE_SIZE; + return p; + } + } + kprintf("we ran out of memory :(\ngoodbye.\n"); + panic_unimplemented(); +} + +void +page_free(void *addr, size_t pages) +{ + assert((void*)pbitmap <= addr); + for (size_t i = 0; i < pages; i++) { + if (pbitmap_set(addr + i*PAGE_SIZE, false) == false) { + panic_invalid_state(); + } + } + firstfreepage = min(firstfreepage, addr); +} -- cgit v1.2.3