From d63addfb64a46763b7af10bef334ef60d2a10991 Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Fri, 18 Apr 2025 14:20:17 +0200 Subject: [PATCH] fix(vmm): Fix crash on CR3 loading --- kernel/src/Main.cpp | 12 ++--------- kernel/src/Memory/Paging.cpp | 39 +++++++++++++++++++++++------------- kernel/src/Memory/Paging.hpp | 3 ++- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/kernel/src/Main.cpp b/kernel/src/Main.cpp index 4e2bc51..483c3fd 100644 --- a/kernel/src/Main.cpp +++ b/kernel/src/Main.cpp @@ -102,19 +102,11 @@ extern "C" void kmain() { #if defined (__x86_64__) Hal::IDTInitialize(); -#endif - - // auto kaddr_request_response = kernel_address_request.response; Memory::VMM::Paging g_paging{}; + g_paging.Init((uint64_t)&KernelStartSymbol, ((uint64_t)&KernelEndSymbol - (uint64_t)&KernelStartSymbol), memmap_request.response); - g_paging.Init((uint64_t)&KernelStartSymbol, ((uint64_t)&KernelEndSymbol - (uint64_t)&KernelStartSymbol)); - // g_paging.Map(0xcfc0000, 0xcfc0000); - - // kout << "0x" << base::hex << Memory::VMM::GetCR3(); - - kout << "0x" << base::hex << 0xdeadbeef << "\n"; - kout << "0x" << base::hex << Memory::HHDM(0xdeadbeef) << "\n"; +#endif Hal::Halt(); } diff --git a/kernel/src/Memory/Paging.cpp b/kernel/src/Memory/Paging.cpp index 04ff2c2..1a080ea 100644 --- a/kernel/src/Memory/Paging.cpp +++ b/kernel/src/Memory/Paging.cpp @@ -14,32 +14,43 @@ namespace Memory::VMM { PML4 = (PageTable*)SubHHDM((PageTable*)Memory::g_pfa->AllocateZeroed()); } - void Paging::Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize) { + void Paging::Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, limine_memmap_response* memMap) { // Map kernel Kt::KernelLogStream(Kt::DEBUG, "VMM") << "Paging::Init called with kernelBaseVirt as 0x" << base::hex << kernelBaseVirt << " and kernelSize as " << base::dec << kernelSize; for (std::uint64_t pageAddr = kernelBaseVirt; pageAddr < (kernelBaseVirt + kernelSize); pageAddr += 0x1000) { - Kt::KernelLogStream(Kt::DEBUG, "VMM") << "Mapping 0x" << base::hex << GetPhysKernelAddress(pageAddr) << " to 0x" << pageAddr; Map(GetPhysKernelAddress(pageAddr), pageAddr); } - // TODO map HHDM - // TODO map ACPI tables + // Map HHDM memMap entries - LoadCR3((PageTable*)&PML4); + for (size_t i = 0; i < memMap->entry_count; i++) { + auto entry = memMap->entries[i]; + + for (size_t pageAddr = entry->base; pageAddr < (entry->base + entry->length); pageAddr += 0x1000) { + Map(pageAddr, HHDM(pageAddr)); + } + } + + LoadCR3(PML4); + Kt::KernelLogStream(Kt::OK, "VMM") << "Switched CR3"; } PageTable* Paging::HandleLevel(VirtualAddress virtualAddress, PageTable* table, const size_t level) { PageTableEntry* entry = (PageTableEntry*)Memory::HHDM(&table->entries[virtualAddress.GetIndex(level)]); - entry->Present = true; - entry->Writable = true; - - uint64_t downLevelAddr = Memory::SubHHDM((uint64_t)Memory::g_pfa->AllocateZeroed()); - - entry->Address = downLevelAddr >> 12; - - return (PageTable*)downLevelAddr; + if (!entry->Present) { + entry->Present = true; + entry->Writable = true; + + uint64_t downLevelAddr = Memory::SubHHDM((uint64_t)Memory::g_pfa->AllocateZeroed()); + + entry->Address = downLevelAddr >> 12; + + return (PageTable*)downLevelAddr; + } else { + return (PageTable*)(entry->Address << 12); + } } void Paging::Map(std::uint64_t physicalAddress, std::uint64_t virtualAddress) { @@ -58,7 +69,7 @@ namespace Memory::VMM { pageEntry->Present = true; pageEntry->Writable = true; - pageEntry->Address = virtualAddress >> 12; + pageEntry->Address = physicalAddress >> 12; } std::uint64_t Paging::GetPhysAddr(std::uint64_t pml4, std::uint64_t virtualAddress, bool use40BitL1) { diff --git a/kernel/src/Memory/Paging.hpp b/kernel/src/Memory/Paging.hpp index 23580cd..3547cd1 100644 --- a/kernel/src/Memory/Paging.hpp +++ b/kernel/src/Memory/Paging.hpp @@ -1,4 +1,5 @@ #pragma once +#include #include #include @@ -87,7 +88,7 @@ namespace Memory::VMM { PageTable* HandleLevel(VirtualAddress virtualAddress, PageTable* table, size_t level); public: Paging(); - void Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize); + void Init(std::uint64_t kernelBaseVirt, std::uint64_t kernelSize, limine_memmap_response* memMap); void Map(std::uint64_t physicalAddress, std::uint64_t virtualAddress); static std::uint64_t GetPhysAddr(std::uint64_t PML4, std::uint64_t virtualAddress, bool use40BitL1 = false); std::uint64_t GetPhysAddr(std::uint64_t virtualAddress);