]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/X64/SmmFuncsArch.c
UefiCpuPkg/PiSmmCpu: Fixed #double fault on #page fault.
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / X64 / SmmFuncsArch.c
index 62338b79bd1f32d3c99886920d1c62130ec84b86..9d26e44a9acd58c1f279694d0afa3eac2498a544 100644 (file)
@@ -14,6 +14,30 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 \r
 #include "PiSmmCpuDxeSmm.h"\r
 \r
+EFI_PHYSICAL_ADDRESS                mGdtBuffer;\r
+UINTN                               mGdtBufferSize;\r
+\r
+/**\r
+  Initialize IDT for SMM Stack Guard.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+InitializeIDTSmmStackGuard (\r
+  VOID\r
+  )\r
+{\r
+  IA32_IDT_GATE_DESCRIPTOR  *IdtGate;\r
+\r
+  //\r
+  // If SMM Stack Guard feature is enabled, set the IST field of\r
+  // the interrupt gate for Page Fault Exception to be 1\r
+  //\r
+  IdtGate = (IA32_IDT_GATE_DESCRIPTOR *)gcSmiIdtr.Base;\r
+  IdtGate += EXCEPT_IA32_PAGE_FAULT;\r
+  IdtGate->Bits.Reserved_0 = 1;\r
+}\r
+\r
 /**\r
   Initialize Gdt for all processors.\r
   \r
@@ -41,8 +65,10 @@ InitGdt (
   // on each SMI entry.\r
   //\r
   GdtTssTableSize = (gcSmiGdtr.Limit + 1 + TSS_SIZE + 7) & ~7; // 8 bytes aligned\r
-  GdtTssTables = (UINT8*)AllocatePages (EFI_SIZE_TO_PAGES (GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus));\r
+  mGdtBufferSize = GdtTssTableSize * gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
+  GdtTssTables = (UINT8*)AllocateCodePages (EFI_SIZE_TO_PAGES (mGdtBufferSize));\r
   ASSERT (GdtTssTables != NULL);\r
+  mGdtBuffer = (UINTN)GdtTssTables;\r
   GdtTableStepSize = GdtTssTableSize;\r
 \r
   for (Index = 0; Index < gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus; Index++) {\r
@@ -69,6 +95,54 @@ InitGdt (
   return GdtTssTables;\r
 }\r
 \r
+/**\r
+  This function sets GDT/IDT buffer to be RO and XP.\r
+**/\r
+VOID\r
+PatchGdtIdtMap (\r
+  VOID\r
+  )\r
+{\r
+  EFI_PHYSICAL_ADDRESS       BaseAddress;\r
+  UINTN                      Size;\r
+\r
+  //\r
+  // GDT\r
+  //\r
+  DEBUG ((DEBUG_INFO, "PatchGdtIdtMap - GDT:\n"));\r
+\r
+  BaseAddress = mGdtBuffer;\r
+  Size = ALIGN_VALUE(mGdtBufferSize, SIZE_4KB);\r
+  SmmSetMemoryAttributes (\r
+    BaseAddress,\r
+    Size,\r
+    EFI_MEMORY_RO\r
+    );\r
+  SmmSetMemoryAttributes (\r
+    BaseAddress,\r
+    Size,\r
+    EFI_MEMORY_XP\r
+    );\r
+\r
+  //\r
+  // IDT\r
+  //\r
+  DEBUG ((DEBUG_INFO, "PatchGdtIdtMap - IDT:\n"));\r
+\r
+  BaseAddress = gcSmiIdtr.Base;\r
+  Size = ALIGN_VALUE(gcSmiIdtr.Limit + 1, SIZE_4KB);\r
+  SmmSetMemoryAttributes (\r
+    BaseAddress,\r
+    Size,\r
+    EFI_MEMORY_RO\r
+    );\r
+  SmmSetMemoryAttributes (\r
+    BaseAddress,\r
+    Size,\r
+    EFI_MEMORY_XP\r
+    );\r
+}\r
+\r
 /**\r
   Get Protected mode code segment from current GDT table.\r
 \r
@@ -103,22 +177,24 @@ GetProtectedModeCS (
 /**\r
   Transfer AP to safe hlt-loop after it finished restore CPU features on S3 patch.\r
 \r
-  @param[in] ApHltLoopCode    The 32-bit address of the safe hlt-loop function.\r
-  @param[in] TopOfStack       A pointer to the new stack to use for the ApHltLoopCode.\r
+  @param[in] ApHltLoopCode          The address of the safe hlt-loop function.\r
+  @param[in] TopOfStack             A pointer to the new stack to use for the ApHltLoopCode.\r
+  @param[in] NumberToFinishAddress  Address of Semaphore of APs finish count.\r
 \r
 **/\r
 VOID\r
 TransferApToSafeState (\r
-  IN UINT32             ApHltLoopCode,\r
-  IN UINT32             TopOfStack\r
+  IN UINTN  ApHltLoopCode,\r
+  IN UINTN  TopOfStack,\r
+  IN UINTN  NumberToFinishAddress\r
   )\r
 {\r
   AsmDisablePaging64 (\r
     GetProtectedModeCS (),\r
-    (UINT32) (UINTN) ApHltLoopCode,\r
+    (UINT32)ApHltLoopCode,\r
+    (UINT32)NumberToFinishAddress,\r
     0,\r
-    0,\r
-    TopOfStack\r
+    (UINT32)TopOfStack\r
     );\r
   //\r
   // It should never reach here\r
@@ -126,4 +202,3 @@ TransferApToSafeState (
   ASSERT (FALSE);\r
 }\r
 \r
-\r