fix(VMM): use correct APTable encoding for table descriptors
fix(VMM): use correct APTable encoding for table descriptors fix(vmm): changed flags to match ARMv8
This commit is contained in:
+18
-9
@@ -4,19 +4,28 @@
|
|||||||
#include "../Common/bootinfo.h"
|
#include "../Common/bootinfo.h"
|
||||||
|
|
||||||
enum VMPTEFlags {
|
enum VMPTEFlags {
|
||||||
kPTEValid = (1ULL << 0), // 1 = Present (Will page fault if 0)
|
// Descriptor type (bits [1:0])
|
||||||
kPTETable = (1ULL << 1), // 1 = Valid for L0/L1/L2 Directory
|
kPTEValid = (1ULL << 0), // 1 = Valid (fault if 0)
|
||||||
kPTEPage = (1ULL << 1), // 1 = Valid for L3 Page (Same bit)
|
kPTETable = (1ULL << 1), // For L0/L1/L2: table descriptor (bits[1:0]=11)
|
||||||
|
kPTEPage = (1ULL << 1), // For L3: page descriptor (same bit, bits[1:0]=11)
|
||||||
|
|
||||||
kPTENormalMem = (0ULL << 2), // Cached, Normal RAM
|
// MAIR attribute index (bits [4:2])
|
||||||
kPTEDeviceMem = (1ULL << 2), // Uncached, MMIO Device
|
kPTENormalMem = (0ULL << 2), // AttrIndx 0 → MAIR[7:0] = 0xFF (Normal, WB Cacheable)
|
||||||
|
kPTEDeviceMem = (1ULL << 2), // AttrIndx 1 → MAIR[15:8] = 0x00 (Device-nGnRnE)
|
||||||
|
|
||||||
kPTEAccessRW = (0ULL << 6), // Read/Write
|
// Leaf entry AP[2:1] (bits [7:6]):
|
||||||
kPTEAccessRO = (1ULL << 6), // Read-Only
|
// AP[1] (bit 6): 0 = EL0 blocked, 1 = EL0 allowed
|
||||||
kPTEUser = (1ULL << 7), // 1 = EL0, 0 = EL1
|
// AP[2] (bit 7): 0 = Read/Write, 1 = Read-only
|
||||||
|
kPTEUser = (1ULL << 6), // AP[1]=1: allow EL0 access
|
||||||
|
kPTEAccessRW = (0ULL << 7), // AP[2]=0: writable for permitted levels
|
||||||
|
kPTEAccessRO = (1ULL << 7), // AP[2]=1: read-only for all levels
|
||||||
|
|
||||||
|
// Table descriptor APTable[1:0] (bits [62:61]):
|
||||||
|
// 00 = no restriction, 01 = block EL0, 10 = reserved, 11 = read-only for all
|
||||||
|
kPTETableNoEL0 = (1ULL << 61), // APTable[0]=1: prevent EL0 table walk
|
||||||
|
|
||||||
kPTEInnerShare = (3ULL << 8), // Inner Shareable (SMP safe)
|
kPTEInnerShare = (3ULL << 8), // Inner Shareable (SMP safe)
|
||||||
kPTEAccessFlag = (1ULL << 10), // CPU access tracking (MUST be 1 to avoid faults)
|
kPTEAccessFlag = (1ULL << 10), // Access Flag (MUST be 1 to avoid faults)
|
||||||
kPTEPrivNX = (1ULL << 53), // PXN: Privileged Execute Never
|
kPTEPrivNX = (1ULL << 53), // PXN: Privileged Execute Never
|
||||||
kPTEUserNX = (1ULL << 54) // UXN: Unprivileged Execute Never
|
kPTEUserNX = (1ULL << 54) // UXN: Unprivileged Execute Never
|
||||||
};
|
};
|
||||||
|
|||||||
+12
-2
@@ -38,7 +38,11 @@ static inline Address* GetOrAllocateTable(Address* parentTable, Size index, UInt
|
|||||||
return newTableVirt;
|
return newTableVirt;
|
||||||
}
|
}
|
||||||
|
|
||||||
parentTable[index] |= (flags & kPTEUser);
|
// if user access requested, clear APTable bit to allow EL0 table walk.
|
||||||
|
// otherwise leave APTable as-is (kernel-only tables keep kPTETableNoEL0).
|
||||||
|
if (flags & kPTEUser) {
|
||||||
|
parentTable[index] &= ~kPTETableNoEL0;
|
||||||
|
}
|
||||||
|
|
||||||
Address physAddress = GetPTEAddress(parentTable[index]);
|
Address physAddress = GetPTEAddress(parentTable[index]);
|
||||||
return GetVirtualTable(physAddress);
|
return GetVirtualTable(physAddress);
|
||||||
@@ -83,7 +87,13 @@ Address* VMMMapPage(Address* l0Table, Address phys, Address virt, UInt64 flags)
|
|||||||
Address* l0Virt = l0Table;
|
Address* l0Virt = l0Table;
|
||||||
if (isInitialized) l0Virt = (Address*)VMPhysToHHDM((Address)l0Table);
|
if (isInitialized) l0Virt = (Address*)VMPhysToHHDM((Address)l0Table);
|
||||||
|
|
||||||
UInt64 directoryFlags = kPTEValid | kPTETable | (flags & kPTEUser);
|
// build directory flags for table descriptors
|
||||||
|
// APTable=01 (kPTETableNoEL0) blocks EL0 entirely - used for kernel-only subtrees.
|
||||||
|
// APTable=00 allows EL0 access by leaf page permissions - used for user mappings.
|
||||||
|
UInt64 directoryFlags = kPTEValid | kPTETable;
|
||||||
|
if (!(flags & kPTEUser)) {
|
||||||
|
directoryFlags |= kPTETableNoEL0;
|
||||||
|
}
|
||||||
|
|
||||||
Address* l1Virt = GetOrAllocateTable(l0Virt, l0Index, flags, directoryFlags);
|
Address* l1Virt = GetOrAllocateTable(l0Virt, l0Index, flags, directoryFlags);
|
||||||
if (!l1Virt) return nullptr;
|
if (!l1Virt) return nullptr;
|
||||||
|
|||||||
Reference in New Issue
Block a user