UefiPayloadPkg/UefiPayloadEntry: Fix PT protection in 5 level paging

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=4873

Currently the function does not cover the 5 level paging case. it will
casued pagetable protection region set incorrectly. This patch do the
enhancemant and with the patch protection region has been set correctly.

Signed-off-by: Ning Feng <ning.feng@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
This commit is contained in:
Ning Feng 2024-11-12 03:59:38 -05:00 committed by mergify[bot]
parent c28721484d
commit 0f3867fa6e
3 changed files with 34 additions and 28 deletions

View File

@ -177,7 +177,7 @@ Create4GPageTablesIa32Pae (
// Protect the page table by marking the memory used for page table to be // Protect the page table by marking the memory used for page table to be
// read-only. // read-only.
// //
EnablePageTableProtection ((UINTN)PageMap, FALSE); EnablePageTableProtection ((UINTN)PageMap, 3);
return (UINTN)PageMap; return (UINTN)PageMap;
} }

View File

@ -481,14 +481,14 @@ Split1GPageTo2M (
@param[in] PageTableBase Base address of page table (CR3). @param[in] PageTableBase Base address of page table (CR3).
@param[in] Address Start address of a page to be set as read-only. @param[in] Address Start address of a page to be set as read-only.
@param[in] Level4Paging Level 4 paging flag. @param[in] LevelOfPaging Level of paging.
**/ **/
VOID VOID
SetPageTablePoolReadOnly ( SetPageTablePoolReadOnly (
IN UINTN PageTableBase, IN UINTN PageTableBase,
IN EFI_PHYSICAL_ADDRESS Address, IN EFI_PHYSICAL_ADDRESS Address,
IN BOOLEAN Level4Paging IN UINT8 LevelOfPaging
) )
{ {
UINTN Index; UINTN Index;
@ -498,9 +498,9 @@ SetPageTablePoolReadOnly (
UINT64 *PageTable; UINT64 *PageTable;
UINT64 *NewPageTable; UINT64 *NewPageTable;
UINT64 PageAttr; UINT64 PageAttr;
UINT64 LevelSize[5]; UINT64 LevelSize[6];
UINT64 LevelMask[5]; UINT64 LevelMask[6];
UINTN LevelShift[5]; UINTN LevelShift[6];
UINTN Level; UINTN Level;
UINT64 PoolUnitSize; UINT64 PoolUnitSize;
@ -517,23 +517,26 @@ SetPageTablePoolReadOnly (
LevelShift[2] = PAGING_L2_ADDRESS_SHIFT; LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;
LevelShift[3] = PAGING_L3_ADDRESS_SHIFT; LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;
LevelShift[4] = PAGING_L4_ADDRESS_SHIFT; LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;
LevelShift[5] = PAGING_L5_ADDRESS_SHIFT;
LevelMask[1] = PAGING_4K_ADDRESS_MASK_64; LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;
LevelMask[2] = PAGING_2M_ADDRESS_MASK_64; LevelMask[2] = PAGING_2M_ADDRESS_MASK_64;
LevelMask[3] = PAGING_1G_ADDRESS_MASK_64; LevelMask[3] = PAGING_1G_ADDRESS_MASK_64;
LevelMask[4] = PAGING_1G_ADDRESS_MASK_64; LevelMask[4] = PAGING_512G_ADDRESS_MASK_64;
LevelMask[5] = PAGING_256T_ADDRESS_MASK_64;
LevelSize[1] = SIZE_4KB; LevelSize[1] = SIZE_4KB;
LevelSize[2] = SIZE_2MB; LevelSize[2] = SIZE_2MB;
LevelSize[3] = SIZE_1GB; LevelSize[3] = SIZE_1GB;
LevelSize[4] = SIZE_512GB; LevelSize[4] = SIZE_512GB;
LevelSize[5] = SIZE_256TB;
AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) &
PAGING_1G_ADDRESS_MASK_64; PAGING_1G_ADDRESS_MASK_64;
PageTable = (UINT64 *)(UINTN)PageTableBase; PageTable = (UINT64 *)(UINTN)PageTableBase;
PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE; PoolUnitSize = PAGE_TABLE_POOL_UNIT_SIZE;
for (Level = (Level4Paging) ? 4 : 3; Level > 0; --Level) { for (Level = LevelOfPaging; Level > 0; --Level) {
Index = ((UINTN)RShiftU64 (Address, LevelShift[Level])); Index = ((UINTN)RShiftU64 (Address, LevelShift[Level]));
Index &= PAGING_PAE_INDEX_MASK; Index &= PAGING_PAE_INDEX_MASK;
@ -603,13 +606,13 @@ SetPageTablePoolReadOnly (
Prevent the memory pages used for page table from been overwritten. Prevent the memory pages used for page table from been overwritten.
@param[in] PageTableBase Base address of page table (CR3). @param[in] PageTableBase Base address of page table (CR3).
@param[in] Level4Paging Level 4 paging flag. @param[in] LevelOfPaging Level of paging.
**/ **/
VOID VOID
EnablePageTableProtection ( EnablePageTableProtection (
IN UINTN PageTableBase, IN UINTN PageTableBase,
IN BOOLEAN Level4Paging IN UINT8 LevelOfPaging
) )
{ {
PAGE_TABLE_POOL *HeadPool; PAGE_TABLE_POOL *HeadPool;
@ -638,7 +641,7 @@ EnablePageTableProtection (
// protection to them one by one. // protection to them one by one.
// //
while (PoolSize > 0) { while (PoolSize > 0) {
SetPageTablePoolReadOnly (PageTableBase, Address, Level4Paging); SetPageTablePoolReadOnly (PageTableBase, Address, LevelOfPaging);
Address += PAGE_TABLE_POOL_UNIT_SIZE; Address += PAGE_TABLE_POOL_UNIT_SIZE;
PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE; PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;
} }
@ -691,7 +694,7 @@ CreateIdentityMappingPageTables (
UINTN TotalPagesNum; UINTN TotalPagesNum;
UINTN BigPageAddress; UINTN BigPageAddress;
VOID *Hob; VOID *Hob;
BOOLEAN Enable5LevelPaging; UINT8 LevelOfPaging;
BOOLEAN Page1GSupport; BOOLEAN Page1GSupport;
PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry;
UINT64 AddressEncMask; UINT64 AddressEncMask;
@ -740,10 +743,10 @@ CreateIdentityMappingPageTables (
// below logic inherits the 5-level paging setting from bootloader in IA-32e mode // below logic inherits the 5-level paging setting from bootloader in IA-32e mode
// and uses 4-level paging in legacy protected mode. // and uses 4-level paging in legacy protected mode.
// //
Cr4.UintN = AsmReadCr4 (); Cr4.UintN = AsmReadCr4 ();
Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1); LevelOfPaging = (Cr4.Bits.LA57 == 1) ? 5 : 4;
DEBUG ((DEBUG_INFO, "PayloadEntry: AddressBits=%u 5LevelPaging=%u 1GPage=%u\n", PhysicalAddressBits, Enable5LevelPaging, Page1GSupport)); DEBUG ((DEBUG_INFO, "PayloadEntry: AddressBits=%u LevelOfPaging=%u 1GPage=%u\n", PhysicalAddressBits, LevelOfPaging, Page1GSupport));
// //
// IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses // IA-32e paging translates 48-bit linear addresses to 52-bit physical addresses
@ -751,7 +754,7 @@ CreateIdentityMappingPageTables (
// due to either unsupported by HW, or disabled by PCD. // due to either unsupported by HW, or disabled by PCD.
// //
ASSERT (PhysicalAddressBits <= 52); ASSERT (PhysicalAddressBits <= 52);
if (!Enable5LevelPaging && (PhysicalAddressBits > 48)) { if ((LevelOfPaging != 5) && (PhysicalAddressBits > 48)) {
PhysicalAddressBits = 48; PhysicalAddressBits = 48;
} }
@ -786,7 +789,7 @@ CreateIdentityMappingPageTables (
// //
// Substract the one page occupied by PML5 entries if 5-Level Paging is disabled. // Substract the one page occupied by PML5 entries if 5-Level Paging is disabled.
// //
if (!Enable5LevelPaging) { if (LevelOfPaging != 5) {
TotalPagesNum--; TotalPagesNum--;
} }
@ -806,7 +809,7 @@ CreateIdentityMappingPageTables (
// By architecture only one PageMapLevel4 exists - so lets allocate storage for it. // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.
// //
PageMap = (VOID *)BigPageAddress; PageMap = (VOID *)BigPageAddress;
if (Enable5LevelPaging) { if (LevelOfPaging == 5) {
// //
// By architecture only one PageMapLevel5 exists - so lets allocate storage for it. // By architecture only one PageMapLevel5 exists - so lets allocate storage for it.
// //
@ -828,7 +831,7 @@ CreateIdentityMappingPageTables (
PageMapLevel4Entry = (VOID *)BigPageAddress; PageMapLevel4Entry = (VOID *)BigPageAddress;
BigPageAddress += SIZE_4KB; BigPageAddress += SIZE_4KB;
if (Enable5LevelPaging) { if (LevelOfPaging == 5) {
// //
// Make a PML5 Entry // Make a PML5 Entry
// //
@ -922,7 +925,7 @@ CreateIdentityMappingPageTables (
ZeroMem (PageMapLevel4Entry, (512 - IndexOfPml4Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER)); ZeroMem (PageMapLevel4Entry, (512 - IndexOfPml4Entries) * sizeof (PAGE_MAP_AND_DIRECTORY_POINTER));
} }
if (Enable5LevelPaging) { if (LevelOfPaging == 5) {
// //
// For the PML5 entries we are not using fill in a null entry. // For the PML5 entries we are not using fill in a null entry.
// //
@ -933,7 +936,7 @@ CreateIdentityMappingPageTables (
// Protect the page table by marking the memory used for page table to be // Protect the page table by marking the memory used for page table to be
// read-only. // read-only.
// //
EnablePageTableProtection ((UINTN)PageMap, TRUE); EnablePageTableProtection ((UINTN)PageMap, LevelOfPaging);
// //
// Set IA32_EFER.NXE if necessary. // Set IA32_EFER.NXE if necessary.

View File

@ -149,14 +149,17 @@ typedef union {
#define PAGING_PAE_INDEX_MASK 0x1FF #define PAGING_PAE_INDEX_MASK 0x1FF
#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull #define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull
#define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull #define PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull
#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull #define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull
#define PAGING_512G_ADDRESS_MASK_64 0x000FF80000000000ull
#define PAGING_256T_ADDRESS_MASK_64 0x000F800000000000ull
#define PAGING_L1_ADDRESS_SHIFT 12 #define PAGING_L1_ADDRESS_SHIFT 12
#define PAGING_L2_ADDRESS_SHIFT 21 #define PAGING_L2_ADDRESS_SHIFT 21
#define PAGING_L3_ADDRESS_SHIFT 30 #define PAGING_L3_ADDRESS_SHIFT 30
#define PAGING_L4_ADDRESS_SHIFT 39 #define PAGING_L4_ADDRESS_SHIFT 39
#define PAGING_L5_ADDRESS_SHIFT 48
#define PAGING_PML4E_NUMBER 4 #define PAGING_PML4E_NUMBER 4
@ -293,13 +296,13 @@ IsNullDetectionEnabled (
Prevent the memory pages used for page table from been overwritten. Prevent the memory pages used for page table from been overwritten.
@param[in] PageTableBase Base address of page table (CR3). @param[in] PageTableBase Base address of page table (CR3).
@param[in] Level4Paging Level 4 paging flag. @param[in] LevelOfPaging Level of paging.
**/ **/
VOID VOID
EnablePageTableProtection ( EnablePageTableProtection (
IN UINTN PageTableBase, IN UINTN PageTableBase,
IN BOOLEAN Level4Paging IN UINT8 LevelOfPaging
); );
/** /**