]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiCpuPkg/PiSmmCpuDxeSmm: implement non-stop mode for SMM
authorJian J Wang <jian.j.wang@intel.com>
Mon, 20 Aug 2018 03:35:58 +0000 (11:35 +0800)
committerJian J Wang <jian.j.wang@intel.com>
Wed, 29 Aug 2018 23:22:30 +0000 (07:22 +0800)
Since SMM profile feature has already implemented non-stop mode if #PF
occurred, this patch just makes use of the existing implementation to
accommodate heap guard and NULL pointer detection feature.

Cc: Eric Dong <eric.dong@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Ruiyu Ni <ruiyu.ni@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jian J Wang <jian.j.wang@intel.com>
Reviewed-by: Eric Dong <eric.dong@intel.com>
Acked-by: Laszlo Ersek <lersek@redhat.com>
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c
UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/SmiException.nasm
UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h
UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfileInternal.h
UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c

index 9300a232e4a6658ba6720c618defbd5cff7f795b..a32b736089ab7eb74cf23df1dca40eef8ad4075c 100644 (file)
@@ -38,7 +38,9 @@ SmmInitPageTable (
 \r
   mPhysicalAddressBits = 32;\r
 \r
-  if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
+  if (FeaturePcdGet (PcdCpuSmmProfileEnable) ||\r
+      HEAP_GUARD_NONSTOP_MODE ||\r
+      NULL_DETECTION_NONSTOP_MODE) {\r
     //\r
     // Set own Page Fault entry instead of the default one, because SMM Profile\r
     // feature depends on IRET instruction to do Single Step\r
@@ -129,6 +131,11 @@ SmiPFHandler (
           DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);\r
         );\r
       }\r
+\r
+      if (HEAP_GUARD_NONSTOP_MODE) {\r
+        GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);\r
+        goto Exit;\r
+      }\r
     }\r
     CpuDeadLoop ();\r
   }\r
@@ -146,6 +153,26 @@ SmiPFHandler (
       );\r
       CpuDeadLoop ();\r
     }\r
+\r
+    //\r
+    // If NULL pointer was just accessed\r
+    //\r
+    if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0 &&\r
+        (PFAddress < EFI_PAGE_SIZE)) {\r
+      DumpCpuContext (InterruptType, SystemContext);\r
+      DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));\r
+      DEBUG_CODE (\r
+        DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);\r
+      );\r
+\r
+      if (NULL_DETECTION_NONSTOP_MODE) {\r
+        GuardPagePFHandler (SystemContext.SystemContextIa32->ExceptionData);\r
+        goto Exit;\r
+      }\r
+\r
+      CpuDeadLoop ();\r
+    }\r
+\r
     if (IsSmmCommBufferForbiddenAddress (PFAddress)) {\r
       DumpCpuContext (InterruptType, SystemContext);\r
       DEBUG ((DEBUG_ERROR, "Access SMM communication forbidden address (0x%x)!\n", PFAddress));\r
@@ -156,19 +183,6 @@ SmiPFHandler (
     }\r
   }\r
 \r
-  //\r
-  // If NULL pointer was just accessed\r
-  //\r
-  if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0 &&\r
-      (PFAddress < EFI_PAGE_SIZE)) {\r
-    DumpCpuContext (InterruptType, SystemContext);\r
-    DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));\r
-    DEBUG_CODE (\r
-      DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip);\r
-    );\r
-    CpuDeadLoop ();\r
-  }\r
-\r
   if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
     SmmProfilePFHandler (\r
       SystemContext.SystemContextIa32->Eip,\r
@@ -179,6 +193,7 @@ SmiPFHandler (
     SmiDefaultPFHandler ();\r
   }\r
 \r
+Exit:\r
   ReleaseSpinLock (mPFLock);\r
 }\r
 \r
index fa02c1016ce70c1e92745195ed4886c542c9ec2a..879fa0ba6309d548fb8b03c7882c24e4605f3aca 100644 (file)
@@ -20,6 +20,7 @@
 \r
 extern  ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))\r
 extern  ASM_PFX(SmiPFHandler)\r
+extern  ASM_PFX(mSetupDebugTrap)\r
 \r
 global  ASM_PFX(gcSmiIdtr)\r
 global  ASM_PFX(gcSmiGdtr)\r
@@ -673,7 +674,7 @@ o16 mov     [ecx + IA32_TSS._SS], ax
     mov     esp, ebp\r
 \r
 ; Set single step DB# if SMM profile is enabled and page fault exception happens\r
