]> git.proxmox.com Git - mirror_edk2.git/commitdiff
MdeModulePkg/DxeIplPeim: Support GHCB pages when creating page tables
authorTom Lendacky <thomas.lendacky@amd.com>
Wed, 12 Aug 2020 20:21:35 +0000 (15:21 -0500)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Sun, 16 Aug 2020 16:45:42 +0000 (16:45 +0000)
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2198

GHCB pages must be mapped as shared pages, so modify the process of
creating identity mapped pagetable entries so that GHCB entries are
created without the encryption bit set. The GHCB range consists of
two pages per CPU, the first being the GHCB and the second being a
per-CPU variable page. Only the GHCB page is mapped as shared.

Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Hao A Wu <hao.a.wu@intel.com>
Cc: Dandan Bi <dandan.bi@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Acked-by: Hao A Wu <hao.a.wu@intel.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
Regression-tested-by: Laszlo Ersek <lersek@redhat.com>
MdeModulePkg/Core/DxeIplPeim/DxeIpl.inf
MdeModulePkg/Core/DxeIplPeim/Ia32/DxeLoadFunc.c
MdeModulePkg/Core/DxeIplPeim/X64/DxeLoadFunc.c
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c
MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h

index 3f17028546609378c1cf8066247b652fe34ec4fa..19b8a4c8aefa8616601ce210ef03c7654a25cbc3 100644 (file)
   gEfiMdeModulePkgTokenSpaceGuid.PcdHeapGuardPropertyMask               ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard                       ## CONSUMES\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdUse5LevelPageTable                  ## SOMETIMES_CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbBase                            ## CONSUMES\r
+  gEfiMdeModulePkgTokenSpaceGuid.PcdGhcbSize                            ## CONSUMES\r
 \r
 [Pcd.IA32,Pcd.X64,Pcd.ARM,Pcd.AARCH64]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack               ## SOMETIMES_CONSUMES\r
