From 7fa1376c5c97d18eac719f35e5e85356d3c1b033 Mon Sep 17 00:00:00 2001 From: Jiewen Yao Date: Tue, 22 Nov 2016 15:05:11 +0800 Subject: UefiCpuPkg/PiSmmCpu: Correct exception message. This patch fixes the first part of https://bugzilla.tianocore.org/show_bug.cgi?id=242 Previously, when SMM exception happens, "stack overflow" is misreported. This patch checked the PF address to see it is stack overflow, or it is caused by SMM page protection. It dumps exception data, PF address and the module trigger the issue. Cc: Laszlo Ersek Cc: Jeff Fan Cc: Michael D Kinney Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jiewen Yao Tested-by: Laszlo Ersek Reviewed-by: Laszlo Ersek Reviewed-by: Jeff Fan --- UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c | 38 +++++++++++++++++++++++++++++--- UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h | 9 ++++++++ UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c | 37 +++++++++++++++++++++++++++---- 3 files changed, 77 insertions(+), 7 deletions(-) (limited to 'UefiCpuPkg') diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c index 5033bc50d7..ba79477e64 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/Ia32/PageTbl.c @@ -91,6 +91,8 @@ SmiPFHandler ( ) { UINTN PFAddress; + UINTN GuardPageAddress; + UINTN CpuIndex; ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT); @@ -98,10 +100,40 @@ SmiPFHandler ( PFAddress = AsmReadCr2 (); - if ((FeaturePcdGet (PcdCpuSmmStackGuard)) && - (PFAddress >= mCpuHotPlugData.SmrrBase) && + // + // If a page fault occurs in SMRAM range, it might be in a SMM stack guard page, + // or SMM page protection violation. + // + if ((PFAddress >= mCpuHotPlugData.SmrrBase) && (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) { - DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n")); + CpuIndex = GetCpuIndex (); + GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * mSmmStackSize); + if ((FeaturePcdGet (PcdCpuSmmStackGuard)) && + (PFAddress >= GuardPageAddress) && + (PFAddress < (GuardPageAddress + EFI_PAGE_SIZE))) { + DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n")); + } else { + DEBUG ((DEBUG_ERROR, "SMM exception data - 0x%x(", SystemContext.SystemContextIa32->ExceptionData)); + DEBUG ((DEBUG_ERROR, "I:%x, R:%x, U:%x, W:%x, P:%x", + (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0, + (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_RSVD) != 0, + (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_US) != 0, + (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_WR) != 0, + (SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_P) != 0 + )); + DEBUG ((DEBUG_ERROR, ")\n")); + if ((SystemContext.SystemContextIa32->ExceptionData & IA32_PF_EC_ID) != 0) { + DEBUG ((DEBUG_ERROR, "SMM exception at execution (0x%x)\n", PFAddress)); + DEBUG_CODE ( + DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextIa32->Esp); + ); + } else { + DEBUG ((DEBUG_ERROR, "SMM exception at access (0x%x)\n", PFAddress)); + DEBUG_CODE ( + DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextIa32->Eip); + ); + } + } CpuDeadLoop (); } diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h index b6fb5cf34b..04a3dfb2e8 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.h @@ -105,6 +105,15 @@ InitPaging ( VOID ); +/** + Get CPU Index from APIC ID. + +**/ +UINTN +GetCpuIndex ( + VOID + ); + // // The flag indicates if execute-disable is supported by processor. // diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c index 531e188215..7237e57e7e 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/X64/PageTbl.c @@ -804,6 +804,8 @@ SmiPFHandler ( ) { UINTN PFAddress; + UINTN GuardPageAddress; + UINTN CpuIndex; ASSERT (InterruptType == EXCEPT_IA32_PAGE_FAULT); @@ -817,12 +819,39 @@ SmiPFHandler ( } // - // If a page fault occurs in SMRAM range, it should be in a SMM stack guard page. + // If a page fault occurs in SMRAM range, it might be in a SMM stack guard page, + // or SMM page protection violation. // - if ((FeaturePcdGet (PcdCpuSmmStackGuard)) && - (PFAddress >= mCpuHotPlugData.SmrrBase) && + if ((PFAddress >= mCpuHotPlugData.SmrrBase) && (PFAddress < (mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize))) { - DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n")); + CpuIndex = GetCpuIndex (); + GuardPageAddress = (mSmmStackArrayBase + EFI_PAGE_SIZE + CpuIndex * mSmmStackSize); + if ((FeaturePcdGet (PcdCpuSmmStackGuard)) && + (PFAddress >= GuardPageAddress) && + (PFAddress < (GuardPageAddress + EFI_PAGE_SIZE))) { + DEBUG ((DEBUG_ERROR, "SMM stack overflow!\n")); + } else { + DEBUG ((DEBUG_ERROR, "SMM exception data - 0x%lx(", SystemContext.SystemContextX64->ExceptionData)); + DEBUG ((DEBUG_ERROR, "I:%x, R:%x, U:%x, W:%x, P:%x", + (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0, + (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_RSVD) != 0, + (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_US) != 0, + (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_WR) != 0, + (SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_P) != 0 + )); + DEBUG ((DEBUG_ERROR, ")\n")); + if ((SystemContext.SystemContextX64->ExceptionData & IA32_PF_EC_ID) != 0) { + DEBUG ((DEBUG_ERROR, "SMM exception at execution (0x%lx)\n", PFAddress)); + DEBUG_CODE ( + DumpModuleInfoByIp (*(UINTN *)(UINTN)SystemContext.SystemContextX64->Rsp); + ); + } else { + DEBUG ((DEBUG_ERROR, "SMM exception at access (0x%lx)\n", PFAddress)); + DEBUG_CODE ( + DumpModuleInfoByIp ((UINTN)SystemContext.SystemContextX64->Rip); + ); + } + } CpuDeadLoop (); } -- cgit v1.2.3