]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/PiSmmCpuDxeSmm: Reflect page table depth with page table address
authorSheng Wei <w.sheng@intel.com>
Mon, 9 Nov 2020 05:16:57 +0000 (13:16 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 18 Nov 2020 04:52:26 +0000 (04:52 +0000)
When trying to get page table base, if mInternalCr3 is zero, it will use
 the page table from CR3, and reflect the page table depth by CR4 LA57 bit.
If mInternalCr3 is non zero, it will use the page table from mInternalCr3
 and reflect the page table depth of mInternalCr3 at same time.
In the case of X64, we use m5LevelPagingNeeded to reflect the depth of
 the page table. And in the case of IA32, it will not the page table depth
 information.

This patch is a bug fix when enable CET feature with 5 level paging.
The SMM page tables are allocated / initialized in PiCpuSmmEntry().
When CET is enabled, PiCpuSmmEntry() must further modify the attribute of
 shadow stack pages. This page table is not set to CR3 in PiCpuSmmEntry().
 So the page table base address is set to mInternalCr3 for modifty the
 page table attribute. It could not use CR4 LA57 bit to reflect the
 page table depth for mInternalCr3.
So we create a architecture-specific implementation GetPageTable() with
 2 output parameters. One parameter is used to output the page table
 address. Another parameter is used to reflect if it is 5 level paging
 or not.

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

Signed-off-by: Sheng Wei <w.sheng@intel.com>
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Rahul Kumar <rahul1.kumar@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
UefiCpuPkg/PiSmmCpuDxeSmm/SmmCpuMemoryManagement.c
UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c

index 2483f2ea849d44c0f915a9e5c6b1a19c38f9f61e..9c8e2d15ac46a9d2bf3e153d959273682db53b34 100644 (file)
@@ -28,6 +28,26 @@ EnableCet (
   VOID\r
   );\r
 \r
+/**\r
+  Get page table base address and the depth of the page table.\r
+\r
+  @param[out] Base        Page table base address.\r
+  @param[out] FiveLevels  TRUE means 5 level paging. FALSE means 4 level paging.\r
+**/\r
+VOID\r
+GetPageTable (\r
+  OUT UINTN   *Base,\r
+  OUT BOOLEAN *FiveLevels OPTIONAL\r
+  )\r
+{\r
+  *Base = ((mInternalCr3 == 0) ?\r
+            (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64) :\r
+            mInternalCr3);\r
+  if (FiveLevels != NULL) {\r
+    *FiveLevels = FALSE;\r
+  }\r
+}\r
+\r
 /**\r
   Create PageTable for SMM use.\r
 \r
@@ -226,6 +246,7 @@ SetPageTableAttributes (
   UINT64                *L1PageTable;\r
   UINT64                *L2PageTable;\r
   UINT64                *L3PageTable;\r
+  UINTN                 PageTableBase;\r
   BOOLEAN               IsSplitted;\r
   BOOLEAN               PageTableSplitted;\r
   BOOLEAN               CetEnabled;\r
@@ -268,9 +289,10 @@ SetPageTableAttributes (
     DEBUG ((DEBUG_INFO, "Start...\n"));\r
     PageTableSplitted = FALSE;\r
 \r
-    L3PageTable = (UINT64 *)GetPageTableBase ();\r
+    GetPageTable (&PageTableBase, NULL);\r
+    L3PageTable = (UINT64 *)PageTableBase;\r
 \r
-    SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L3PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
+    SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
     PageTableSplitted = (PageTableSplitted || IsSplitted);\r
 \r
     for (Index3 = 0; Index3 < 4; Index3++) {\r
index 7fb3a2d9e4b759b32dcc98d221cae7ca1c34a998..b8aa9e1769d317b3e2b0abcd116bf7507d0fc762 100644 (file)
@@ -263,6 +263,7 @@ extern UINTN                  mMaxNumberOfCpus;
 extern UINTN                  mNumberOfCpus;\r
 extern EFI_SMM_CPU_PROTOCOL   mSmmCpu;\r
 extern EFI_MM_MP_PROTOCOL     mSmmMp;\r
+extern UINTN                  mInternalCr3;\r
 \r
 ///\r
 /// The mode of the CPU at the time an SMI occurs\r
@@ -942,13 +943,15 @@ SetPageTableAttributes (
   );\r
 \r
 /**\r
-  Return page table base.\r
+  Get page table base address and the depth of the page table.\r
 \r
-  @return page table base.\r
+  @param[out] Base        Page table base address.\r
+  @param[out] FiveLevels  TRUE means 5 level paging. FALSE means 4 level paging.\r
 **/\r
-UINTN\r
-GetPageTableBase (\r
-  VOID\r
+VOID\r
+GetPageTable (\r
+  OUT UINTN   *Base,\r
+  OUT BOOLEAN *FiveLevels OPTIONAL\r
   );\r
 \r
 /**\r
index d67f036aea69a3bbc04410408c4ca518390249e6..766eb1246aea6128ca3c81022154e8dd99346726 100644 (file)
@@ -49,22 +49,6 @@ SetPageTableBase (
   mInternalCr3 = Cr3;\r
 }\r
 \r
-/**\r
-  Return page table base.\r
-\r
-  @return page table base.\r
-**/\r
-UINTN\r
-GetPageTableBase (\r
-  VOID\r
-  )\r
-{\r
-  if (mInternalCr3 != 0) {\r
-    return mInternalCr3;\r
-  }\r
-  return (AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64);\r
-}\r
-\r
 /**\r
   Return length according to page attributes.\r
 \r
@@ -131,21 +115,20 @@ GetPageTableEntry (
   UINT64                *L3PageTable;\r
   UINT64                *L4PageTable;\r
   UINT64                *L5PageTable;\r
-  IA32_CR4              Cr4;\r
+  UINTN                 PageTableBase;\r
   BOOLEAN               Enable5LevelPaging;\r
 \r
+  GetPageTable (&PageTableBase, &Enable5LevelPaging);\r
+\r
   Index5 = ((UINTN)RShiftU64 (Address, 48)) & PAGING_PAE_INDEX_MASK;\r
   Index4 = ((UINTN)RShiftU64 (Address, 39)) & PAGING_PAE_INDEX_MASK;\r
   Index3 = ((UINTN)Address >> 30) & PAGING_PAE_INDEX_MASK;\r
   Index2 = ((UINTN)Address >> 21) & PAGING_PAE_INDEX_MASK;\r
   Index1 = ((UINTN)Address >> 12) & PAGING_PAE_INDEX_MASK;\r
 \r
-  Cr4.UintN = AsmReadCr4 ();\r
-  Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);\r
-\r
   if (sizeof(UINTN) == sizeof(UINT64)) {\r
     if (Enable5LevelPaging) {\r
-      L5PageTable = (UINT64 *)GetPageTableBase ();\r
+      L5PageTable = (UINT64 *)PageTableBase;\r
       if (L5PageTable[Index5] == 0) {\r
         *PageAttribute = PageNone;\r
         return NULL;\r
@@ -153,7 +136,7 @@ GetPageTableEntry (
 \r
       L4PageTable = (UINT64 *)(UINTN)(L5PageTable[Index5] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);\r
     } else {\r
-      L4PageTable = (UINT64 *)GetPageTableBase ();\r
+      L4PageTable = (UINT64 *)PageTableBase;\r
     }\r
     if (L4PageTable[Index4] == 0) {\r
       *PageAttribute = PageNone;\r
@@ -162,7 +145,7 @@ GetPageTableEntry (
 \r
     L3PageTable = (UINT64 *)(UINTN)(L4PageTable[Index4] & ~mAddressEncMask & PAGING_4K_ADDRESS_MASK_64);\r
   } else {\r
-    L3PageTable = (UINT64 *)GetPageTableBase ();\r
+    L3PageTable = (UINT64 *)PageTableBase;\r
   }\r
   if (L3PageTable[Index3] == 0) {\r
     *PageAttribute = PageNone;\r
index 810985df20aee6e5ac04b008241a378f5ebc2867..cdc1fcefc524e9e6538c7dfc78f05a5c4fe9355f 100644 (file)
@@ -104,6 +104,35 @@ Is5LevelPagingNeeded (
   }\r
 }\r
 \r
+/**\r
+  Get page table base address and the depth of the page table.\r
+\r
+  @param[out] Base        Page table base address.\r
+  @param[out] FiveLevels  TRUE means 5 level paging. FALSE means 4 level paging.\r
+**/\r
+VOID\r
+GetPageTable (\r
+  OUT UINTN   *Base,\r
+  OUT BOOLEAN *FiveLevels OPTIONAL\r
+  )\r
+{\r
+  IA32_CR4 Cr4;\r
+\r
+  if (mInternalCr3 == 0) {\r
+    *Base = AsmReadCr3 () & PAGING_4K_ADDRESS_MASK_64;\r
+    if (FiveLevels != NULL) {\r
+      Cr4.UintN = AsmReadCr4 ();\r
+      *FiveLevels = (BOOLEAN)(Cr4.Bits.LA57 == 1);\r
+    }\r
+    return;\r
+  }\r
+\r
+  *Base = mInternalCr3;\r
+  if (FiveLevels != NULL) {\r
+    *FiveLevels = m5LevelPagingNeeded;\r
+  }\r
+}\r
+\r
 /**\r
   Set sub-entries number in entry.\r
 \r
@@ -1111,15 +1140,12 @@ SetPageTableAttributes (
   UINT64                *L3PageTable;\r
   UINT64                *L4PageTable;\r
   UINT64                *L5PageTable;\r
+  UINTN                 PageTableBase;\r
   BOOLEAN               IsSplitted;\r
   BOOLEAN               PageTableSplitted;\r
   BOOLEAN               CetEnabled;\r
-  IA32_CR4              Cr4;\r
   BOOLEAN               Enable5LevelPaging;\r
 \r
-  Cr4.UintN = AsmReadCr4 ();\r
-  Enable5LevelPaging = (BOOLEAN) (Cr4.Bits.LA57 == 1);\r
-\r
   //\r
   // Don't mark page table memory as read-only if\r
   //  - no restriction on access to non-SMRAM memory; or\r
@@ -1163,9 +1189,12 @@ SetPageTableAttributes (
     DEBUG ((DEBUG_INFO, "Start...\n"));\r
     PageTableSplitted = FALSE;\r
     L5PageTable = NULL;\r
+\r
+    GetPageTable (&PageTableBase, &Enable5LevelPaging);\r
+\r
     if (Enable5LevelPaging) {\r
-      L5PageTable = (UINT64 *)GetPageTableBase ();\r
-      SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L5PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
+      L5PageTable = (UINT64 *)PageTableBase;\r
+      SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)PageTableBase, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
       PageTableSplitted = (PageTableSplitted || IsSplitted);\r
     }\r
 \r
@@ -1176,7 +1205,7 @@ SetPageTableAttributes (
           continue;\r
         }\r
       } else {\r
-        L4PageTable = (UINT64 *)GetPageTableBase ();\r
+        L4PageTable = (UINT64 *)PageTableBase;\r
       }\r
       SmmSetMemoryAttributesEx ((EFI_PHYSICAL_ADDRESS)(UINTN)L4PageTable, SIZE_4KB, EFI_MEMORY_RO, &IsSplitted);\r
       PageTableSplitted = (PageTableSplitted || IsSplitted);\r