Files
my-os-project2/kernel/pmm/pmm.c
2025-08-14 01:49:04 +02:00

71 lines
1.9 KiB
C

#include <stddef.h>
#include <limine.h>
#include "pmm.h"
#include "kprintf.h"
#include "bitmap/bitmap.h"
#include "bootinfo/bootinfo.h"
#include "spinlock/spinlock.h"
#include "util/util.h"
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("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("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("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);
}