]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
MdeModulePkg/Dxe/Page: take MAX_ALLOC_ADDRESS into account
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / MpService.c
index d99ad467b75f3c876d99b6b675764068449a16e5..abcc3eea052f4b99142ccdee8a9a47ab55addad0 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 SMM MP service implementation\r
 \r
-Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2018, 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
@@ -27,6 +27,7 @@ SMM_CPU_SEMAPHORES                          mSmmCpuSemaphores;
 UINTN                                       mSemaphoreSize;\r
 SPIN_LOCK                                   *mPFLock = NULL;\r
 SMM_CPU_SYNC_MODE                           mCpuSmmSyncMode;\r
+BOOLEAN                                     mMachineCheckSupported = FALSE;\r
 \r
 /**\r
   Performs an atomic compare exchange operation to get semaphore.\r
@@ -196,6 +197,56 @@ AllCpusInSmmWithExceptions (
   return TRUE;\r
 }\r
 \r
+/**\r
+  Has OS enabled Lmce in the MSR_IA32_MCG_EXT_CTL\r
+\r
+  @retval TRUE     Os enable lmce.\r
+  @retval FALSE    Os not enable lmce.\r
+\r
+**/\r
+BOOLEAN\r
+IsLmceOsEnabled (\r
+  VOID\r
+  )\r
+{\r
+  MSR_IA32_MCG_CAP_REGISTER          McgCap;\r
+  MSR_IA32_FEATURE_CONTROL_REGISTER  FeatureCtrl;\r
+  MSR_IA32_MCG_EXT_CTL_REGISTER      McgExtCtrl;\r
+\r
+  McgCap.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_CAP);\r
+  if (McgCap.Bits.MCG_LMCE_P == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  FeatureCtrl.Uint64 = AsmReadMsr64 (MSR_IA32_FEATURE_CONTROL);\r
+  if (FeatureCtrl.Bits.LmceOn == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  McgExtCtrl.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_EXT_CTL);\r
+  return (BOOLEAN) (McgExtCtrl.Bits.LMCE_EN == 1);\r
+}\r
+\r
+/**\r
+  Return if Local machine check exception signaled.\r
+\r
+  Indicates (when set) that a local machine check exception was generated. This indicates that the current machine-check event was\r
+  delivered to only the logical processor.\r
+\r
+  @retval TRUE    LMCE was signaled.\r
+  @retval FALSE   LMCE was not signaled.\r
+\r
+**/\r
+BOOLEAN\r
+IsLmceSignaled (\r
+  VOID\r
+  )\r
+{\r
+  MSR_IA32_MCG_STATUS_REGISTER McgStatus;\r
+\r
+  McgStatus.Uint64 = AsmReadMsr64 (MSR_IA32_MCG_STATUS);\r
+  return (BOOLEAN) (McgStatus.Bits.LMCE_S == 1);\r
+}\r
 \r
 /**\r
   Given timeout constraint, wait for all APs to arrive, and insure when this function returns, no AP will execute normal mode code before\r
@@ -209,9 +260,18 @@ SmmWaitForApArrival (
 {\r
   UINT64                            Timer;\r
   UINTN                             Index;\r
+  BOOLEAN                           LmceEn;\r
+  BOOLEAN                           LmceSignal;\r
 \r
   ASSERT (*mSmmMpSyncData->Counter <= mNumberOfCpus);\r
 \r
+  LmceEn     = FALSE;\r
+  LmceSignal = FALSE;\r
+  if (mMachineCheckSupported) {\r
+    LmceEn     = IsLmceOsEnabled ();\r
+    LmceSignal = IsLmceSignaled();\r
+  }\r
+\r
   //\r
   // Platform implementor should choose a timeout value appropriately:\r
   // - The timeout value should balance the SMM time constrains and the likelihood that delayed CPUs are excluded in the SMM run. Note\r
@@ -227,7 +287,7 @@ SmmWaitForApArrival (
   // Sync with APs 1st timeout\r
   //\r
   for (Timer = StartSyncTimer ();\r
-       !IsSyncTimerTimeout (Timer) &&\r
+       !IsSyncTimerTimeout (Timer) && !(LmceEn && LmceSignal) &&\r
        !AllCpusInSmmWithExceptions (ARRIVAL_EXCEPTION_BLOCKED | ARRIVAL_EXCEPTION_SMI_DISABLED );\r
        ) {\r
     CpuPause ();\r
@@ -407,7 +467,7 @@ BSPHandler (
   //\r
   // The BUSY lock is initialized to Acquired state\r
   //\r
-  AcquireSpinLockOrFail (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
+  AcquireSpinLock (mSmmMpSyncData->CpuData[CpuIndex].Busy);\r
 \r
   //\r
   // Perform the pre tasks\r
@@ -783,7 +843,7 @@ Gen4GPageTable (
   // Set Page Directory Pointers\r
   //\r
   for (Index = 0; Index < 4; Index++) {\r
-    Pte[Index] = (UINT64)((UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1)) | mAddressEncMask |\r
+    Pte[Index] = ((UINTN)PageTable + EFI_PAGE_SIZE * (Index + 1)) | mAddressEncMask |\r
                    (Is32BitPageTable ? IA32_PAE_PDPTE_ATTRIBUTE_BITS : PAGE_ATTRIBUTE_BITS);\r
   }\r
   Pte += EFI_PAGE_SIZE / sizeof (*Pte);\r
@@ -795,10 +855,10 @@ Gen4GPageTable (
     Pte[Index] = (Index << 21) | mAddressEncMask | IA32_PG_PS | PAGE_ATTRIBUTE_BITS;\r
   }\r
 \r
+  Pdpte = (UINT64*)PageTable;\r
   if (FeaturePcdGet (PcdCpuSmmStackGuard)) {\r
     Pages = (UINTN)PageTable + EFI_PAGES_TO_SIZE (5);\r
     GuardPage = mSmmStackArrayBase + EFI_PAGE_SIZE;\r
-    Pdpte = (UINT64*)PageTable;\r
     for (PageIndex = Low2MBoundary; PageIndex <= High2MBoundary; PageIndex += SIZE_2MB) {\r
       Pte = (UINT64*)(UINTN)(Pdpte[BitFieldRead32 ((UINT32)PageIndex, 30, 31)] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));\r
       Pte[BitFieldRead32 ((UINT32)PageIndex, 21, 29)] = (UINT64)Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
@@ -826,6 +886,29 @@ Gen4GPageTable (
     }\r
   }\r
 \r
+  if ((PcdGet8 (PcdNullPointerDetectionPropertyMask) & BIT1) != 0) {\r
+    Pte = (UINT64*)(UINTN)(Pdpte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));\r
+    if ((Pte[0] & IA32_PG_PS) == 0) {\r
+      // 4K-page entries are already mapped. Just hide the first one anyway.\r
+      Pte = (UINT64*)(UINTN)(Pte[0] & ~mAddressEncMask & ~(EFI_PAGE_SIZE - 1));\r
+      Pte[0] &= ~(UINT64)IA32_PG_P; // Hide page 0\r
+    } else {\r
+      // Create 4K-page entries\r
+      Pages = (UINTN)AllocatePageTableMemory (1);\r
+      ASSERT (Pages != 0);\r
+\r
+      Pte[0] = (UINT64)(Pages | mAddressEncMask | PAGE_ATTRIBUTE_BITS);\r
+\r
+      Pte = (UINT64*)Pages;\r
+      PageAddress = 0;\r
+      Pte[0] = PageAddress | mAddressEncMask; // Hide page 0 but present left\r
+      for (Index = 1; Index < EFI_PAGE_SIZE / sizeof (*Pte); Index++) {\r
+        PageAddress += EFI_PAGE_SIZE;\r
+        Pte[Index] = PageAddress | mAddressEncMask | PAGE_ATTRIBUTE_BITS;\r
+      }\r
+    }\r
+  }\r
+\r
   return (UINT32)(UINTN)PageTable;\r
 }\r
 \r
@@ -860,6 +943,9 @@ InternalSmmStartupThisAp (
     DEBUG((DEBUG_ERROR, "CpuIndex(%d) == gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu\n", CpuIndex));\r
     return EFI_INVALID_PARAMETER;\r
   }\r
+  if (gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId == INVALID_APIC_ID) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
   if (!(*(mSmmMpSyncData->CpuData[CpuIndex].Present))) {\r
     if (mSmmMpSyncData->EffectiveSyncMode == SmmCpuSyncModeTradition) {\r
       DEBUG((DEBUG_ERROR, "!mSmmMpSyncData->CpuData[%d].Present\n", CpuIndex));\r
@@ -960,7 +1046,7 @@ CpuSmmDebugEntry (
   )\r
 {\r
   SMRAM_SAVE_STATE_MAP *CpuSaveState;\r
-  \r
+\r
   if (FeaturePcdGet (PcdCpuSmmDebug)) {\r
     ASSERT(CpuIndex < mMaxNumberOfCpus);\r
     CpuSaveState = (SMRAM_SAVE_STATE_MAP *)gSmmCpuPrivate->CpuSaveState[CpuIndex];\r
@@ -1186,7 +1272,6 @@ InitializeSmmCpuSemaphores (
   UINTN                      TotalSize;\r
   UINTN                      GlobalSemaphoresSize;\r
   UINTN                      CpuSemaphoresSize;\r
-  UINTN                      MsrSemahporeSize;\r
   UINTN                      SemaphoreSize;\r
   UINTN                      Pages;\r
   UINTN                      *SemaphoreBlock;\r
@@ -1196,8 +1281,7 @@ InitializeSmmCpuSemaphores (
   ProcessorCount = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
   GlobalSemaphoresSize = (sizeof (SMM_CPU_SEMAPHORE_GLOBAL) / sizeof (VOID *)) * SemaphoreSize;\r
   CpuSemaphoresSize    = (sizeof (SMM_CPU_SEMAPHORE_CPU) / sizeof (VOID *)) * ProcessorCount * SemaphoreSize;\r
-  MsrSemahporeSize     = MSR_SPIN_LOCK_INIT_NUM * SemaphoreSize;\r
-  TotalSize = GlobalSemaphoresSize + CpuSemaphoresSize + MsrSemahporeSize;\r
+  TotalSize = GlobalSemaphoresSize + CpuSemaphoresSize;\r
   DEBUG((EFI_D_INFO, "One Semaphore Size    = 0x%x\n", SemaphoreSize));\r
   DEBUG((EFI_D_INFO, "Total Semaphores Size = 0x%x\n", TotalSize));\r
   Pages = EFI_SIZE_TO_PAGES (TotalSize);\r
@@ -1217,8 +1301,6 @@ InitializeSmmCpuSemaphores (
   mSmmCpuSemaphores.SemaphoreGlobal.CodeAccessCheckLock\r
                                                   = (SPIN_LOCK *)SemaphoreAddr;\r
   SemaphoreAddr += SemaphoreSize;\r
-  mSmmCpuSemaphores.SemaphoreGlobal.MemoryMappedLock\r
-                                                  = (SPIN_LOCK *)SemaphoreAddr;\r
 \r
   SemaphoreAddr = (UINTN)SemaphoreBlock + GlobalSemaphoresSize;\r
   mSmmCpuSemaphores.SemaphoreCpu.Busy    = (SPIN_LOCK *)SemaphoreAddr;\r
@@ -1227,15 +1309,8 @@ InitializeSmmCpuSemaphores (
   SemaphoreAddr += ProcessorCount * SemaphoreSize;\r
   mSmmCpuSemaphores.SemaphoreCpu.Present = (BOOLEAN *)SemaphoreAddr;\r
 \r
-  SemaphoreAddr = (UINTN)SemaphoreBlock + GlobalSemaphoresSize + CpuSemaphoresSize;\r
-  mSmmCpuSemaphores.SemaphoreMsr.Msr              = (SPIN_LOCK *)SemaphoreAddr;\r
-  mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter =\r
-        ((UINTN)SemaphoreBlock + Pages * SIZE_4KB - SemaphoreAddr) / SemaphoreSize;\r
-  ASSERT (mSmmCpuSemaphores.SemaphoreMsr.AvailableCounter >= MSR_SPIN_LOCK_INIT_NUM);\r
-\r
   mPFLock                       = mSmmCpuSemaphores.SemaphoreGlobal.PFLock;\r
   mConfigSmmCodeAccessCheckLock = mSmmCpuSemaphores.SemaphoreGlobal.CodeAccessCheckLock;\r
-  mMemoryMappedLock             = mSmmCpuSemaphores.SemaphoreGlobal.MemoryMappedLock;\r
 \r
   mSemaphoreSize = SemaphoreSize;\r
 }\r
@@ -1308,6 +1383,13 @@ InitializeMpServiceData (
   UINTN                     Index;\r
   UINT8                     *GdtTssTables;\r
   UINTN                     GdtTableStepSize;\r
+  CPUID_VERSION_INFO_EDX    RegEdx;\r
+\r
+  //\r
+  // Determine if this CPU supports machine check\r
+  //\r
+  AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx.Uint32);\r
+  mMachineCheckSupported = (BOOLEAN)(RegEdx.Bits.MCA == 1);\r
 \r
   //\r
   // Allocate memory for all locks and semaphores\r