Add a KernelMemoryManager namespace to wrap PMM + VMM
This commit is contained in:
parent
0fbc68ca88
commit
bd0a24097f
@ -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 :=
|
||||
|
14
kernel/include/memory/KernelMemoryManager.h
Normal file
14
kernel/include/memory/KernelMemoryManager.h
Normal 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);
|
||||
}
|
@ -35,4 +35,4 @@ class RangeAllocator
|
||||
uint64_t start_index = 0;
|
||||
};
|
||||
|
||||
extern RangeAllocator physical_allocator;
|
||||
extern RangeAllocator kernelPMM;
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
|
58
kernel/src/memory/KernelMemoryManager.cpp
Normal file
58
kernel/src/memory/KernelMemoryManager.cpp
Normal 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);
|
||||
}
|
@ -6,7 +6,7 @@
|
||||
|
||||
extern BOOTBOOT bootboot;
|
||||
|
||||
RangeAllocator physical_allocator;
|
||||
RangeAllocator kernelPMM;
|
||||
|
||||
void RangeAllocator::init_from_mmap()
|
||||
{
|
||||
|
@ -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;
|
||||
|
@ -52,13 +52,13 @@ 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;
|
||||
preserve_format = false;
|
||||
current_char = format[format_index];
|
||||
switch (current_char)
|
||||
{
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user