index 6e8ca824d469e9db51405fc673c41d539e750436..284b34818ca7fa37d5e50b7545ae32999439b8c3 100644 (file)
@@ -123,7 +123,7 @@ Create4GPageTablesIa32Pae (
         //\r
         // Need to split this 2M page that covers stack range.\r
         //\r
-        Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);\r
+        Split2MPageTo4K (PhysicalAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, 0, 0);\r
       } else {\r
         //\r
         // Fill in the Page Directory entries\r
@@ -282,7 +282,7 @@ HandOffToDxeCore (
     //\r
     // Create page table and save PageMapLevel4 to CR3\r
     //\r
-    PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE);\r
+    PageTables = CreateIdentityMappingPageTables (BaseOfStack, STACK_SIZE, 0, 0);\r
 \r
     //\r
     // End of PEI phase signal\r
index f465eb1d8ac4237f1702ee8de4df0fae2d0e1b23..156a477d8467e226ade828b5d008803e31eebac4 100644 (file)
@@ -35,6 +35,8 @@ HandOffToDxeCore (
   UINT32                          Index;\r
   EFI_VECTOR_HANDOFF_INFO         *VectorInfo;\r
   EFI_PEI_VECTOR_HANDOFF_INFO_PPI *VectorHandoffInfoPpi;\r
+  VOID                            *GhcbBase;\r
+  UINTN                           GhcbSize;\r
 \r
   //\r
   // Clear page 0 and mark it as allocated if NULL pointer detection is enabled.\r
@@ -81,12 +83,19 @@ HandOffToDxeCore (
   TopOfStack = (VOID *) ((UINTN) BaseOfStack + EFI_SIZE_TO_PAGES (STACK_SIZE) * EFI_PAGE_SIZE - CPU_STACK_ALIGNMENT);\r
   TopOfStack = ALIGN_POINTER (TopOfStack, CPU_STACK_ALIGNMENT);\r
 \r
+  //\r
+  // Get the address and size of the GHCB pages\r
+  //\r
+  GhcbBase = (VOID *) PcdGet64 (PcdGhcbBase);\r
+  GhcbSize = PcdGet64 (PcdGhcbSize);\r
+\r
   PageTables = 0;\r
   if (FeaturePcdGet (PcdDxeIplBuildPageTables)) {\r
     //\r
     // Create page table and save PageMapLevel4 to CR3\r
     //\r
-    PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE);\r
+    PageTables = CreateIdentityMappingPageTables ((EFI_PHYSICAL_ADDRESS) (UINTN) BaseOfStack, STACK_SIZE,\r
+                                                  (EFI_PHYSICAL_ADDRESS) (UINTN) GhcbBase, GhcbSize);\r
   } else {\r
     //\r
     // Set NX for stack feature also require PcdDxeIplBuildPageTables be TRUE\r
index 516cf908bc886e8c34ab549694cb9beea1896d16..6831946c54d375c6b3d97684a5ae3041a1fac731 100644 (file)
@@ -181,6 +181,8 @@ EnableExecuteDisableBit (
   @param Size         Size of the given physical memory.\r
   @param StackBase    Base address of stack.\r
   @param StackSize    Size of stack.\r
+  @param GhcbBase     Base address of GHCB pages.\r
+  @param GhcbSize     Size of GHCB area.\r
 \r
   @retval TRUE      Page table should be split.\r
   @retval FALSE     Page table should not be split.\r
@@ -190,7 +192,9 @@ ToSplitPageTable (
   IN EFI_PHYSICAL_ADDRESS               Address,\r
   IN UINTN                              Size,\r
   IN EFI_PHYSICAL_ADDRESS               StackBase,\r
-  IN UINTN                              StackSize\r
+  IN UINTN                              StackSize,\r
+  IN EFI_PHYSICAL_ADDRESS               GhcbBase,\r
+  IN UINTN                              GhcbSize\r
   )\r
 {\r
   if (IsNullDetectionEnabled () && Address == 0) {\r
@@ -209,6 +213,12 @@ ToSplitPageTable (
     }\r
   }\r
 \r
+  if (GhcbBase != 0) {\r
+    if ((Address < GhcbBase + GhcbSize) && ((Address + Size) > GhcbBase)) {\r
+      return TRUE;\r
+    }\r
+  }\r
+\r
   return FALSE;\r
 }\r
 /**\r
@@ -322,6 +332,8 @@ AllocatePageTableMemory (
   @param[in, out] PageEntry2M           Pointer to 2M page entry.\r
   @param[in]      StackBase             Stack base address.\r
   @param[in]      StackSize             Stack size.\r
+  @param[in]      GhcbBase              GHCB page area base address.\r
+  @param[in]      GhcbSize              GHCB page area size.\r
 \r
 **/\r
 VOID\r
@@ -329,7 +341,9 @@ Split2MPageTo4K (
   IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,\r
   IN OUT UINT64                         *PageEntry2M,\r
   IN EFI_PHYSICAL_ADDRESS               StackBase,\r
-  IN UINTN                              StackSize\r
+  IN UINTN                              StackSize,\r
+  IN EFI_PHYSICAL_ADDRESS               GhcbBase,\r
+  IN UINTN                              GhcbSize\r
   )\r
 {\r
   EFI_PHYSICAL_ADDRESS                  PhysicalAddress4K;\r
@@ -355,7 +369,20 @@ Split2MPageTo4K (
     //\r
     // Fill in the Page Table entries\r
     //\r
-    PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask;\r
+    PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K;\r
+\r
+    //\r
+    // The GHCB range consists of two pages per CPU, the GHCB and a\r
+    // per-CPU variable page. The GHCB page needs to be mapped as an\r
+    // unencrypted page while the per-CPU variable page needs to be\r
+    // mapped encrypted. These pages alternate in assignment.\r
+    //\r
+    if ((GhcbBase == 0)\r
+        || (PhysicalAddress4K < GhcbBase)\r
+        || (PhysicalAddress4K >= GhcbBase + GhcbSize)\r
+        || (((PhysicalAddress4K - GhcbBase) & SIZE_4KB) != 0)) {\r
+      PageTableEntry->Uint64 |= AddressEncMask;\r
+    }\r
     PageTableEntry->Bits.ReadWrite = 1;\r
 \r
     if ((IsNullDetectionEnabled () && PhysicalAddress4K == 0) ||\r
@@ -383,6 +410,8 @@ Split2MPageTo4K (
   @param[in, out] PageEntry1G           Pointer to 1G page entry.\r
   @param[in]      StackBase             Stack base address.\r
   @param[in]      StackSize             Stack size.\r
+  @param[in]      GhcbBase              GHCB page area base address.\r
+  @param[in]      GhcbSize              GHCB page area size.\r
 \r
 **/\r
 VOID\r
@@ -390,7 +419,9 @@ Split1GPageTo2M (
   IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,\r
   IN OUT UINT64                         *PageEntry1G,\r
   IN EFI_PHYSICAL_ADDRESS               StackBase,\r
-  IN UINTN                              StackSize\r
+  IN UINTN                              StackSize,\r
+  IN EFI_PHYSICAL_ADDRESS               GhcbBase,\r
+  IN UINTN                              GhcbSize\r
   )\r
 {\r
   EFI_PHYSICAL_ADDRESS                  PhysicalAddress2M;\r
@@ -413,11 +444,11 @@ Split1GPageTo2M (
 \r
   PhysicalAddress2M = PhysicalAddress;\r
   for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) {\r
-    if (ToSplitPageTable (PhysicalAddress2M, SIZE_2MB, StackBase, StackSize)) {\r
+    if (ToSplitPageTable (PhysicalAddress2M, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) {\r
       //\r
       // Need to split this 2M page that covers NULL or stack range.\r
       //\r
-      Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);\r
+      Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize);\r
     } else {\r
       //\r
       // Fill in the Page Directory entries\r
@@ -616,6 +647,8 @@ EnablePageTableProtection (
 \r
   @param[in] StackBase  Stack base address.\r
   @param[in] StackSize  Stack size.\r
+  @param[in] GhcbBase   GHCB base address.\r
+  @param[in] GhcbSize   GHCB size.\r
 \r
   @return The address of 4 level page map.\r
 \r
@@ -623,7 +656,9 @@ EnablePageTableProtection (
 UINTN\r
 CreateIdentityMappingPageTables (\r
   IN EFI_PHYSICAL_ADDRESS   StackBase,\r
-  IN UINTN                  StackSize\r
+  IN UINTN                  StackSize,\r
+  IN EFI_PHYSICAL_ADDRESS   GhcbBase,\r
+  IN UINTN                  GhcbSize\r
   )\r
 {\r
   UINT32                                        RegEax;\r
@@ -809,8 +844,8 @@ CreateIdentityMappingPageTables (
         PageDirectory1GEntry = (VOID *) PageDirectoryPointerEntry;\r
 \r
         for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectory1GEntry++, PageAddress += SIZE_1GB) {\r
-          if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSize)) {\r
-            Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize);\r
+          if (ToSplitPageTable (PageAddress, SIZE_1GB, StackBase, StackSize, GhcbBase, GhcbSize)) {\r
+            Split1GPageTo2M (PageAddress, (UINT64 *) PageDirectory1GEntry, StackBase, StackSize, GhcbBase, GhcbSize);\r
           } else {\r
             //\r
             // Fill in the Page Directory entries\r
@@ -840,11 +875,11 @@ CreateIdentityMappingPageTables (
           PageDirectoryPointerEntry->Bits.Present = 1;\r
 \r
           for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PageAddress += SIZE_2MB) {\r
-            if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, StackSize)) {\r
+            if (ToSplitPageTable (PageAddress, SIZE_2MB, StackBase, StackSize, GhcbBase, GhcbSize)) {\r
               //\r
               // Need to split this 2M page that covers NULL or stack range.\r
               //\r
-              Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize);\r
+              Split2MPageTo4K (PageAddress, (UINT64 *) PageDirectoryEntry, StackBase, StackSize, GhcbBase, GhcbSize);\r
             } else {\r
               //\r
               // Fill in the Page Directory entries\r
index 2d0493f109e859ae17d11854a202c30d945d9d4d..6b7c38a441d654811224309bcc6ee76f8341b3f0 100644 (file)
@@ -201,6 +201,8 @@ EnableExecuteDisableBit (
   @param[in, out] PageEntry2M           Pointer to 2M page entry.\r
   @param[in]      StackBase             Stack base address.\r
   @param[in]      StackSize             Stack size.\r
+  @param[in]      GhcbBase              GHCB page area base address.\r
+  @param[in]      GhcbSize              GHCB page area size.\r
 \r
 **/\r
 VOID\r
@@ -208,7 +210,9 @@ Split2MPageTo4K (
   IN EFI_PHYSICAL_ADDRESS               PhysicalAddress,\r
   IN OUT UINT64                         *PageEntry2M,\r
   IN EFI_PHYSICAL_ADDRESS               StackBase,\r
-  IN UINTN                              StackSize\r
+  IN UINTN                              StackSize,\r
+  IN EFI_PHYSICAL_ADDRESS               GhcbBase,\r
+  IN UINTN                              GhcbSize\r
   );\r
 \r
 /**\r
@@ -217,6 +221,8 @@ Split2MPageTo4K (
 \r
   @param[in] StackBase  Stack base address.\r
   @param[in] StackSize  Stack size.\r
+  @param[in] GhcbBase   GHCB page area base address.\r
+  @param[in] GhcbSize   GHCB page area size.\r
 \r
   @return The address of 4 level page map.\r
 \r
@@ -224,7 +230,9 @@ Split2MPageTo4K (
 UINTN\r
 CreateIdentityMappingPageTables (\r
   IN EFI_PHYSICAL_ADDRESS   StackBase,\r
-  IN UINTN                  StackSize\r
+  IN UINTN                  StackSize,\r
+  IN EFI_PHYSICAL_ADDRESS   GhcbBase,\r
+  IN UINTN                  GhcbkSize\r
   );\r
 \r
 \r