72 lines
1.9 KiB
C
72 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"
|
|
|
|
#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);
|
|
}
|