\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
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
);\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
}\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
SmiDefaultPFHandler ();\r
}\r
\r
+Exit:\r
ReleaseSpinLock (mPFLock);\r
}\r
\r
\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
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
//\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
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
//\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
// 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
}\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
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
// 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
#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
}\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
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
);\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
}\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
SmiDefaultPFHandler ();\r
}\r
\r
+Exit:\r
ReleaseSpinLock (mPFLock);\r
}\r
\r