~kernel/archive/c/pmm.c
.c
C
(text/x-csrc)
#include <stdint.h>
#include "module.h"
#include "pmm.h"

#define KERNEL_HEAP_START 0x200000
#define KERNEL_HEAP_SIZE  (16 * 1024 * 1024)

static uint8_t *heap_ptr = (uint8_t*)KERNEL_HEAP_START;
static uint8_t *heap_end = (uint8_t*)(KERNEL_HEAP_START + KERNEL_HEAP_SIZE);

/* Simple bitmap for page allocation (supports up to 16 MiB) */
#define TOTAL_PAGES (KERNEL_HEAP_SIZE / PAGE_SIZE)
static uint64_t page_bitmap[TOTAL_PAGES / 64] = {0};

static void set_page_used(uint64_t page) {
    page_bitmap[page / 64] |= (1ULL << (page % 64));
}
static void clear_page_used(uint64_t page) {
    page_bitmap[page / 64] &= ~(1ULL << (page % 64));
}
static int is_page_used(uint64_t page) {
    return (page_bitmap[page / 64] >> (page % 64)) & 1ULL;
}

/* Initialize the physical memory manager */
void pmm_init(void) {
    for (uint64_t i = 0; i < TOTAL_PAGES; ++i) {
        clear_page_used(i);
    }
}

/* Allocate a single 4 KiB page */
void *pmm_alloc_page(void) {
    for (uint64_t i = 0; i < TOTAL_PAGES; ++i) {
        if (!is_page_used(i)) {
            set_page_used(i);
            return (void*)(KERNEL_HEAP_START + i * PAGE_SIZE);
        }
    }
    return 0; /* Out of memory */
}

/* Free a previously allocated page */
void pmm_free_page(void *page) {
    uint64_t addr = (uint64_t)page;
    if (addr < KERNEL_HEAP_START || addr >= KERNEL_HEAP_START + KERNEL_HEAP_SIZE) return;
    uint64_t page_idx = (addr - KERNEL_HEAP_START) / PAGE_SIZE;
    clear_page_used(page_idx);
}

/* Existing bump allocator (kept for compatibility) */
void *kalloc(uint64_t bytes) {
    uint8_t *ret = heap_ptr;
    uint64_t size = (bytes + 7) & ~7;
    if (heap_ptr + size > heap_end) return 0;
    heap_ptr += size;
    return ret;
}