diff --git a/zion/memory/physical_memory.cpp b/zion/memory/physical_memory.cpp index 2e89b7f..29fc465 100644 --- a/zion/memory/physical_memory.cpp +++ b/zion/memory/physical_memory.cpp @@ -15,6 +15,69 @@ struct BootstrapMemory { static BootstrapMemory gBootstrap; static bool gBootstrapEnabled = false; +class PhysicalMemoryManager { + public: + // Reads the memory map and takes + // control of the available regions. + PhysicalMemoryManager() { + const limine_memmap_response& memmap = boot::GetMemoryMap(); + for (uint64_t i = 0; i < memmap.entry_count; i++) { + const limine_memmap_entry& entry = *memmap.entries[i]; + if (entry.type == 0) { + uint64_t base = entry.base; + uint64_t size = entry.length; + if (base == gBootstrap.init_page) { + base = gBootstrap.next_page; + uint64_t bootstrap_used = gBootstrap.next_page - gBootstrap.init_page; + dbgln("[PMM] Taking over from bootstrap, used: %x", bootstrap_used); + size -= bootstrap_used; + } + AddMemoryRegion(base, size); + } + } + } + + uint64_t AllocatePage() { + if (front_ == nullptr) { + panic("No available memory regions."); + } + + if (front_->num_pages == 0) { + panic("Bad state, empty memory block."); + } + + uint64_t page = front_->base; + front_->base += 0x1000; + front_->num_pages--; + if (front_->num_pages == 0) { + MemBlock* temp = front_; + front_ = front_->next; + delete temp; + } + return page; + } + void FreePage(uint64_t page) { AddMemoryRegion(page, 0x1000); } + + private: + void AddMemoryRegion(uint64_t base, uint64_t size) { + MemBlock* block = new MemBlock{ + .next = front_, + .base = base, + .num_pages = size >> 12, + }; + front_ = block; + } + struct MemBlock { + MemBlock* next = nullptr; + uint64_t base = 0; + uint64_t num_pages = 0; + }; + + MemBlock* front_ = nullptr; +}; + +static PhysicalMemoryManager* gPmm = nullptr; + }; // namespace void InitBootstrapPageAllocation() { @@ -36,11 +99,18 @@ void InitBootstrapPageAllocation() { } } +void InitPhysicalMemoryManager() { gPmm = new PhysicalMemoryManager(); } + uint64_t AllocatePage() { + if (gPmm != nullptr) { + return gPmm->AllocatePage(); + } if (!gBootstrapEnabled) { panic("No Bootstrap Memory Manager"); } + dbgln("[PMM] Boostrap Alloc!"); + uint64_t page = gBootstrap.next_page; if (page == gBootstrap.max_page) { panic("Bootstrap Memory Manager OOM"); diff --git a/zion/zion.cpp b/zion/zion.cpp index 080dde9..4313af0 100644 --- a/zion/zion.cpp +++ b/zion/zion.cpp @@ -14,7 +14,8 @@ extern "C" void zion() { phys_mem::InitBootstrapPageAllocation(); KernelHeap heap(0xFFFFFFFF'40000000, 0xFFFFFFFF'80000000); - heap.Allocate(1); + phys_mem::InitPhysicalMemoryManager(); + heap.Allocate(0x2000); dbgln("Sleeping!"); while (1)