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