From 075058a958641b3c7067b6ba10c4847ec39382a1 Mon Sep 17 00:00:00 2001 From: xamidev Date: Wed, 31 Dec 2025 17:42:26 +0100 Subject: [PATCH] PMM: init with freelist --- src/mem/paging/pmm.c | 83 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 78 insertions(+), 5 deletions(-) diff --git a/src/mem/paging/pmm.c b/src/mem/paging/pmm.c index 0f1e956..3ce044b 100644 --- a/src/mem/paging/pmm.c +++ b/src/mem/paging/pmm.c @@ -10,8 +10,10 @@ to see which pages are used by kernel/bootloader/mmio/fb etc. #include "paging.h" #include #include +#include #include #include "../misc/utils.h" +#include "pmm.h" /* First we'll have to discover the physical memory layout, @@ -25,20 +27,42 @@ and use this for the bitmap. The reserved memory will be ignored. struct usable_memory* usable_mem; struct limine_memmap_entry* biggest_entry; - +/* uint64_t* bitmap; +uint64_t* usable_memory_begin; +// Bitmap will be placed at the start of the biggest usable region +// 1 bitmap page = 4096 bytes = 32768 bits +// So 1 bitmap page can track up to 32768 pages of memory static void pmm_allocate_bitmap(struct limine_hhdm_response* hhdm) { uint64_t pages = biggest_entry->length / PAGE_SIZE; - DEBUG("we need %u pages (bits) that will fit in %u uint64_t", pages, pages/64); + uint64_t bitmap_items = (pages+BITS_PER_ROW-1)/BITS_PER_ROW; + DEBUG("we need %u pages (bits) that will fit in %u uint64_t", pages, bitmap_items); bitmap = (uint64_t*)(biggest_entry->base + hhdm->offset); DEBUG("bitmap will live at 0x%p", bitmap); + uint64_t bitmap_bytes = bitmap_items*sizeof(uint64_t); + // All pages are marked free since we're in a USABLE region - memset(bitmap, 0x00, pages/64); -} + memset(bitmap, 0x00, bitmap_bytes); + + uint64_t bitmap_pages = (bitmap_bytes + PAGE_SIZE - 1) / PAGE_SIZE; + + // The 1st memory page we can use is at bitmap + bitmap_pages + usable_memory_begin = (void*)((uintptr_t)bitmap + bitmap_pages*PAGE_SIZE); + + // Mark bitmap as allocated + for (uint64_t i=0; ibase+offset, biggest_entry->base+biggest_entry->length+offset); } +// Offset from Higher Half Direct Map +uint64_t hhdm_off; + +static uintptr_t g_freelist = 0; + +#define PHYS_TO_VIRT(x) ((void*)((uintptr_t)(x) + hhdm_off)) +#define VIRT_TO_PHYS(x) ((uintptr_t)(x) - hhdm_off) + +// Stole it +#define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1)) +#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1)) + +uintptr_t pmm_alloc() +{ + if (!g_freelist) return 0; + uintptr_t addr = g_freelist; + g_freelist = *(uintptr_t*) PHYS_TO_VIRT(g_freelist); + return addr; +} + +void pmm_free(uintptr_t addr) +{ + *(uintptr_t*) PHYS_TO_VIRT(addr) = g_freelist; + g_freelist = addr; +} + +static void pmm_init_freelist() +{ + // We simply call pmm_free() on each page that is marked USABLE + // in our big memory region. + uint64_t base = ALIGN_UP(biggest_entry->base, PAGE_SIZE); + uint64_t end = ALIGN_DOWN(biggest_entry->base + biggest_entry->length, PAGE_SIZE); + + uint64_t page_count=0; + for (uint64_t addr = base; addr < end; addr += PAGE_SIZE) + { + pmm_free(addr); + //DEBUG("page %u lives at phys 0x%p (virt 0x%p)", page_count, addr, PHYS_TO_VIRT(addr)); + //page_count++; + } +} + void pmm_init(struct limine_memmap_response* memmap, struct limine_hhdm_response* hhdm) { + hhdm_off = hhdm->offset; pmm_find_biggest_usable_region(memmap, hhdm); - pmm_allocate_bitmap(hhdm); + //pmm_allocate_bitmap(hhdm); too complicated for my small brain + + // Now we have biggest USABLE region, + // so to populate the free list we just iterate through it + pmm_init_freelist(); + + DEBUG("Trying pmm_alloc gives us page at 0x%p", pmm_alloc()); } \ No newline at end of file