memory #7

Merged
xamidev merged 7 commits from memory into main 2026-01-04 09:28:00 +01:00
Showing only changes of commit 075058a958 - Show all commits

View File

@@ -10,8 +10,10 @@ to see which pages are used by kernel/bootloader/mmio/fb etc.
#include "paging.h" #include "paging.h"
#include <limine.h> #include <limine.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <kernel.h> #include <kernel.h>
#include "../misc/utils.h" #include "../misc/utils.h"
#include "pmm.h"
/* /*
First we'll have to discover the physical memory layout, First we'll have to discover the physical memory layout,
@@ -25,21 +27,43 @@ and use this for the bitmap. The reserved memory will be ignored.
struct usable_memory* usable_mem; struct usable_memory* usable_mem;
struct limine_memmap_entry* biggest_entry; struct limine_memmap_entry* biggest_entry;
/*
uint64_t* bitmap; 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) static void pmm_allocate_bitmap(struct limine_hhdm_response* hhdm)
{ {
uint64_t pages = biggest_entry->length / PAGE_SIZE; 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); bitmap = (uint64_t*)(biggest_entry->base + hhdm->offset);
DEBUG("bitmap will live at 0x%p", bitmap); 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 // 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) static void pmm_find_biggest_usable_region(struct limine_memmap_response* memmap, struct limine_hhdm_response* hhdm)
{ {
// Max length of a usable memory region // Max length of a usable memory region
@@ -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); 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) 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_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());
} }