diff --git a/zion/CMakeLists.txt b/zion/CMakeLists.txt index 272016f..2f858cb 100644 --- a/zion/CMakeLists.txt +++ b/zion/CMakeLists.txt @@ -7,6 +7,7 @@ add_executable(zion interrupt/interrupt_enter.s memory/kernel_heap.cpp memory/paging_util.cpp + memory/physical_memory.cpp zion.cpp) target_include_directories(zion diff --git a/zion/memory/paging_util.cpp b/zion/memory/paging_util.cpp index 1ccc9f7..727a276 100644 --- a/zion/memory/paging_util.cpp +++ b/zion/memory/paging_util.cpp @@ -2,6 +2,7 @@ #include "boot/boot_info.h" #include "debug/debug.h" +#include "memory/physical_memory.h" #define PRESENT_BIT 0x1 #define READ_WRITE_BIT 0x2 @@ -39,6 +40,31 @@ uint64_t ShiftForEntryIndexing(uint64_t addr, uint64_t offset) { addr <<= 3; return addr; } + +void MapPage(uint64_t virt, uint64_t phys) { + if (PageLoaded(virt)) { + panic("Allocating Over Existing Page: %m", virt); + } + + if (!PageDirectoryPointerLoaded(virt)) { + uint64_t page = phys_mem::AllocatePage(); + *Pml4Entry(virt) = page | PRESENT_BIT | READ_WRITE_BIT; + ZeroOutPage(PageDirectoryPointerEntry(virt)); + } + if (!PageDirectoryLoaded(virt)) { + uint64_t page = phys_mem::AllocatePage(); + *PageDirectoryPointerEntry(virt) = page | PRESENT_BIT | READ_WRITE_BIT; + ZeroOutPage(PageDirectoryEntry(virt)); + } + if (!PageTableLoaded(virt)) { + uint64_t page = phys_mem::AllocatePage(); + *PageDirectoryEntry(virt) = page | PRESENT_BIT | READ_WRITE_BIT; + ZeroOutPage(PageTableEntry(virt)); + } + + *PageTableEntry(virt) = PageAlign(phys) | PRESENT_BIT | READ_WRITE_BIT; + ZeroOutPage(reinterpret_cast(virt)); +} } // namespace void InitPaging() { @@ -55,10 +81,10 @@ void InitializePml4(uint64_t pml4_physical_addr) { pml4_virtual[0x1FE] = recursive_entry; } -void AllocatePageDirectoryPointer(uint64_t addr); -void AllocatePageDirectory(uint64_t addr); -void AllocatePageTable(uint64_t addr); -void AllocatePage(uint64_t addr) { panic("Page Allocation Not Implemented."); } +void AllocatePage(uint64_t addr) { + uint64_t physical_page = phys_mem::AllocatePage(); + MapPage(addr, physical_page); +} void EnsureResident(uint64_t addr, uint64_t size) { uint64_t max = addr + size; diff --git a/zion/memory/physical_memory.cpp b/zion/memory/physical_memory.cpp new file mode 100644 index 0000000..2e89b7f --- /dev/null +++ b/zion/memory/physical_memory.cpp @@ -0,0 +1,53 @@ +#include "memory/physical_memory.h" + +#include "boot/boot_info.h" +#include "debug/debug.h" + +namespace phys_mem { +namespace { + +struct BootstrapMemory { + uint64_t init_page = 0; + uint64_t next_page = 0; + uint64_t max_page = 0; +}; + +static BootstrapMemory gBootstrap; +static bool gBootstrapEnabled = false; + +}; // namespace + +void InitBootstrapPageAllocation() { + 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]; + // We may want to chose a high address space to not limit + // the number of buffers we can allocate later but + // if we limit the number of pages this should be fine. + // Currently set to the minimum of 3 for one kernel heap allocation: + // PageDirectory + PageTable + Page + if (entry.type == 0 && entry.length >= 0x3000) { + gBootstrap.init_page = entry.base; + gBootstrap.next_page = entry.base; + gBootstrap.max_page = entry.base + 0x3000; + gBootstrapEnabled = true; + return; + } + } +} + +uint64_t AllocatePage() { + if (!gBootstrapEnabled) { + panic("No Bootstrap Memory Manager"); + } + + uint64_t page = gBootstrap.next_page; + if (page == gBootstrap.max_page) { + panic("Bootstrap Memory Manager OOM"); + } + gBootstrap.next_page += 0x1000; + + return page; +} + +} // namespace phys_mem diff --git a/zion/memory/physical_memory.h b/zion/memory/physical_memory.h new file mode 100644 index 0000000..40bca04 --- /dev/null +++ b/zion/memory/physical_memory.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +namespace phys_mem { + +// Called before creating a kernel heap object +// that allows dynamic allocation. The real +// PhysicalMemoryManager requires some allocations +// to initialize so we need this first. +void InitBootstrapPageAllocation(); + +void InitPhysicalMemoryManager(); + +uint64_t AllocatePage(); +void FreePage(uint64_t page); + +} // namespace phys_mem diff --git a/zion/zion.cpp b/zion/zion.cpp index 003eb87..080dde9 100644 --- a/zion/zion.cpp +++ b/zion/zion.cpp @@ -1,21 +1,22 @@ #include -#include "boot/boot_info.h" -#include "boot/limine.h" #include "common/gdt.h" #include "debug/debug.h" #include "interrupt/interrupt.h" #include "memory/kernel_heap.h" #include "memory/paging_util.h" +#include "memory/physical_memory.h" extern "C" void zion() { InitGdt(); InitIdt(); InitPaging(); + phys_mem::InitBootstrapPageAllocation(); KernelHeap heap(0xFFFFFFFF'40000000, 0xFFFFFFFF'80000000); heap.Allocate(1); + dbgln("Sleeping!"); while (1) ; }