-    cmp     byte [dword ASM_PFX(FeaturePcdGet (PcdCpuSmmProfileEnable))], 0\r
+    cmp     byte [dword ASM_PFX(mSetupDebugTrap)], 0\r
     jz      @Done2\r
 \r
 ; Create return context for iretd in stub function\r
index b4fe0bc23b6cb6f9d0b0a53050d5255700366456..a743cf64f90715a51358da2209abd97cce1b2039 100644 (file)
@@ -51,6 +51,11 @@ BOOLEAN                   mBtsSupported     = TRUE;
 //\r
 BOOLEAN                   mSmmProfileStart = FALSE;\r
 \r
+//\r
+// The flag indicates if #DB will be setup in #PF handler.\r
+//\r
+BOOLEAN                   mSetupDebugTrap = FALSE;\r
+\r
 //\r
 // Record the page fault exception count for one instruction execution.\r
 //\r
@@ -229,7 +234,9 @@ DebugExceptionHandler (
   UINTN  CpuIndex;\r
   UINTN  PFEntry;\r
 \r
-  if (!mSmmProfileStart) {\r
+  if (!mSmmProfileStart &&\r
+      !HEAP_GUARD_NONSTOP_MODE &&\r
+      !NULL_DETECTION_NONSTOP_MODE) {\r
     return;\r
   }\r
   CpuIndex = GetCpuIndex ();\r
@@ -1174,7 +1181,9 @@ InitSmmProfile (
   //\r
   // Skip SMM profile initialization if feature is disabled\r
   //\r
-  if (!FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
+  if (!FeaturePcdGet (PcdCpuSmmProfileEnable) &&\r
+      !HEAP_GUARD_NONSTOP_MODE &&\r
+      !NULL_DETECTION_NONSTOP_MODE) {\r
     return;\r
   }\r
 \r
@@ -1187,6 +1196,11 @@ InitSmmProfile (
   // Initialize profile IDT.\r
   //\r
   InitIdtr ();\r
+\r
+  //\r
+  // Tell #PF handler to prepare a #DB subsequently.\r
+  //\r
+  mSetupDebugTrap = TRUE;\r
 }\r
 \r
 /**\r
@@ -1294,6 +1308,46 @@ RestorePageTableBelow4G (
   }\r
 }\r
 \r
+/**\r
+  Handler for Page Fault triggered by Guard page.\r
+\r
+  @param  ErrorCode  The Error code of exception.\r
+\r
+**/\r
+VOID\r
+GuardPagePFHandler (\r
+  UINTN ErrorCode\r
+  )\r
+{\r
+  UINT64                *PageTable;\r
+  UINT64                PFAddress;\r
+  UINT64                RestoreAddress;\r
+  UINTN                 RestorePageNumber;\r
+  UINTN                 CpuIndex;\r
+\r
+  PageTable         = (UINT64 *)AsmReadCr3 ();\r
+  PFAddress         = AsmReadCr2 ();\r
+  CpuIndex          = GetCpuIndex ();\r
+\r
+  //\r
+  // Memory operation cross pages, like "rep mov" instruction, will cause\r
+  // infinite loop between this and Debug Trap handler. We have to make sure\r
+  // that current page and the page followed are both in PRESENT state.\r
+  //\r
+  RestorePageNumber = 2;\r
+  RestoreAddress = PFAddress;\r
+  while (RestorePageNumber > 0) {\r
+    RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);\r
+    RestoreAddress += EFI_PAGE_SIZE;\r
+    RestorePageNumber--;\r
+  }\r
+\r
+  //\r
+  // Flush TLB\r
+  //\r
+  CpuFlushTlb ();\r
+}\r
+\r
 /**\r
   The Page fault handler to save SMM profile data.\r
 \r
index 04a3dfb2e85764ea9dca99d83f1e105aea5812ef..c2a48235abefe4f8aa931414b48901c535eef329 100644 (file)
@@ -114,6 +114,17 @@ GetCpuIndex (
   VOID\r
   );\r
 \r
+/**\r
+  Handler for Page Fault triggered by Guard page.\r
+\r
+  @param  ErrorCode  The Error code of exception.\r
+\r
+**/\r
+VOID\r
+GuardPagePFHandler (\r
+  UINTN ErrorCode\r
+  );\r
+\r
 //\r
 // The flag indicates if execute-disable is supported by processor.\r
 //\r
@@ -122,5 +133,9 @@ extern BOOLEAN    mXdSupported;
 // The flag indicates if execute-disable is enabled on processor.\r
 //\r
 extern BOOLEAN    mXdEnabled;\r
+//\r
+// The flag indicates if #DB will be setup in #PF handler.\r
+//\r
+extern BOOLEAN    mSetupDebugTrap;\r
 \r
 #endif // _SMM_PROFILE_H_\r
index 1613e9cd5cb97f59668d4fdccae29f3a70e98891..bacb2f8ad32c240ff3932d43d2faf65380afd624 100644 (file)
@@ -64,6 +64,12 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #define   MSR_DEBUG_CTL_BTINT        0x100\r
 #define MSR_DS_AREA                  0x600\r
 \r
+#define HEAP_GUARD_NONSTOP_MODE      \\r
+        ((PcdGet8 (PcdHeapGuardPropertyMask) & (BIT6|BIT3|BIT2)) > BIT6)\r
+\r
+#define NULL_DETECTION_NONSTOP_MODE  \\r
+        ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & (BIT6|BIT1)) > BIT6)\r
+\r
 typedef struct {\r
   EFI_PHYSICAL_ADDRESS   Base;\r
   EFI_PHYSICAL_ADDRESS   Top;\r
index 0fe944fc18cc9402c0217110ba723363ec0ae855..5bb7d57238f443e12701d7176bf89c745cec395c 100644 (file)
@@ -300,7 +300,9 @@ SmmInitPageTable (
     }\r
   }\r
 \r
-  if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
+  if (FeaturePcdGet (PcdCpuSmmProfileEnable) ||\r
+      HEAP_GUARD_NONSTOP_MODE ||\r
+      NULL_DETECTION_NONSTOP_MODE) {\r
     //\r
     // Set own Page Fault entry instead of the default one, because SMM Profile\r
     // feature depends on IRET instruction to do Single Step\r
@@ -846,6 +848,11 @@ SmiPFHandler (
           DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextX64->Rip);\r
         );\r
       }\r
