Better docs and structure

This commit is contained in:
2026-02-26 21:33:16 +00:00
parent d449150169
commit 13a281fa4f
18 changed files with 892 additions and 387 deletions

View File

@@ -1,5 +1,18 @@
/*
* memory.c Kernel memory management.
*
* Implements three layers:
* PMM bitmap-based physical page-frame allocator backed by a
* 16 MB pool obtained from UEFI at boot.
* Paging walks and creates 4-level x86-64 page tables; supports
* map, unmap, and virtual-to-physical translation.
* Heap first-fit free-list allocator with block splitting and
* bidirectional coalescing; 16-byte aligned.
*/
#include "memory.h"
/* Null-safe print helper used throughout the kernel. */
#define SAFE_PRINT(Boot, ...) \
do { \
if ((Boot) != NULL && (Boot)->print != NULL) { \
@@ -17,21 +30,36 @@ static UINTN pmm_free_count = 0;
static UINT8 pmm_bitmap[PMM_POOL_PAGES / 8];
static BOOLEAN pmm_ready = FALSE;
/* ================================================================
* PMM bitmap helpers
* ================================================================ */
/* Mark page `idx` as allocated. */
static void pmm_set_bit(UINTN idx)
{
pmm_bitmap[idx / 8] |= (UINT8)(1U << (idx % 8));
}
/* Mark page `idx` as free. */
static void pmm_clear_bit(UINTN idx)
{
pmm_bitmap[idx / 8] &= (UINT8)~(1U << (idx % 8));
}
/* Return TRUE if page `idx` is currently allocated. */
static BOOLEAN pmm_test_bit(UINTN idx)
{
return (pmm_bitmap[idx / 8] & (1U << (idx % 8))) != 0;
}
/* ----------------------------------------------------------------
* PMM public interface
* ---------------------------------------------------------------- */
/*
* Initialise the PMM: request PMM_POOL_PAGES from UEFI and set up
* the bitmap with all pages marked free.
*/
void pmm_init(BootInfo *Boot)
{
EFI_STATUS Status;
@@ -66,6 +94,7 @@ void pmm_init(BootInfo *Boot)
pmm_pool_base);
}
/* Allocate a single 4 KB page. Returns physical address or 0. */
UINT64 pmm_alloc_page(void)
{
UINTN i;
@@ -85,6 +114,7 @@ UINT64 pmm_alloc_page(void)
return 0;
}
/* Free a single page previously returned by pmm_alloc_page(). */
void pmm_free_page(UINT64 phys_addr)
{
UINTN idx;
@@ -100,6 +130,7 @@ void pmm_free_page(UINT64 phys_addr)
pmm_free_count++;
}
/* Allocate `count` physically contiguous pages (first-fit). */
UINT64 pmm_alloc_pages(UINTN count)
{
UINTN i, j;
@@ -131,6 +162,7 @@ UINT64 pmm_alloc_pages(UINTN count)
return 0;
}
/* Free `count` contiguous pages starting at phys_addr. */
void pmm_free_pages(UINT64 phys_addr, UINTN count)
{
UINTN i;
@@ -146,6 +178,11 @@ UINTN pmm_get_total_pages(void) { return pmm_total_pages; }
* Paging manipulate the live 4-level x86-64 page tables
* ================================================================ */
/* ================================================================
* Paging low-level helpers
* ================================================================ */
/* Read the CR3 register (physical address of PML4). */
static UINT64 read_cr3(void)
{
UINT64 cr3;
@@ -153,11 +190,13 @@ static UINT64 read_cr3(void)
return cr3;
}
/* Invalidate the TLB entry for virtual address `addr`. */
static void invlpg(UINT64 addr)
{
__asm__ __volatile__("invlpg (%0)" :: "r"(addr) : "memory");
}
/* Return a pointer to the current PML4 table. */
static UINT64 *get_pml4(void)
{
return (UINT64 *)(UINTN)(read_cr3() & PTE_ADDR_MASK);
@@ -197,12 +236,22 @@ static UINT64 *paging_walk_level(UINT64 *table, UINTN index, BOOLEAN create)
return next;
}
/* ----------------------------------------------------------------
* Paging public interface
* ---------------------------------------------------------------- */
/* Log the current CR3 value (identity-mapped by UEFI). */
void paging_init(BootInfo *Boot)
{
SAFE_PRINT(Boot, L" Page: CR3 = 0x%lx (UEFI identity-mapped)\n\r",
read_cr3());
}
/*
* Map a single 4 KB page: virt → phys with the given flags.
* Returns TRUE on success, FALSE if a huge page is in the way or
* page-table allocation failed.
*/
BOOLEAN paging_map_page(UINT64 virt, UINT64 phys, UINT64 flags)
{
UINT64 *pml4, *pdpt, *pd, *pt;
@@ -235,6 +284,7 @@ BOOLEAN paging_map_page(UINT64 virt, UINT64 phys, UINT64 flags)
return TRUE;
}
/* Remove the mapping for a single 4 KB page and flush the TLB. */
void paging_unmap_page(UINT64 virt)
{
UINT64 *pml4, *pdpt, *pd, *pt;
@@ -262,6 +312,10 @@ void paging_unmap_page(UINT64 virt)
invlpg(virt);
}
/*
* Translate a virtual address to its physical counterpart.
* Handles 4 KB, 2 MB, and 1 GB page sizes. Returns 0 if unmapped.
*/
UINT64 paging_get_phys(UINT64 virt)
{
UINT64 *pml4, *pdpt, *pd, *pt;
@@ -302,11 +356,16 @@ UINT64 paging_get_phys(UINT64 virt)
static HeapBlock *heap_start = NULL;
static BOOLEAN heap_ready = FALSE;
/* Round `val` up to the next multiple of `align`. */
static UINTN align_up(UINTN val, UINTN align)
{
return (val + align - 1) & ~(align - 1);
}
/*
* Initialise the heap: allocate HEAP_INITIAL_PAGES from the PMM
* and set up a single free block spanning the entire region.
*/
void heap_init(BootInfo *Boot)
{
UINT64 phys;
@@ -333,6 +392,11 @@ void heap_init(BootInfo *Boot)
heap_size / 1024, phys);
}
/*
* Allocate `size` bytes from the heap (first-fit).
* The returned pointer is aligned to HEAP_ALIGN. Returns NULL on
* failure or heap corruption.
*/
void *kmalloc(UINTN size)
{
HeapBlock *block, *split;
@@ -377,6 +441,10 @@ void *kmalloc(UINTN size)
return NULL; /* out of heap memory */
}
/*
* Free a previously kmalloc'd pointer. Coalesces adjacent free
* blocks to reduce fragmentation.
*/
void kfree(void *ptr)
{
HeapBlock *block;
@@ -416,6 +484,7 @@ void kfree(void *ptr)
}
}
/* Gather aggregate heap statistics. */
void heap_get_stats(UINTN *total, UINTN *used, UINTN *free_mem,
UINTN *num_blocks)
{
@@ -441,6 +510,7 @@ void heap_get_stats(UINTN *total, UINTN *used, UINTN *free_mem,
* Top-level helpers
* ================================================================ */
/* Initialise all memory subsystems in order. */
void memory_init(BootInfo *Boot)
{
SAFE_PRINT(Boot, L"Initializing memory management...\n\r");
@@ -450,6 +520,7 @@ void memory_init(BootInfo *Boot)
SAFE_PRINT(Boot, L"Memory management ready.\n\r\n\r");
}
/* Print a summary of PMM, heap, and paging state to the console. */
void memory_print_stats(BootInfo *Boot)
{
UINTN h_total, h_used, h_free, h_blocks;