Added bitmap_t type and bmap_* functions & used them in PMM

This commit is contained in:
2025-04-05 15:44:55 +02:00
parent 25771de53e
commit b104755904
7 changed files with 127 additions and 102 deletions
+44 -86
View File
@@ -4,26 +4,18 @@
#include <string.h>
#include <pmm.h>
// Bitmap & helpers
uint32_t* bitmap;
int pmm_ready = 0;
#define SET_BLOCK(_b) bitmap[(_b) / 32] |= (1 << ((_b) % 32))
#define USET_BLOCK(_b) bitmap[(_b) / 32] &= ~(1 << ((_b) % 32))
#define TEST_BLOCK(_b) ((bitmap[(_b) / 32] & (1 << ((_b) % 32))) ? 1 : 0)
// Status
size_t usedBlocks = 0;
size_t maxBlocks = 0;
// Bitmap
bitmap_t pmm_bitmap;
int pmm_init(void) {
size_t totalmem = (bootloader.memLower + bootloader.memUpper) * 1024;
maxBlocks = dceil(totalmem, PMM_BS);
size_t bitmapBytes = dceil(maxBlocks, PMM_BPB);
usedBlocks = maxBlocks;
bitmap = NULL;
pmm_bitmap.blocks = dceil(totalmem, BLOCK_SIZE);
pmm_bitmap.bytes = dceil(pmm_bitmap.blocks, 8);
pmm_bitmap.map = NULL;
// # of pagetabs required to map the bitmap
size_t ptcount = dceil(dceil(bitmapBytes, PAGE_SIZE), 1024);
size_t ptcount = dceil(dceil(pmm_bitmap.bytes, PAGE_SIZE), 1024);
// Find enough space for the bitmap
struct boot_memmap* mmap;
@@ -31,8 +23,7 @@ int pmm_init(void) {
for (size_t i = 0; i < bootloader.memmapLen; i++) {
mmap = &bootloader.memmap[i];
if (mmap->type == BOOT_MMAP_AVAILABLE &&
mmap->size >= maxBlocks / PMM_BPB) {
if (mmap->type == BOOT_MMAP_AVAILABLE && mmap->size >= pmm_bitmap.bytes) {
found = 1;
break;
}
@@ -43,109 +34,76 @@ int pmm_init(void) {
pag_registerTempFrame(pageFrameStart);
mmap->base += ptcount * PAGE_SIZE;
uint32_t bitmapStart = KERNEL_HEAP - dceil(bitmapBytes, PAGE_SIZE) * PAGE_SIZE;
uint32_t bitmapStart = KERNEL_MEM_BASE - dceil(pmm_bitmap.bytes, PAGE_SIZE) * PAGE_SIZE;
uint32_t bitmapStartPhys = mmap->base;
bitmap = (uint32_t*)bitmapStart;
pmm_bitmap.map = (void*)bitmapStart;
size_t pagecount = dceil(bitmapBytes, PAGE_SIZE);
size_t pagecount = dceil(pmm_bitmap.bytes, PAGE_SIZE);
for (size_t i = 0; i < pagecount; i++) {
// We can't unmap this with pag_umapPage(), it's in a tempFrame
// NOTE: We can't unmap this with pag_umapPage(), it's in a tempFrame
pag_mapPage(bitmapStart + i * PAGE_SIZE, mmap->base + i * PAGE_SIZE, 0);
}
// Set all blocks as used
memset(bitmap, 0xff, maxBlocks / PMM_BPB);
bmap_setall(&pmm_bitmap, 1);
debugf("[pmm] Memory map:\n"); // Use the loop to also print the memmap
for (size_t i = 0; i < bootloader.memmapLen; i++) {
mmap = &bootloader.memmap[i];
if (mmap->size == 0) continue; // Ignore dummy entries
if (mmap->type == BOOT_MMAP_AVAILABLE) pmm_initRegion(mmap->base, mmap->size);
// Print entry
debugf("\tRegion %2d: 0x%08x - 0x%08x (%d bytes) %s\n",
i + 1, mmap->base, mmap->base + mmap->size - 1, mmap->size,
(mmap->type == BOOT_MMAP_AVAILABLE) ? "AVAILABLE" : "RESERVED");
}
pmm_deinitRegion(bitmapStartPhys, bitmapBytes);
pmm_deinitRegion(bitmapStartPhys, pmm_bitmap.bytes);
pmm_deinitRegion(pageFrameStart, ptcount * PAGE_SIZE);
// Beatifull print statement :)
debugf(
"[pmm] Physical memory manager initialized.\n"
"\tAvailable memory: %d blocks free (%d bytes)\n"
"\tBitmap at phys(%08x), virt(%08x), %d bytes\n",
maxBlocks - usedBlocks, (maxBlocks - usedBlocks) * PMM_BS,
bitmapStartPhys, bitmapStart, bitmapBytes
"\tBitmap at 0x%08x mapped to 0x%08x\n"
"\tBitmap is %d bytes contained in %d pages\n",
pmm_bitmap.blocks - pmm_bitmap.used,
(pmm_bitmap.blocks - pmm_bitmap.used) * BLOCK_SIZE,
bitmapStartPhys, bitmapStart, pmm_bitmap.bytes, pagecount
);
pmm_ready = 1;
pmm_bitmap.ready = 1;
return 0;
}
int findFreeBlocks(size_t blockCount) {
if (blockCount == 0) return -1;
uint32_t max = maxBlocks / 32;
uint32_t freeCount = 0;
for (size_t i = 0; i < max; i++) {
// We don't have to check, cause it's all used
if (bitmap[i] == 0xffffffff) continue;
for (uint8_t j = 0; j < 32; j++) {
if (TEST_BLOCK(i * PMM_BPB + j) == 0) freeCount++;
else freeCount = 0;
if (freeCount >= blockCount) return i * PMM_BPB + j;
}
}
// We didn't find enough free memory :(
return -1;
}
void pmm_initRegion(size_t base, size_t len) {
uint32_t align = base / PMM_BS;
uint32_t blockCount = len / PMM_BS;
while (blockCount-- > 0) {
USET_BLOCK(align);
align++;
usedBlocks--;
}
SET_BLOCK(0);
bmap_setarea(&pmm_bitmap, base, len, 0);
bmap_set(&pmm_bitmap, 0, 1);
}
void pmm_deinitRegion(size_t base, size_t len) {
uint32_t align = base / PMM_BS;
uint32_t blockCount = len / PMM_BS;
while (blockCount-- > 0) {
SET_BLOCK(align); // We can't increment here, because macros -_(._.)_-
align++;
usedBlocks++;
}
SET_BLOCK(0);
bmap_setarea(&pmm_bitmap, base, len, 1);
bmap_set(&pmm_bitmap, 0, 1);
}
void* pmm_alloc(size_t blockCount) {
if ((maxBlocks - usedBlocks) < blockCount) return NULL;
void* pmm_alloc(size_t len) {
if (pmm_bitmap.blocks - pmm_bitmap.used < len) return NULL;
int startBlock = findFreeBlocks(blockCount);
if (startBlock == -1) return NULL;
size_t base = bmap_findarea(&pmm_bitmap, len, 0);
if (base == BMAP_NOT_FOUND) return NULL;
bmap_setarea(&pmm_bitmap, base, len, 1);
for (size_t i = 0; i < blockCount; i++) {
SET_BLOCK(startBlock + i);
usedBlocks++;
}
return (void*)(startBlock * PMM_BS);
return (void*)(base * BLOCK_SIZE);
}
void pmm_free(void* ptr, size_t blockCount) {
size_t startBlock = (size_t)ptr / PMM_BS;
for (size_t i = 0; i < blockCount; i++) {
USET_BLOCK(startBlock + i);
usedBlocks--;
}
SET_BLOCK(0); // Make sure block 0 is always set
void pmm_free(void* ptr, size_t len) {
size_t base = (size_t)ptr / BLOCK_SIZE;
bmap_setarea(&pmm_bitmap, base, len, 0);
bmap_set(&pmm_bitmap, 0, 1);
}