PMM: init with freelist
This commit is contained in:
@@ -10,8 +10,10 @@ to see which pages are used by kernel/bootloader/mmio/fb etc.
|
||||
#include "paging.h"
|
||||
#include <limine.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <kernel.h>
|
||||
#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; i<bitmap_pages; i++)
|
||||
{
|
||||
uint64_t row = i / BITS_PER_ROW;
|
||||
uint64_t bit = i % BITS_PER_ROW;
|
||||
bitmap[row] |= (1ULL << bit);
|
||||
}
|
||||
|
||||
DEBUG("bitmap occupies %u pages", bitmap_pages);
|
||||
} */
|
||||
|
||||
static void pmm_find_biggest_usable_region(struct limine_memmap_response* memmap, struct limine_hhdm_response* hhdm)
|
||||
{
|
||||
@@ -68,8 +92,57 @@ static void pmm_find_biggest_usable_region(struct limine_memmap_response* memmap
|
||||
biggest_entry->base+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());
|
||||
}
|
||||
Reference in New Issue
Block a user