Files
bsb2/kernel/memory/pageframealloc.cc
2026-02-03 21:02:33 +01:00

144 lines
4.3 KiB
C++

#include "../memory/pageframealloc.h"
#include "../boot/multiboot/data.h"
#include "page.h"
#include "pageframe.h"
#include "../debug/output.h"
#include "../memory/config.h"
#include "../arch/lapic.h"
#include "../arch/apic.h"
//uint8_t PageFrameAllocator::bitmap[4294967296 / 4096 / 8];
PageFrame PageFrameAllocator::PageFrames[4294967296 / 4096];
void mark_pageframes(uintptr_t start, uintptr_t end, bool available){
// DBG << "start: " << hex << start << " end: " << end;
start = Page::floor(start);
end = Page::ceil(end);
if(start > 4294967296)
start = 4294967296;
if(end > 4294967296)
end = 4294967296;
//DBG << " page start: " << hex << start << " end: " << end << endl;
for(uint64_t i = start; i < end; i += 4096){
uint64_t pg = i/4096;
PageFrameAllocator::PageFrames[pg].available = available;
//if(available)
// PageFrameAllocator::bitmap[pg/8] |= (1 << pg%8);
//else
// PageFrameAllocator::bitmap[pg/8] &= ~(1 << pg%8);
}
}
void PageFrameAllocator::init(){
Multiboot::Memory* memory_map_start = Multiboot::getMemoryMap();
Multiboot::Memory* memory_map_entry = memory_map_start;
//mark as available
while(memory_map_entry != 0){
uintptr_t start = (uintptr_t)memory_map_entry->getStartAddress();
uintptr_t end = (uintptr_t)memory_map_entry->getEndAddress();
bool available = memory_map_entry->isAvailable();
if(available)
mark_pageframes(start, end, true);
memory_map_entry = memory_map_entry->getNext();
}
//mark as unavailable
memory_map_entry = memory_map_start;
while(memory_map_entry != 0){
uintptr_t start = (uintptr_t)memory_map_entry->getStartAddress();
uintptr_t end = (uintptr_t)memory_map_entry->getEndAddress();
bool available = memory_map_entry->isAvailable();
if(!available)
mark_pageframes(start, end, false);
memory_map_entry = memory_map_entry->getNext();
}
//mark other known regions as unavailable
mark_pageframes((uintptr_t)&___KERNEL_START___, (uintptr_t)&___KERNEL_END___, false);
mark_pageframes(0x00F00000, 0x00FFFFFF, false);
mark_pageframes(0xfee00000, 0xfee003f0, false);
mark_pageframes(APIC::getIOAPICAddress(), APIC::getIOAPICAddress()+0x10, false);
}
void PageFrameAllocator::stats(){
Multiboot::Memory* memory_map_entry = Multiboot::getMemoryMap();
while(memory_map_entry != 0){
void* start = memory_map_entry->getStartAddress();
void* end = memory_map_entry->getEndAddress();
bool available = memory_map_entry->isAvailable();
DBG << "Memory: " << hex << start << " to " << end << " is available: " << available << "." << endl;
memory_map_entry = memory_map_entry->getNext();
}
uint64_t pages_available = 0;
for(uint64_t i=0; i<(sizeof(PageFrames)/sizeof(PageFrames[0]));i++){
if(PageFrames[i].available)
//if(bitmap[i/8] & (1<<i%8))
pages_available++;
}
for(uint64_t i=0; i < 0x2000000/4096/8; i++){
if(i%64 == 0){
DBG << endl << hex << i * 8 * 4096 << " " << flush;
int x,y;
dout.getPos(x,y);
for(uint8_t j=x; j<10; j++){
DBG<<" ";
}
}
if(PageFrames[i].available)
DBG << '#';
else
DBG << '.';
}
DBG << "\npages available: " << dec << pages_available << endl;
}
PageFrame* PageFrameAllocator::alloc(bool kernel){
uintptr_t search_start;
uintptr_t search_end;
if(kernel){
search_start = Page::ceil((uintptr_t)&___KERNEL_END___);
search_end = 0x4000000;
}
else{
search_start = 0x4000000;
search_end = 0x8000000; //TODO find some appropriate value
}
uint64_t free_pageframe=0;
//TODO make this more efficent
for(uint64_t i=search_start/4096; i < search_end/4096; i++){
if(PageFrames[i].available){
free_pageframe = i;
break;
}
}
if(!free_pageframe)
return 0;
mark_pageframes(free_pageframe*4096, free_pageframe*4096, false);
return &PageFrames[free_pageframe];
}
void PageFrameAllocator::free(PageFrame* frame){
(void) frame;
}
void PageFrameAllocator::free(uintptr_t addr){
(void) addr;
}