#include #include #include "pmm.h" #include "kprintf.h" #include "bitmap/bitmap.h" #include "bootinfo/bootinfo.h" #include "spinlock/spinlock.h" #define _DIV_ROUNDUP(num, div) ((num + div - 1) / div) PhysMem PHYS_MEM; void pmm_init(void) { spinlock_init(&PHYS_MEM.spinlock); BitMap *bm = &PHYS_MEM.self; bm->init = false; bm->nblocks = _DIV_ROUNDUP(BOOT_INFO.memmap_total, BITMAP_BLOCK_SIZE); bm->nbytes = _DIV_ROUNDUP(bm->nblocks, 8); struct limine_memmap_entry *memmap_ent = NULL; for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) { struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i]; if (entry->type != LIMINE_MEMMAP_USABLE || entry->length < bm->nbytes) { continue; } memmap_ent = entry; break; } if (!memmap_ent) { ERR("hal/pmm", "required memory: {%lx}\n", bm->nbytes); hal_hang(); } size_t physbegin = memmap_ent->base; bm->map = (uint8_t *)(physbegin + BOOT_INFO.hhdm_off); HAL_MEMSET(bm->map, 0xff, bm->nbytes); for (size_t i = 0; i < BOOT_INFO.memmap_entrycount; i++) { struct limine_memmap_entry *entry = BOOT_INFO.memmap_entries[i]; // mark usable as 0 and unusable as 1 bitmap_markregion(bm, (void *)entry->base, entry->length, entry->type != LIMINE_MEMMAP_USABLE); } bitmap_markregion(bm, (void *)physbegin, bm->nbytes, 1); bm->alloc_blocks = 0; LOG("hal/pmm", "phys bitmap init 0x%lx, size = 0x%lx\n", physbegin, bm->nbytes); bm->init = true; } void *pmm_alloc(size_t pages) { spinlock_acquire(&PHYS_MEM.spinlock); uintptr_t phys = (uintptr_t)bitmap_alloc(&PHYS_MEM.self, pages); spinlock_release(&PHYS_MEM.spinlock); if (!phys) { ERR("hal/pmm", "phys memory ran out\n"); hal_hang(); } return (void *)phys; } void pmm_free(uintptr_t ptr, size_t pages) { spinlock_acquire(&PHYS_MEM.spinlock); bitmap_markregion(&PHYS_MEM.self, (void *)ptr, pages * BITMAP_BLOCK_SIZE, 0); spinlock_release(&PHYS_MEM.spinlock); }