Add a KernelMemoryManager namespace to wrap PMM + VMM

This commit is contained in:
apio 2022-09-06 18:08:15 +02:00
parent 0fbc68ca88
commit bd0a24097f
12 changed files with 133 additions and 33 deletions

View File

@ -8,7 +8,7 @@ CXX := x86_64-elf-g++
AS := x86_64-elf-as AS := x86_64-elf-as
NASM := nasm NASM := nasm
CFLAGS := -Wall -Wextra -Werror -Os -ffreestanding -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std CFLAGS := -g -Wall -Wextra -Werror -Os -ffreestanding -mno-red-zone -mno-mmx -mno-sse -mno-sse2 -fshort-wchar -mcmodel=kernel -I$(MOON_DIR)/include -isystem $(MOON_DIR)/include/std
CXXFLAGS := -fno-rtti -fno-exceptions CXXFLAGS := -fno-rtti -fno-exceptions
NASMFLAGS := -felf64 NASMFLAGS := -felf64
ASFLAGS := ASFLAGS :=

View File

@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
namespace KernelMemoryManager
{
void* get_mapping(void* physicalAddress);
void release_mapping(void* mapping);
void* get_page();
void* get_pages(uint64_t count);
void release_page(void* page);
void release_pages(void* pages, uint64_t count);
}

View File

@ -35,4 +35,4 @@ class RangeAllocator
uint64_t start_index = 0; uint64_t start_index = 0;
}; };
extern RangeAllocator physical_allocator; extern RangeAllocator kernelPMM;

View File

@ -11,6 +11,7 @@ namespace Paging
void map(uint64_t virtualAddress, uint64_t physicalAddress); void map(uint64_t virtualAddress, uint64_t physicalAddress);
void unmap(uint64_t virtualAddress); void unmap(uint64_t virtualAddress);
uint64_t getPhysical(uint64_t virtualAddress);
private: private:
PageTable* PML4; PageTable* PML4;

View File

@ -32,6 +32,6 @@ void Init::early_init()
ASSERT(Draw::try_initialize()); ASSERT(Draw::try_initialize());
// ASSERT(TextRenderer::try_initialize()); // ASSERT(TextRenderer::try_initialize());
physical_allocator.init_from_mmap(); kernelPMM.init_from_mmap();
kernelVMM.init(); kernelVMM.init();
} }

View File

@ -13,6 +13,11 @@ extern "C" void common_handler(SavedContext* context)
context->rsp, context->error_code, context->cr2); context->rsp, context->error_code, context->cr2);
while (1) halt(); while (1) halt();
} }
if (context->number == 14)
{
printf("Page fault at 0x%zx\n");
hang();
}
if (context->number >= 0x20 && context->number < 0x30) { IRQ::interrupt_handler(context); } if (context->number >= 0x20 && context->number < 0x30) { IRQ::interrupt_handler(context); }
return; return;
} }

View File

@ -13,6 +13,7 @@
#include "io/Serial.h" #include "io/Serial.h"
#include "log/Log.h" #include "log/Log.h"
#include "memory/KernelHeap.h" #include "memory/KernelHeap.h"
#include "memory/KernelMemoryManager.h"
#include "memory/Memory.h" #include "memory/Memory.h"
#include "memory/RangeAllocator.h" #include "memory/RangeAllocator.h"
#include "panic/hang.h" #include "panic/hang.h"
@ -74,27 +75,6 @@ extern "C" void _start()
kinfoln("Interrupts enabled"); kinfoln("Interrupts enabled");
printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024,
physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024,
physical_allocator.get_reserved() / 1024);
void* address = physical_allocator.request_page();
printf("Allocated page at address 0x%zx\n", address);
void* address2 = physical_allocator.request_page();
printf("Allocated page at address 0x%zx\n", address2);
printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024,
physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024,
physical_allocator.get_reserved() / 1024);
physical_allocator.free_page(address);
printf("Freed page\n");
printf("%d KB of system memory\n%d KB free\n%d KB used\n%d KB reserved\n", Memory::get_system() / 1024,
physical_allocator.get_free() / 1024, physical_allocator.get_used() / 1024,
physical_allocator.get_reserved() / 1024);
Debug::DebugStatus::the()->StartBootStage(Color{0x33, 0x33, 0x00, 0xFF}); Debug::DebugStatus::the()->StartBootStage(Color{0x33, 0x33, 0x00, 0xFF});
ACPI::SDTHeader* rootSDT = ACPI::GetRSDTOrXSDT(); ACPI::SDTHeader* rootSDT = ACPI::GetRSDTOrXSDT();
bool isXSDT = false; bool isXSDT = false;

View File

