feat(mm): add bitmap physical frame allocator

This commit is contained in:
dualfroz committed 2026-08-25 13:06:40 +02:00
1 parent 371b50a3a5
commit ef45af5077
2 files changed
+183

No files matched your search

+18
View File
@@ -0,0 +1,18 @@
#ifndef FROSTBYTE_PMM_H
#define FROSTBYTE_PMM_H
#include "types.h"
#define frameSize 4096
void pmmInit(uint64 multibootInfo, uint64 protectedEnd);
uint64 pmmAlloc(void);
void pmmFree(uint64 frame);
void pmmReserve(uint64 start, uint64 size);
uint64 pmmReservedEnd(void);
uint64 pmmTotalFrames(void);
uint64 pmmUsedFrames(void);
uint64 pmmFreeFrames(void);
uint64 pmmTotalBytes(void);
#endif
+165
View File
@@ -0,0 +1,165 @@
#include "pmm.h"
#include "multiboot2.h"
#include "string.h"
extern uint8 kernelPhysEnd[];
static uint8* bitmap;
static uint64 frameCount;
static uint64 usedFrames;
static uint64 totalMemoryBytes;
static uint64 reservedEnd;
static uint64 allocHint;
static void markUsed(uint64 frame)
{
if (frame >= frameCount)
return;
uint64 index = frame / 8;
uint8 bit = (uint8)(1 << (frame % 8));
if (!(bitmap[index] & bit)) {
bitmap[index] |= bit;
usedFrames++;
}
}
static void markFree(uint64 frame)
{
if (frame >= frameCount)
return;
uint64 index = frame / 8;
uint8 bit = (uint8)(1 << (frame % 8));
if (bitmap[index] & bit) {
bitmap[index] &= (uint8)~bit;
usedFrames--;
}
}
static bool isUsed(uint64 frame)
{
return (bitmap[frame / 8] & (1 << (frame % 8))) != 0;
}
static uint64 alignUp(uint64 value, uint64 alignment)
{
return (value + alignment - 1) & ~(alignment - 1);
}
void pmmReserve(uint64 start, uint64 size)
{
uint64 first = start / frameSize;
uint64 last = (start + size + frameSize - 1) / frameSize;
for (uint64 frame = first; frame < last; frame++)
markUsed(frame);
}
uint64 pmmReservedEnd(void)
{
return reservedEnd;
}
void pmmInit(uint64 multibootInfo, uint64 protectedEnd)
{
uint32 totalSize = *(uint32*)multibootInfo;
uint64 tagAddr = multibootInfo + 8;
uint64 endAddr = multibootInfo + totalSize;
MultibootTagMmap* mmap = nullptr;
uint64 highestAddr = 0;
while (tagAddr < endAddr) {
MultibootTag* tag = (MultibootTag*)tagAddr;
if (tag->type == multibootTagTypeEnd)
break;
if (tag->type == multibootTagTypeMmap)
mmap = (MultibootTagMmap*)tag;
tagAddr = alignUp(tagAddr + tag->size, 8);
}
if (mmap) {
uint64 entryAddr = (uint64)mmap->entries;
uint64 mmapEnd = (uint64)mmap + mmap->size;
while (entryAddr < mmapEnd) {
MultibootMmapEntry* entry = (MultibootMmapEntry*)entryAddr;
if (entry->type == multibootMemoryAvailable) {
uint64 regionEnd = entry->baseAddr + entry->length;
totalMemoryBytes += entry->length;
if (regionEnd > highestAddr)
highestAddr = regionEnd;
}
entryAddr += mmap->entrySize;
}
}
if (highestAddr == 0)
highestAddr = 128 * 1024 * 1024;
frameCount = highestAddr / frameSize;
uint64 bitmapAnchor = (uint64)kernelPhysEnd;
if (protectedEnd > bitmapAnchor)
bitmapAnchor = protectedEnd;
bitmap = (uint8*)alignUp(bitmapAnchor, frameSize);
uint64 bitmapBytes = (frameCount + 7) / 8;
memset(bitmap, 0xFF, bitmapBytes);
usedFrames = frameCount;
if (mmap) {
uint64 entryAddr = (uint64)mmap->entries;
uint64 mmapEnd = (uint64)mmap + mmap->size;
while (entryAddr < mmapEnd) {
MultibootMmapEntry* entry = (MultibootMmapEntry*)entryAddr;
if (entry->type == multibootMemoryAvailable) {
uint64 first = alignUp(entry->baseAddr, frameSize) / frameSize;
uint64 last = (entry->baseAddr + entry->length) / frameSize;
for (uint64 frame = first; frame < last; frame++)
markFree(frame);
}
entryAddr += mmap->entrySize;
}
}
reservedEnd = alignUp((uint64)bitmap + bitmapBytes, frameSize);
pmmReserve(0, reservedEnd);
allocHint = reservedEnd / frameSize;
}
uint64 pmmAlloc(void)
{
for (uint64 offset = 0; offset < frameCount; offset++) {
uint64 frame = allocHint + offset;
if (frame >= frameCount)
frame -= frameCount;
if (!isUsed(frame)) {
markUsed(frame);
allocHint = frame + 1;
return frame * frameSize;
}
}
return 0;
}
void pmmFree(uint64 frame)
{
markFree(frame / frameSize);
}
uint64 pmmTotalFrames(void)
{
return frameCount;
}
uint64 pmmUsedFrames(void)
{
return usedFrames;
}
uint64 pmmFreeFrames(void)
{
return frameCount - usedFrames;
}
uint64 pmmTotalBytes(void)
{
return totalMemoryBytes;
}