#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);
#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;
}
void pmm_init(void) {
for (uint64_t i = 0; i < TOTAL_PAGES; ++i) {
clear_page_used(i);
}
}
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;
}
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);
}
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;
}