@ -0,0 +1,58 @@
#include "memory/KernelMemoryManager.h"
#include "assert.h"
#include "memory/KernelHeap.h"
#include "memory/RangeAllocator.h"
#include "memory/VMM.h"
void* KernelMemoryManager::get_mapping(void* physicalAddress)
{
uint64_t virtualAddress = KernelHeap::request_virtual_page();
kernelVMM.map(virtualAddress, (uint64_t)physicalAddress);
return (void*)virtualAddress;
}
void KernelMemoryManager::release_mapping(void* mapping)
{
kernelVMM.unmap((uint64_t)mapping);
}
void* KernelMemoryManager::get_page()
{
void* physicalAddress = kernelPMM.request_page();
uint64_t virtualAddress = KernelHeap::request_virtual_page();
kernelVMM.map(virtualAddress, (uint64_t)physicalAddress);
return (void*)virtualAddress;
}
void KernelMemoryManager::release_page(void* page)
{
uint64_t physicalAddress = kernelVMM.getPhysical((uint64_t)page);
ASSERT(physicalAddress != UINT64_MAX);
kernelVMM.unmap((uint64_t)page);
kernelPMM.free_page((void*)physicalAddress);
KernelHeap::free_virtual_page((uint64_t)page);
}
void* KernelMemoryManager::get_pages(uint64_t count)
{
uint64_t virtualAddress = KernelHeap::request_virtual_pages(count);
for (uint64_t i = 0; i < count; i++)
{
void* physicalAddress = kernelPMM.request_page();
kernelVMM.map(virtualAddress + (i * 4096), (uint64_t)physicalAddress);
}
return (void*)virtualAddress;
}
void KernelMemoryManager::release_pages(void* pages, uint64_t count)
{
for (uint64_t i = 0; i < count; i++)
{
void* page = (void*)((uint64_t)pages + (i * 4096));
uint64_t physicalAddress = kernelVMM.getPhysical((uint64_t)page);
ASSERT(physicalAddress != UINT64_MAX);
kernelVMM.unmap((uint64_t)page);
kernelPMM.free_page((void*)physicalAddress);
}
KernelHeap::free_virtual_pages((uint64_t)pages, count);
}

View File

@ -6,7 +6,7 @@
extern BOOTBOOT bootboot; extern BOOTBOOT bootboot;
RangeAllocator physical_allocator; RangeAllocator kernelPMM;
void RangeAllocator::init_from_mmap() void RangeAllocator::init_from_mmap()
{ {

View File

@ -1,4 +1,5 @@
#include "memory/VMM.h" #include "memory/VMM.h"
#include "log/Log.h"
#include "memory/RangeAllocator.h" #include "memory/RangeAllocator.h"
#include "std/string.h" #include "std/string.h"
@ -59,6 +60,47 @@ namespace Paging
PT->entries[P_i] = PDE; PT->entries[P_i] = PDE;
} }
uint64_t VirtualMemoryManager::getPhysical(uint64_t virtualAddress)
{
virtualAddress >>= 12;
uint64_t P_i = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t PT_i = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t PD_i = virtualAddress & 0x1ff;
virtualAddress >>= 9;
uint64_t PDP_i = virtualAddress & 0x1ff;
PageDirectoryEntry PDE;
PDE = PML4->entries[PDP_i];
PageTable* PDP;
if (!PDE.Present)
{
return UINT64_MAX; // Not mapped
}
else { PDP = (PageTable*)((uint64_t)PDE.Address << 12); }
PDE = PDP->entries[PD_i];
PageTable* PD;
if (!PDE.Present)
{
return UINT64_MAX; // Not mapped
}
else { PD = (PageTable*)((uint64_t)PDE.Address << 12); }
PDE = PD->entries[PT_i];
PageTable* PT;
if (!PDE.Present)
{
return UINT64_MAX; // Not mapped
}
else { PT = (PageTable*)((uint64_t)PDE.Address << 12); }
PDE = PT->entries[P_i];
return PDE.Address;
}
void VirtualMemoryManager::map(uint64_t virtualAddress, uint64_t physicalAddress) void VirtualMemoryManager::map(uint64_t virtualAddress, uint64_t physicalAddress)
{ {
virtualAddress >>= 12; virtualAddress >>= 12;
@ -76,7 +118,7 @@ namespace Paging
PageTable* PDP; PageTable* PDP;
if (!PDE.Present) if (!PDE.Present)
{ {
PDP = (PageTable*)physical_allocator.request_page(); PDP = (PageTable*)kernelPMM.request_page();
memset(PDP, 0, 0x1000); memset(PDP, 0, 0x1000);
PDE.Address = (uint64_t)PDP >> 12; PDE.Address = (uint64_t)PDP >> 12;
PDE.Present = true; PDE.Present = true;
@ -89,8 +131,8 @@ namespace Paging
PageTable* PD; PageTable* PD;
if (!PDE.Present) if (!PDE.Present)
{ {
PD = (PageTable*)physical_allocator.request_page(); PD = (PageTable*)kernelPMM.request_page();
memset(PDP, 0, 0x1000); memset(PD, 0, 0x1000);
PDE.Address = (uint64_t)PD >> 12; PDE.Address = (uint64_t)PD >> 12;
PDE.Present = true; PDE.Present = true;
PDE.ReadWrite = true; PDE.ReadWrite = true;
@ -102,8 +144,8 @@ namespace Paging
PageTable* PT; PageTable* PT;
if (!PDE.Present) if (!PDE.Present)
{ {
PT = (PageTable*)physical_allocator.request_page(); PT = (PageTable*)kernelPMM.request_page();
memset(PDP, 0, 0x1000); memset(PT, 0, 0x1000);
PDE.Address = (uint64_t)PT >> 12; PDE.Address = (uint64_t)PT >> 12;
PDE.Present = true; PDE.Present = true;
PDE.ReadWrite = true; PDE.ReadWrite = true;

View File

@ -52,12 +52,12 @@ static int internal_printf(const char* format, PutString put_string_callback, ss
{ {
if (format_index + 1 == format_size) // end of format string if (format_index + 1 == format_size) // end of format string
{ {
format_index++;
continue; continue;
} }
else else
{ {
if (!preserve_format) format_index++; if (!preserve_format) format_index++;
else
preserve_format = false; preserve_format = false;
current_char = format[format_index]; current_char = format[format_index];
switch (current_char) switch (current_char)

View File

@ -5,4 +5,4 @@ source $(dirname $0)/env.sh
tools/build-iso.sh tools/build-iso.sh
qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s qemu-system-x86_64 -cdrom Luna.iso -smp 1 -m 256M -serial stdio -d int,cpu_reset -s -no-reboot