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
|
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 :=
|
||||||
|
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;
|
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 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;
|
||||||
|
@ -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();
|
||||||
}
|
}
|
@ -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;
|
||||||
}
|
}
|
@ -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;
|
||||||
|
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;
|
extern BOOTBOOT bootboot;
|
||||||
|
|
||||||
RangeAllocator physical_allocator;
|
RangeAllocator kernelPMM;
|
||||||
|
|
||||||
void RangeAllocator::init_from_mmap()
|
void RangeAllocator::init_from_mmap()
|
||||||
{
|
{
|
||||||
|
@ -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;
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user