+\r
+      if (HEAP_GUARD_NONSTOP_MODE) {\r
+        GuardPagePFHandler (SystemContext.SystemContextX64->ExceptionData);\r
+        goto Exit;\r
+      }\r
     }\r
     CpuDeadLoop ();\r
   }\r
@@ -863,6 +870,26 @@ SmiPFHandler (
       );\r
       CpuDeadLoop ();\r
     }\r
+\r
+    //\r
+    // If NULL pointer was just accessed\r
+    //\r
+    if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0 &&\r
+        (PFAddress < EFI_PAGE_SIZE)) {\r
+      DumpCpuContext (InterruptType, SystemContext);\r
+      DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));\r
+      DEBUG_CODE (\r
+        DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextX64->Rip);\r
+      );\r
+\r
+      if (NULL_DETECTION_NONSTOP_MODE) {\r
+        GuardPagePFHandler (SystemContext.SystemContextX64->ExceptionData);\r
+        goto Exit;\r
+      }\r
+\r
+      CpuDeadLoop ();\r
+    }\r
+\r
     if (IsSmmCommBufferForbiddenAddress (PFAddress)) {\r
       DumpCpuContext (InterruptType, SystemContext);\r
       DEBUG ((DEBUG_ERROR, "Access SMM communication forbidden address (0x%lx)!\n", PFAddress));\r
@@ -873,19 +900,6 @@ SmiPFHandler (
     }\r
   }\r
 \r
-  //\r
-  // If NULL pointer was just accessed\r
-  //\r
-  if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0 &&\r
-      (PFAddress < EFI_PAGE_SIZE)) {\r
-    DumpCpuContext (InterruptType, SystemContext);\r
-    DEBUG ((DEBUG_ERROR, "!!! NULL pointer access !!!\n"));\r
-    DEBUG_CODE (\r
-      DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextX64->Rip);\r
-    );\r
-    CpuDeadLoop ();\r
-  }\r
-\r
   if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
     SmmProfilePFHandler (\r
       SystemContext.SystemContextX64->Rip,\r
@@ -895,6 +909,7 @@ SmiPFHandler (
     SmiDefaultPFHandler ();\r
   }\r
 \r
+Exit:\r
   ReleaseSpinLock (mPFLock);\r
 }\r
 \r