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
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
NASMFLAGS := -felf64
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;
};
extern RangeAllocator physical_allocator;
extern RangeAllocator kernelPMM;

View File

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

View File

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

View File

@ -13,6 +13,11 @@ extern "C" void common_handler(SavedContext* context)
context->rsp, context->error_code, context->cr2);
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); }
return;
}

View File

@ -13,6 +13,7 @@
#include "io/Serial.h"
#include "log/Log.h"
#include "memory/KernelHeap.h"
#include "memory/KernelMemoryManager.h"
#include "memory/Memory.h"
#include "memory/RangeAllocator.h"
#include "panic/hang.h"
@ -74,27 +75,6 @@ extern "C" void _start()
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});
ACPI::SDTHeader* rootSDT = ACPI::GetRSDTOrXSDT();
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;
RangeAllocator physical_allocator;
RangeAllocator kernelPMM;
void RangeAllocator::init_from_mmap()
{

View File

@ -1,4 +1,5 @@
#include "memory/VMM.h"
#include "log/Log.h"
#include "memory/RangeAllocator.h"
#include "std/string.h"
@ -59,6 +60,47 @@ namespace Paging
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)
{
virtualAddress >>= 12;
@ -76,7 +118,7 @@ namespace Paging
PageTable* PDP;
if (!PDE.Present)
{
PDP = (PageTable*)physical_allocator.request_page();
PDP = (PageTable*)kernelPMM.request_page();
memset(PDP, 0, 0x1000);
PDE.Address = (uint64_t)PDP >> 12;
PDE.Present = true;
@ -89,8 +131,8 @@ namespace Paging
PageTable* PD;
if (!PDE.Present)
{
PD = (PageTable*)physical_allocator.request_page();
memset(PDP, 0, 0x1000);
PD = (PageTable*)kernelPMM.request_page();
memset(PD, 0, 0x1000);
PDE.Address = (uint64_t)PD >> 12;
PDE.Present = true;
PDE.ReadWrite = true;
@ -102,8 +144,8 @@ namespace Paging
PageTable* PT;
if (!PDE.Present)
{
PT = (PageTable*)physical_allocator.request_page();
memset(PDP, 0, 0x1000);
PT = (PageTable*)kernelPMM.request_page();
memset(PT, 0, 0x1000);
PDE.Address = (uint64_t)PT >> 12;
PDE.Present = 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
{
format_index++;
continue;
}
else
{
if (!preserve_format) format_index++;
else
preserve_format = false;
current_char = format[format_index];
switch (current_char)

View File

@ -5,4 +5,4 @@ source $(dirname $0)/env.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