X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FPiSmmCpuDxeSmm%2FSmmProfile.c;h=3b2f967355d4aaaa763e9b9f04f6ab311b94dfcb;hp=9588eaf02964b175d029cac637664691226d2186;hb=0acd869796ded1266e69487dff717cd69d6031f9;hpb=29dc8aa861fac78c6d62391dff312db934b755e3
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
index 9588eaf029..3b2f967355 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
@@ -1,16 +1,10 @@
/** @file
Enable SMM profile.
-Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2012 - 2019, Intel Corporation. All rights reserved.
Copyright (c) 2017, AMD Incorporated. All rights reserved.
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+SPDX-License-Identifier: BSD-2-Clause-Patent
**/
@@ -31,6 +25,11 @@ UINTN mSmmProfileSize;
//
UINTN mMsrDsAreaSize = SMM_PROFILE_DTS_SIZE;
+//
+// The flag indicates if execute-disable is supported by processor.
+//
+BOOLEAN mXdSupported = TRUE;
+
//
// The flag indicates if execute-disable is enabled on processor.
//
@@ -46,6 +45,11 @@ BOOLEAN mBtsSupported = TRUE;
//
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.
//
@@ -224,7 +228,9 @@ DebugExceptionHandler (
UINTN CpuIndex;
UINTN PFEntry;
- if (!mSmmProfileStart) {
+ if (!mSmmProfileStart &&
+ !HEAP_GUARD_NONSTOP_MODE &&
+ !NULL_DETECTION_NONSTOP_MODE) {
return;
}
CpuIndex = GetCpuIndex ();
@@ -713,84 +719,6 @@ InitPaging (
return ;
}
-/**
- To find FADT in ACPI tables.
-
- @param AcpiTableGuid The GUID used to find ACPI table in UEFI ConfigurationTable.
-
- @return FADT table pointer.
-**/
-EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *
-FindAcpiFadtTableByAcpiGuid (
- IN EFI_GUID *AcpiTableGuid
- )
-{
- EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER *Rsdp;
- EFI_ACPI_DESCRIPTION_HEADER *Rsdt;
- EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
- UINTN Index;
- UINT32 Data32;
- Rsdp = NULL;
- Rsdt = NULL;
- Fadt = NULL;
- //
- // found ACPI table RSD_PTR from system table
- //
- for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
- if (CompareGuid (&(gST->ConfigurationTable[Index].VendorGuid), AcpiTableGuid)) {
- //
- // A match was found.
- //
- Rsdp = gST->ConfigurationTable[Index].VendorTable;
- break;
- }
- }
-
- if (Rsdp == NULL) {
- return NULL;
- }
-
- Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *)(UINTN) Rsdp->RsdtAddress;
- if (Rsdt == NULL || Rsdt->Signature != EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_TABLE_SIGNATURE) {
- return NULL;
- }
-
- for (Index = sizeof (EFI_ACPI_DESCRIPTION_HEADER); Index < Rsdt->Length; Index = Index + sizeof (UINT32)) {
-
- Data32 = *(UINT32 *) ((UINT8 *) Rsdt + Index);
- Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) (UINT32 *) (UINTN) Data32;
- if (Fadt->Header.Signature == EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
- break;
- }
- }
-
- if (Fadt == NULL || Fadt->Header.Signature != EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE) {
- return NULL;
- }
-
- return Fadt;
-}
-
-/**
- To find FADT in ACPI tables.
-
- @return FADT table pointer.
-**/
-EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *
-FindAcpiFadtTable (
- VOID
- )
-{
- EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
-
- Fadt = FindAcpiFadtTableByAcpiGuid (&gEfiAcpi20TableGuid);
- if (Fadt != NULL) {
- return Fadt;
- }
-
- return FindAcpiFadtTableByAcpiGuid (&gEfiAcpi10TableGuid);
-}
-
/**
To get system port address of the SMI Command Port in FADT table.
@@ -802,7 +730,9 @@ GetSmiCommandPort (
{
EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *Fadt;
- Fadt = FindAcpiFadtTable ();
+ Fadt = (EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE *) EfiLocateFirstAcpiTable (
+ EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE
+ );
ASSERT (Fadt != NULL);
mSmiCommandPort = Fadt->SmiCmd;
@@ -991,7 +921,7 @@ InitSmmProfileInternal (
}
/**
- Check if XD feature is supported by a processor.
+ Check if feature is supported by a processor.
**/
VOID
@@ -1000,9 +930,23 @@ CheckFeatureSupported (
)
{
UINT32 RegEax;
+ UINT32 RegEcx;
UINT32 RegEdx;
MSR_IA32_MISC_ENABLE_REGISTER MiscEnableMsr;
+ if ((PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) && mCetSupported) {
+ AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+ if (RegEax <= CPUID_EXTENDED_FUNCTION) {
+ mCetSupported = FALSE;
+ PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+ }
+ AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, NULL);
+ if ((RegEcx & CPUID_CET_SS) == 0) {
+ mCetSupported = FALSE;
+ PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+ }
+ }
+
if (mXdSupported) {
AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
if (RegEax <= CPUID_EXTENDED_FUNCTION) {
@@ -1010,6 +954,7 @@ CheckFeatureSupported (
// Extended CPUID functions are not supported on this processor.
//
mXdSupported = FALSE;
+ PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);
}
AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
@@ -1018,6 +963,7 @@ CheckFeatureSupported (
// Execute Disable Bit feature is not supported on this processor.
//
mXdSupported = FALSE;
+ PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);
}
}
@@ -1167,7 +1113,9 @@ InitSmmProfile (
//
// Skip SMM profile initialization if feature is disabled
//
- if (!FeaturePcdGet (PcdCpuSmmProfileEnable)) {
+ if (!FeaturePcdGet (PcdCpuSmmProfileEnable) &&
+ !HEAP_GUARD_NONSTOP_MODE &&
+ !NULL_DETECTION_NONSTOP_MODE) {
return;
}
@@ -1180,6 +1128,11 @@ InitSmmProfile (
// Initialize profile IDT.
//
InitIdtr ();
+
+ //
+ // Tell #PF handler to prepare a #DB subsequently.
+ //
+ mSetupDebugTrap = TRUE;
}
/**
@@ -1287,6 +1240,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.
@@ -1302,6 +1295,8 @@ SmmProfilePFHandler (
{
UINT64 *PageTable;
UINT64 PFAddress;
+ UINT64 RestoreAddress;
+ UINTN RestorePageNumber;
UINTN CpuIndex;
UINTN Index;
UINT64 InstructionAddress;
@@ -1331,10 +1326,21 @@ SmmProfilePFHandler (
PFAddress = AsmReadCr2 ();
CpuIndex = GetCpuIndex ();
- if (PFAddress <= 0xFFFFFFFF) {
- RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode);
- } else {
- RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress);
+ //
+ // 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) {
+ if (RestoreAddress <= 0xFFFFFFFF) {
+ RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);
+ } else {
+ RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress);
+ }
+ RestoreAddress += EFI_PAGE_SIZE;
+ RestorePageNumber--;
}
if (!IsValidPFAddress) {