fix(vmm): make MMU bring-up and kernel mappings reliable
This commit is contained in:
+30
-8
@@ -4,6 +4,7 @@
|
||||
#include <Arch/CPU.h>
|
||||
#include <OS/Panic.h>
|
||||
#include "../Common/bootinfo.h"
|
||||
#include "OS/Log.h"
|
||||
|
||||
static const UInt64 kPTEAddressMask = 0x0000FFFFFFFFF000ULL;
|
||||
static inline Address GetPTEAddress(UInt64 entry) { return entry & kPTEAddressMask; }
|
||||
@@ -18,6 +19,9 @@ static Boolean isInitialized = false;
|
||||
Address* gVMKernelL0Table = nullptr;
|
||||
Address gVMKernelL0Physical = 0;
|
||||
|
||||
extern char _kernelStart[];
|
||||
extern char _kernelEnd[];
|
||||
|
||||
static Address* GetVirtualTable(Address phys) {
|
||||
if (isInitialized) return (Address*)VMPhysToHHDM(phys);
|
||||
return (Address*)phys;
|
||||
@@ -92,7 +96,7 @@ Address* VMMMapPage(Address* l0Table, Address phys, Address virt, UInt64 flags)
|
||||
if (!l3Virt) return nullptr;
|
||||
|
||||
l3Virt[l3Index] = phys | flags | kPTEPage | kPTEAccessFlag | kPTEValid;
|
||||
CPUInvalidateTLB(virt);
|
||||
if (isInitialized) CPUInvalidateTLB(virt);
|
||||
return l3Virt;
|
||||
}
|
||||
|
||||
@@ -138,7 +142,9 @@ void VMMInitialize(VMBootMemoryMap* bootMap, Bootinfo* info) {
|
||||
gVMKernelL0Physical = (Address)PMMAllocatePage();
|
||||
gVMKernelL0Table = (Address*)gVMKernelL0Physical;
|
||||
if (!gVMKernelL0Physical) OSPanic("Failed to allocate kernel L0 table");
|
||||
MemorySet(gVMKernelL0Table, 0, kVMPageSize);
|
||||
|
||||
OSLog("Mapping RAM.. Can take a while\n");
|
||||
Size totalRAM = bootMap->totalRAM.size;
|
||||
Size ramEnd = bootMap->totalRAM.base + totalRAM;
|
||||
for (Address phys = bootMap->totalRAM.base; phys < ramEnd; phys += kVMPageSize) {
|
||||
@@ -148,14 +154,25 @@ void VMMInitialize(VMBootMemoryMap* bootMap, Bootinfo* info) {
|
||||
kPTENormalMem | kPTEAccessRW | kPTEPrivNX | kPTEUserNX
|
||||
);
|
||||
}
|
||||
OSLog("RAM mapped\n");
|
||||
|
||||
Size pmmBitmapSize = (bootMap->totalRAM.size / kVMPageSize) / 8;
|
||||
Size kernelSize = ((Address)_kernelEnd - (Address)_kernelStart) + pmmBitmapSize;
|
||||
kernelSize = (kernelSize + kVMPageSize - 1) & ~(kVMPageSize - 1);
|
||||
|
||||
Address kernelPhysStart = 0x40100000; // TODO: hardcode is awful
|
||||
|
||||
Address kernelPhysStart = (Address)info->kernelInfo.kernelAddress;
|
||||
Size kernelSize = info->kernelInfo.kernelSize;
|
||||
for (Address offset = 0; offset < kernelSize; offset += kVMPageSize) {
|
||||
Address phys = kernelPhysStart + offset;
|
||||
Address virt = kVMKernelVMA + offset;
|
||||
Address virt = (Address)_kernelStart + offset;
|
||||
VMMMapPage(gVMKernelL0Table, phys, virt, kPTENormalMem | kPTEAccessRW);
|
||||
}
|
||||
OSLog("Kernel mapped to HHDM\n");
|
||||
|
||||
for (Address offset = 0; offset < kernelSize; offset += kVMPageSize) {
|
||||
VMMMapPage(gVMKernelL0Table, kernelPhysStart + offset, kernelPhysStart + offset, kPTENormalMem | kPTEAccessRW);
|
||||
}
|
||||
OSLog("Kernel Identity mapped\n");
|
||||
|
||||
Address fbPhys = (Address)info->framebuffer.base;
|
||||
Size fbSize = info->framebuffer.baseSize;
|
||||
@@ -166,18 +183,23 @@ void VMMInitialize(VMBootMemoryMap* bootMap, Bootinfo* info) {
|
||||
kPTEDeviceMem | kPTEAccessRW | kPTEUserNX | kPTEPrivNX
|
||||
);
|
||||
}
|
||||
OSLog("Framebuffer mapped\n");
|
||||
|
||||
Address UARTPhys = bootMap->UART.base;
|
||||
if (!UARTPhys) UARTPhys = 0x09000000;
|
||||
|
||||
VMMMapPage(
|
||||
gVMKernelL0Table, UARTPhys, VMPhysToHHDM(UARTPhys),
|
||||
kPTEDeviceMem | kPTEAccessRW | kPTEUserNX | kPTEPrivNX
|
||||
);
|
||||
VMMMapPage(
|
||||
gVMKernelL0Table, UARTPhys, UARTPhys,
|
||||
kPTEDeviceMem | kPTEAccessRW | kPTEUserNX | kPTEPrivNX
|
||||
);
|
||||
OSLog("UART mapped\n");
|
||||
|
||||
for (Address offset = 0; offset < kernelSize; offset += kVMPageSize) {
|
||||
VMMMapPage(gVMKernelL0Table, kernelPhysStart + offset, kernelPhysStart + offset, kPTENormalMem | kPTEAccessRW);
|
||||
}
|
||||
|
||||
info->framebuffer.base = (BIUInt32*)kVMFbVirtBase;;
|
||||
OSLog("Enabling MMU...\n");
|
||||
CPUEnableMMU(gVMKernelL0Physical);
|
||||
isInitialized = true;
|
||||
}
|
||||
Reference in New Issue
Block a user