#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]; Queue user_memory_q; Queue kernel_memory_q; 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; if(start < 0x4000000 && end > 0x4000000){ mark_pageframes(start, 0x4000000, available); mark_pageframes(0x4000000, end, available); } //DBG << " page start: " << hex << start << " end: " << end << endl; Queue* q = start<0x4000000?&kernel_memory_q:&user_memory_q; for(uint64_t i = start; i < end; i += 4096){ uint64_t pg = i/4096; PageFrameAllocator::PageFrames[pg].available = available; if(available) q->enqueue(PageFrameAllocator::PageFrames[pg]); else q->remove(&PageFrameAllocator::PageFrames[pg]); } } 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){ if(start < (uintptr_t)&___KERNEL_END___) start = Page::ceil((uintptr_t)&___KERNEL_END___ +1); mark_pageframes(start, end, available); } 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, available); } memory_map_entry = memory_map_entry->getNext(); } Multiboot::Module* mod = Multiboot::getModule(0); mark_pageframes((uintptr_t)mod, (uintptr_t)mod+1, false); mark_pageframes((uintptr_t)mod->getStartAddress(), (uintptr_t)mod->getEndAddress(), false); //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<* q = kernel?&kernel_memory_q:&user_memory_q; PageFrame* free_pageframe = q->dequeue(); if(!free_pageframe) return 0; free_pageframe->available = false; uintptr_t addr = ((free_pageframe - &PageFrames[0]))<<12; mark_pageframes(addr, addr+1, false); return (void*)(addr); } void PageFrameAllocator::free(PageFrame* frame){ frame->available = true; //TODO ref counter etc... } void PageFrameAllocator::free(uintptr_t addr){ free(&PageFrames[addr>>12]); }