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>
diff --git a/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c b/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c
index cf9c03a..6009232 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c
+++ b/UefiPayloadPkg/UefiPayloadEntry/Ia32/DxeLoadFunc.c
@@ -177,7 +177,7 @@
   // Protect the page table by marking the memory used for page table to be

   // read-only.

   //

-  EnablePageTableProtection ((UINTN)PageMap, FALSE);

+  EnablePageTableProtection ((UINTN)PageMap, 3);

 

   return (UINTN)PageMap;

 }

diff --git a/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c b/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c
index 1899404..bfe1ba4 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c
+++ b/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.c
@@ -481,14 +481,14 @@
 

   @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] Level4Paging     Level 4 paging flag.

+  @param[in] LevelOfPaging     Level of paging.

 

 **/

 VOID

 SetPageTablePoolReadOnly (

   IN  UINTN                 PageTableBase,

   IN  EFI_PHYSICAL_ADDRESS  Address,

-  IN  BOOLEAN               Level4Paging

+  IN  UINT8                 LevelOfPaging

   )

 {

   UINTN                 Index;

@@ -498,9 +498,9 @@
   UINT64                *PageTable;

   UINT64                *NewPageTable;

   UINT64                PageAttr;

-  UINT64                LevelSize[5];

-  UINT64                LevelMask[5];

-  UINTN                 LevelShift[5];

+  UINT64                LevelSize[6];

+  UINT64                LevelMask[6];

+  UINTN                 LevelShift[6];

   UINTN                 Level;

   UINT64                PoolUnitSize;

 

@@ -517,23 +517,26 @@
   LevelShift[2] = PAGING_L2_ADDRESS_SHIFT;

   LevelShift[3] = PAGING_L3_ADDRESS_SHIFT;

   LevelShift[4] = PAGING_L4_ADDRESS_SHIFT;

+  LevelShift[5] = PAGING_L5_ADDRESS_SHIFT;

 

   LevelMask[1] = PAGING_4K_ADDRESS_MASK_64;

   LevelMask[2] = PAGING_2M_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[2] = SIZE_2MB;

   LevelSize[3] = SIZE_1GB;

   LevelSize[4] = SIZE_512GB;

+  LevelSize[5] = SIZE_256TB;

 

   AddressEncMask = PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) &

                    PAGING_1G_ADDRESS_MASK_64;

   PageTable    = (UINT64 *)(UINTN)PageTableBase;

   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 &= PAGING_PAE_INDEX_MASK;

 

@@ -603,13 +606,13 @@
   Prevent the memory pages used for page table from been overwritten.

 

   @param[in] PageTableBase    Base address of page table (CR3).

-  @param[in] Level4Paging     Level 4 paging flag.

