]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/SmmProfile.c
UefiCpuPkg: Remove redundant library classes, Ppis and GUIDs
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / SmmProfile.c
index 4b7fad29c30a0c65093917aacddd430c46f5613d..a743cf64f90715a51358da2209abd97cce1b2039 100644 (file)
@@ -1,7 +1,9 @@
 /** @file\r
 Enable SMM profile.\r
 \r
-Copyright (c) 2012 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2012 - 2017, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>\r
+\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -29,6 +31,11 @@ UINTN                     mSmmProfileSize;
 //\r
 UINTN                     mMsrDsAreaSize   = SMM_PROFILE_DTS_SIZE;\r
 \r
+//\r
+// The flag indicates if execute-disable is supported by processor.\r
+//\r
+BOOLEAN                   mXdSupported     = TRUE;\r
+\r
 //\r
 // The flag indicates if execute-disable is enabled on processor.\r
 //\r
@@ -44,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
@@ -80,6 +92,12 @@ MEMORY_PROTECTION_RANGE mProtectionMemRangeTemplate[] = {
   //\r
   {{0x00000000, 0x00000000},TRUE,TRUE},\r
 \r
+  //\r
+  // SMRAM ranges not covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz (to be fixed in runtime).\r
+  // It is always present and instruction fetches are allowed.\r
+  // {{0x00000000, 0x00000000},TRUE,FALSE},\r
+  //\r
+\r
   //\r
   // Future extended range could be added here.\r
   //\r
@@ -139,7 +157,7 @@ GetCpuIndex (
 \r
   ApicId = GetApicId ();\r
 \r
-  for (Index = 0; Index < PcdGet32 (PcdCpuMaxLogicalProcessorNumber); Index++) {\r
+  for (Index = 0; Index < mMaxNumberOfCpus; Index++) {\r
     if (gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId == ApicId) {\r
       return Index;\r
     }\r
@@ -216,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
@@ -244,6 +264,33 @@ DebugExceptionHandler (
   ClearTrapFlag (SystemContext);\r
 }\r
 \r
+/**\r
+  Check if the input address is in SMM ranges.\r
+\r
+  @param[in]  Address       The input address.\r
+\r
+  @retval TRUE     The input address is in SMM.\r
+  @retval FALSE    The input address is not in SMM.\r
+**/\r
+BOOLEAN\r
+IsInSmmRanges (\r
+  IN EFI_PHYSICAL_ADDRESS   Address\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  if ((Address >= mCpuHotPlugData.SmrrBase) && (Address < mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {\r
+    return TRUE;\r
+  }\r
+  for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {\r
+    if (Address >= mSmmCpuSmramRanges[Index].CpuStart &&\r
+        Address < mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize) {\r
+      return TRUE;\r
+    }\r
+  }\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Check if the memory address will be mapped by 4KB-page.\r
 \r
@@ -259,7 +306,6 @@ IsAddressValid (
 {\r
   UINTN  Index;\r
 \r
-  *Nx = FALSE;\r
   if (FeaturePcdGet (PcdCpuSmmProfileEnable)) {\r
     //\r
     // Check configuration\r
@@ -274,9 +320,9 @@ IsAddressValid (
     return FALSE;\r
 \r
   } else {\r
-    if ((Address < mCpuHotPlugData.SmrrBase) ||\r
-        (Address >= mCpuHotPlugData.SmrrBase + mCpuHotPlugData.SmrrSize)) {\r
-      *Nx = TRUE;\r
+    *Nx = TRUE;\r
+    if (IsInSmmRanges (Address)) {\r
+      *Nx = FALSE;\r
     }\r
     return TRUE;\r
   }\r
@@ -332,7 +378,7 @@ InitProtectedMemRange (
 {\r
   UINTN                            Index;\r
   UINTN                            NumberOfDescriptors;\r
-  UINTN                            NumberOfMmioDescriptors;\r
+  UINTN                            NumberOfAddedDescriptors;\r
   UINTN                            NumberOfProtectRange;\r
   UINTN                            NumberOfSpliteRange;\r
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *MemorySpaceMap;\r
@@ -345,7 +391,7 @@ InitProtectedMemRange (
   UINT64                           Low4KBPageSize;\r
 \r
   NumberOfDescriptors      = 0;\r
-  NumberOfMmioDescriptors  = 0;\r
+  NumberOfAddedDescriptors = mSmmCpuSmramRangeCount;\r
   NumberOfSpliteRange      = 0;\r
   MemorySpaceMap           = NULL;\r
 \r
@@ -358,12 +404,12 @@ InitProtectedMemRange (
        );\r
   for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
     if (MemorySpaceMap[Index].GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo) {\r
-      NumberOfMmioDescriptors++;\r
+      NumberOfAddedDescriptors++;\r
     }\r
   }\r
 \r
-  if (NumberOfMmioDescriptors != 0) {\r
-    TotalSize = NumberOfMmioDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);\r
+  if (NumberOfAddedDescriptors != 0) {\r
+    TotalSize = NumberOfAddedDescriptors * sizeof (MEMORY_PROTECTION_RANGE) + sizeof (mProtectionMemRangeTemplate);\r
     mProtectionMemRange = (MEMORY_PROTECTION_RANGE *) AllocateZeroPool (TotalSize);\r
     ASSERT (mProtectionMemRange != NULL);\r
     mProtectionMemRangeCount = TotalSize / sizeof (MEMORY_PROTECTION_RANGE);\r
@@ -380,10 +426,28 @@ InitProtectedMemRange (
     mSplitMemRange = (MEMORY_RANGE *) AllocateZeroPool (TotalSize);\r
     ASSERT (mSplitMemRange != NULL);\r
 \r
+    //\r
+    // Create SMM ranges which are set to present and execution-enable.\r
+    //\r
+    NumberOfProtectRange = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);\r
+    for (Index = 0; Index < mSmmCpuSmramRangeCount; Index++) {\r
+      if (mSmmCpuSmramRanges[Index].CpuStart >= mProtectionMemRange[0].Range.Base &&\r
+          mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize < mProtectionMemRange[0].Range.Top) {\r
+        //\r
+        // If the address have been already covered by mCpuHotPlugData.SmrrBase/mCpuHotPlugData.SmrrSiz\r
+        //\r
+        break;\r
+      }\r
+      mProtectionMemRange[NumberOfProtectRange].Range.Base = mSmmCpuSmramRanges[Index].CpuStart;\r
+      mProtectionMemRange[NumberOfProtectRange].Range.Top  = mSmmCpuSmramRanges[Index].CpuStart + mSmmCpuSmramRanges[Index].PhysicalSize;\r
+      mProtectionMemRange[NumberOfProtectRange].Present    = TRUE;\r
+      mProtectionMemRange[NumberOfProtectRange].Nx         = FALSE;\r
+      NumberOfProtectRange++;\r
+    }\r
+\r
     //\r
     // Create MMIO ranges which are set to present and execution-disable.\r
     //\r
-    NumberOfProtectRange    = sizeof (mProtectionMemRangeTemplate) / sizeof (MEMORY_PROTECTION_RANGE);\r
     for (Index = 0; Index < NumberOfDescriptors; Index++) {\r
       if (MemorySpaceMap[Index].GcdMemoryType != EfiGcdMemoryTypeMemoryMappedIo) {\r
         continue;\r
@@ -394,6 +458,12 @@ InitProtectedMemRange (
       mProtectionMemRange[NumberOfProtectRange].Nx         = TRUE;\r
       NumberOfProtectRange++;\r
     }\r
+\r
+    //\r
+    // Check and updated actual protected memory ranges count\r
+    //\r
+    ASSERT (NumberOfProtectRange <= mProtectionMemRangeCount);\r
+    mProtectionMemRangeCount = NumberOfProtectRange;\r
   }\r
 \r
   //\r
@@ -513,7 +583,7 @@ InitPaging (
         //\r
         continue;\r
       }\r
-      Pde = (UINT64 *)(UINTN)(Pml4[Level1] & PHYSICAL_ADDRESS_MASK);\r
+      Pde = (UINT64 *)(UINTN)(Pml4[Level1] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
     } else {\r
       Pde = (UINT64*)(UINTN)mSmmProfileCr3;\r
     }\r
@@ -530,7 +600,7 @@ InitPaging (
         //\r
         continue;\r
       }\r
-      Pte = (UINT64 *)(UINTN)(*Pde & PHYSICAL_ADDRESS_MASK);\r
+      Pte = (UINT64 *)(UINTN)(*Pde & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
       if (Pte == 0) {\r
         continue;\r
       }\r
@@ -557,9 +627,9 @@ InitPaging (
 \r
           // Split it\r
           for (Level4 = 0; Level4 < SIZE_4KB / sizeof(*Pt); Level4++) {\r
-            Pt[Level4] = Address + ((Level4 << 12) | PAGE_ATTRIBUTE_BITS);\r
+            Pt[Level4] = Address + ((Level4 << 12) | mAddressEncMask | PAGE_ATTRIBUTE_BITS);\r
           } // end for PT\r
-          *Pte = (UINTN)Pt | PAGE_ATTRIBUTE_BITS;\r
+          *Pte = (UINT64)(UINTN)Pt | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
         } // end if IsAddressSplit\r
       } // end for PTE\r
     } // end for PDE\r
@@ -577,7 +647,7 @@ InitPaging (
         //\r
         continue;\r
       }\r
-      Pde = (UINT64 *)(UINTN)(Pml4[Level1] & PHYSICAL_ADDRESS_MASK);\r
+      Pde = (UINT64 *)(UINTN)(Pml4[Level1] & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
     } else {\r
       Pde = (UINT64*)(UINTN)mSmmProfileCr3;\r
     }\r
@@ -597,7 +667,7 @@ InitPaging (
         }\r
         continue;\r
       }\r
-      Pte = (UINT64 *)(UINTN)(*Pde & PHYSICAL_ADDRESS_MASK);\r
+      Pte = (UINT64 *)(UINTN)(*Pde & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
       if (Pte == 0) {\r
         continue;\r
       }\r
@@ -624,7 +694,7 @@ InitPaging (
           }\r
         } else {\r
           // 4KB page\r
-          Pt = (UINT64 *)(UINTN)(*Pte & PHYSICAL_ADDRESS_MASK);\r
+          Pt = (UINT64 *)(UINTN)(*Pte & ~mAddressEncMask & PHYSICAL_ADDRESS_MASK);\r
           if (Pt == 0) {\r
             continue;\r
           }\r
@@ -825,13 +895,13 @@ InitSmmProfileInternal (
   UINTN                      MsrDsAreaSizePerCpu;\r
   UINTN                      TotalSize;\r
 \r
-  mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+  mPFEntryCount = (UINTN *)AllocateZeroPool (sizeof (UINTN) * mMaxNumberOfCpus);\r
   ASSERT (mPFEntryCount != NULL);\r
   mLastPFEntryValue = (UINT64  (*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (\r
-                                                         sizeof (mLastPFEntryValue[0]) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+                                                         sizeof (mLastPFEntryValue[0]) * mMaxNumberOfCpus);\r
   ASSERT (mLastPFEntryValue != NULL);\r
   mLastPFEntryPointer = (UINT64 *(*)[MAX_PF_ENTRY_COUNT])AllocateZeroPool (\r
-                                                           sizeof (mLastPFEntryPointer[0]) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+                                                           sizeof (mLastPFEntryPointer[0]) * mMaxNumberOfCpus);\r
   ASSERT (mLastPFEntryPointer != NULL);\r
 \r
   //\r
@@ -872,17 +942,17 @@ InitSmmProfileInternal (
   mSmmProfileBase->NumCpus        = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
 \r
   if (mBtsSupported) {\r
-    mMsrDsArea = (MSR_DS_AREA_STRUCT **)AllocateZeroPool (sizeof (MSR_DS_AREA_STRUCT *) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+    mMsrDsArea = (MSR_DS_AREA_STRUCT **)AllocateZeroPool (sizeof (MSR_DS_AREA_STRUCT *) * mMaxNumberOfCpus);\r
     ASSERT (mMsrDsArea != NULL);\r
-    mMsrBTSRecord = (BRANCH_TRACE_RECORD **)AllocateZeroPool (sizeof (BRANCH_TRACE_RECORD *) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+    mMsrBTSRecord = (BRANCH_TRACE_RECORD **)AllocateZeroPool (sizeof (BRANCH_TRACE_RECORD *) * mMaxNumberOfCpus);\r
     ASSERT (mMsrBTSRecord != NULL);\r
-    mMsrPEBSRecord = (PEBS_RECORD **)AllocateZeroPool (sizeof (PEBS_RECORD *) * PcdGet32 (PcdCpuMaxLogicalProcessorNumber));\r
+    mMsrPEBSRecord = (PEBS_RECORD **)AllocateZeroPool (sizeof (PEBS_RECORD *) * mMaxNumberOfCpus);\r
     ASSERT (mMsrPEBSRecord != NULL);\r
 \r
     mMsrDsAreaBase  = (MSR_DS_AREA_STRUCT *)((UINTN)Base + mSmmProfileSize);\r
-    MsrDsAreaSizePerCpu = mMsrDsAreaSize / PcdGet32 (PcdCpuMaxLogicalProcessorNumber);\r
+    MsrDsAreaSizePerCpu = mMsrDsAreaSize / mMaxNumberOfCpus;\r
     mBTSRecordNumber    = (MsrDsAreaSizePerCpu - sizeof(PEBS_RECORD) * PEBS_RECORD_NUMBER - sizeof(MSR_DS_AREA_STRUCT)) / sizeof(BRANCH_TRACE_RECORD);\r
-    for (Index = 0; Index < PcdGet32 (PcdCpuMaxLogicalProcessorNumber); Index++) {\r
+    for (Index = 0; Index < mMaxNumberOfCpus; Index++) {\r
       mMsrDsArea[Index]     = (MSR_DS_AREA_STRUCT *)((UINTN)mMsrDsAreaBase + MsrDsAreaSizePerCpu * Index);\r
       mMsrBTSRecord[Index]  = (BRANCH_TRACE_RECORD *)((UINTN)mMsrDsArea[Index] + sizeof(MSR_DS_AREA_STRUCT));\r
       mMsrPEBSRecord[Index] = (PEBS_RECORD *)((UINTN)mMsrDsArea[Index] + MsrDsAreaSizePerCpu - sizeof(PEBS_RECORD) * PEBS_RECORD_NUMBER);\r
@@ -952,6 +1022,7 @@ CheckFeatureSupported (
       // Extended CPUID functions are not supported on this processor.\r
       //\r
       mXdSupported = FALSE;\r
+      PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
     }\r
 \r
     AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);\r
@@ -960,6 +1031,7 @@ CheckFeatureSupported (
       // Execute Disable Bit feature is not supported on this processor.\r
       //\r
       mXdSupported = FALSE;\r
+      PatchInstructionX86 (gPatchXdSupported, mXdSupported, 1);\r
     }\r
   }\r
 \r
@@ -1109,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
@@ -1122,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
@@ -1229,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
@@ -1244,6 +1363,8 @@ SmmProfilePFHandler (
 {\r
   UINT64                *PageTable;\r
   UINT64                PFAddress;\r
+  UINT64                RestoreAddress;\r
+  UINTN                 RestorePageNumber;\r
   UINTN                 CpuIndex;\r
   UINTN                 Index;\r
   UINT64                InstructionAddress;\r
@@ -1273,10 +1394,21 @@ SmmProfilePFHandler (
   PFAddress         = AsmReadCr2 ();\r
   CpuIndex          = GetCpuIndex ();\r
 \r
-  if (PFAddress <= 0xFFFFFFFF) {\r
-    RestorePageTableBelow4G (PageTable, PFAddress, CpuIndex, ErrorCode);\r
-  } else {\r
-    RestorePageTableAbove4G (PageTable, PFAddress, CpuIndex, ErrorCode, &IsValidPFAddress);\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
+    if (RestoreAddress <= 0xFFFFFFFF) {\r
+      RestorePageTableBelow4G (PageTable, RestoreAddress, CpuIndex, ErrorCode);\r
+    } else {\r
+      RestorePageTableAbove4G (PageTable, RestoreAddress, CpuIndex, ErrorCode, &IsValidPFAddress);\r
+    }\r
+    RestoreAddress += EFI_PAGE_SIZE;\r
+    RestorePageNumber--;\r
   }\r
 \r
   if (!IsValidPFAddress) {\r
@@ -1375,5 +1507,8 @@ InitIdtr (
   VOID\r
   )\r
 {\r
-  SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_DEBUG, DebugExceptionHandler);\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = SmmRegisterExceptionHandler (&mSmmCpuService, EXCEPT_IA32_DEBUG, DebugExceptionHandler);\r
+  ASSERT_EFI_ERROR (Status);\r
 }\r