Add a bootstrap physical memory manager.

This will allow the real physical memory manager to use allocations.
This commit is contained in:
Drew Galbraith 2023-05-18 11:00:05 -07:00
parent 747c2a4e17
commit 2d719d0443
5 changed files with 105 additions and 6 deletions

View File

@ -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

View File

@ -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<uint64_t*>(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;

View File

@ -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

View File

@ -0,0 +1,18 @@
#pragma once
#include <stdint.h>
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

View File

@ -1,21 +1,22 @@
#include <stdint.h>
#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)
;
}