+  @param[in] LevelOfPaging     Level of paging.

 

 **/

 VOID

 EnablePageTableProtection (

-  IN  UINTN    PageTableBase,

-  IN  BOOLEAN  Level4Paging

+  IN  UINTN  PageTableBase,

+  IN  UINT8  LevelOfPaging

   )

 {

   PAGE_TABLE_POOL       *HeadPool;

@@ -638,7 +641,7 @@
     // protection to them one by one.

     //

     while (PoolSize > 0) {

-      SetPageTablePoolReadOnly (PageTableBase, Address, Level4Paging);

+      SetPageTablePoolReadOnly (PageTableBase, Address, LevelOfPaging);

       Address  += PAGE_TABLE_POOL_UNIT_SIZE;

       PoolSize -= PAGE_TABLE_POOL_UNIT_SIZE;

     }

@@ -691,7 +694,7 @@
   UINTN                           TotalPagesNum;

   UINTN                           BigPageAddress;

   VOID                            *Hob;

-  BOOLEAN                         Enable5LevelPaging;

+  UINT8                           LevelOfPaging;

   BOOLEAN                         Page1GSupport;

   PAGE_TABLE_1G_ENTRY             *PageDirectory1GEntry;

   UINT64                          AddressEncMask;

@@ -740,10 +743,10 @@
   // below logic inherits the 5-level paging setting from bootloader in IA-32e mode

   // and uses 4-level paging in legacy protected mode.

   //

-  Cr4.UintN          = AsmReadCr4 ();

-  Enable5LevelPaging = (BOOLEAN)(Cr4.Bits.LA57 == 1);

+  Cr4.UintN     = AsmReadCr4 ();

+  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

@@ -751,7 +754,7 @@
   //  due to either unsupported by HW, or disabled by PCD.

   //

   ASSERT (PhysicalAddressBits <= 52);

-  if (!Enable5LevelPaging && (PhysicalAddressBits > 48)) {

+  if ((LevelOfPaging != 5) && (PhysicalAddressBits > 48)) {

     PhysicalAddressBits = 48;

   }

 

@@ -786,7 +789,7 @@
   //

   // Substract the one page occupied by PML5 entries if 5-Level Paging is disabled.

   //

-  if (!Enable5LevelPaging) {

+  if (LevelOfPaging != 5) {

     TotalPagesNum--;

   }

 

@@ -806,7 +809,7 @@
   // By architecture only one PageMapLevel4 exists - so lets allocate storage for it.

   //

   PageMap = (VOID *)BigPageAddress;

-  if (Enable5LevelPaging) {

+  if (LevelOfPaging == 5) {

     //

     // By architecture only one PageMapLevel5 exists - so lets allocate storage for it.

     //

@@ -828,7 +831,7 @@
     PageMapLevel4Entry = (VOID *)BigPageAddress;

     BigPageAddress    += SIZE_4KB;

 

-    if (Enable5LevelPaging) {

+    if (LevelOfPaging == 5) {

       //

       // Make a PML5 Entry

       //

@@ -922,7 +925,7 @@
     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.

     //

@@ -933,7 +936,7 @@
   // Protect the page table by marking the memory used for page table to be

   // read-only.

   //

-  EnablePageTableProtection ((UINTN)PageMap, TRUE);

+  EnablePageTableProtection ((UINTN)PageMap, LevelOfPaging);

 

   //

   // Set IA32_EFER.NXE if necessary.

diff --git a/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h b/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h
index 616ebe4..e035284 100644
--- a/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h
+++ b/UefiPayloadPkg/UefiPayloadEntry/X64/VirtualMemory.h
@@ -149,14 +149,17 @@
 

 #define PAGING_PAE_INDEX_MASK  0x1FF

 

-#define PAGING_4K_ADDRESS_MASK_64  0x000FFFFFFFFFF000ull

-#define PAGING_2M_ADDRESS_MASK_64  0x000FFFFFFFE00000ull

-#define PAGING_1G_ADDRESS_MASK_64  0x000FFFFFC0000000ull

+#define PAGING_4K_ADDRESS_MASK_64    0x000FFFFFFFFFF000ull

+#define PAGING_2M_ADDRESS_MASK_64    0x000FFFFFFFE00000ull

+#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_L2_ADDRESS_SHIFT  21

 #define PAGING_L3_ADDRESS_SHIFT  30

 #define PAGING_L4_ADDRESS_SHIFT  39

+#define PAGING_L5_ADDRESS_SHIFT  48

 

 #define PAGING_PML4E_NUMBER  4

 

@@ -293,13 +296,13 @@
   Prevent the memory pages used for page table from been overwritten.

 

   @param[in] PageTableBase    Base address of page table (CR3).

-  @param[in] Level4Paging     Level 4 paging flag.

+  @param[in] LevelOfPaging     Level of paging.

 

 **/

 VOID

 EnablePageTableProtection (

-  IN  UINTN    PageTableBase,

-  IN  BOOLEAN  Level4Paging

+  IN  UINTN  PageTableBase,

+  IN  UINT8  LevelOfPaging

   );

 

 /**