]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
UefiCpuPkg/PiSmmCpuDxeSmm: Using CPU semaphores in aligned buffer
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.c
index e210c8d44659357e02e6989021148e57842e287c..8b3bb343ce10e4d1bc59c7675107c0aa65131a8d 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
 Agent Module to load other modules to deploy SMM Entry Vector for X86 CPU.\r
 \r
-Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\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
@@ -76,13 +76,6 @@ EFI_SMM_CPU_PROTOCOL  mSmmCpu  = {
 \r
 EFI_CPU_INTERRUPT_HANDLER   mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];\r
 \r
-///\r
-/// SMM CPU Save State Protocol instance\r
-///\r
-EFI_SMM_CPU_SAVE_STATE_PROTOCOL  mSmmCpuSaveState = {\r
-  NULL\r
-};\r
-\r
 //\r
 // SMM stack information\r
 //\r
@@ -111,7 +104,7 @@ BOOLEAN                  mSmmCodeAccessCheckEnable = FALSE;
 //\r
 // Spin lock used to serialize setting of SMM Code Access Check feature\r
 //\r
-SPIN_LOCK                mConfigSmmCodeAccessCheckLock;\r
+SPIN_LOCK                *mConfigSmmCodeAccessCheckLock = NULL;\r
 \r
 /**\r
   Initialize IDT to setup exception handlers for SMM.\r
@@ -253,7 +246,7 @@ SmmReadSaveState (
     // the pseudo register value for EFI_SMM_SAVE_STATE_REGISTER_PROCESSOR_ID is returned in Buffer.\r
     // Otherwise, EFI_NOT_FOUND is returned.\r
     //\r
-    if (mSmmMpSyncData->CpuData[CpuIndex].Present) {\r
+    if (*(mSmmMpSyncData->CpuData[CpuIndex].Present)) {\r
       *(UINT64 *)Buffer = gSmmCpuPrivate->ProcessorInfo[CpuIndex].ProcessorId;\r
       return EFI_SUCCESS;\r
     } else {\r
@@ -261,7 +254,7 @@ SmmReadSaveState (
     }\r
   }\r
 \r
-  if (!mSmmMpSyncData->CpuData[CpuIndex].Present) {\r
+  if (!(*(mSmmMpSyncData->CpuData[CpuIndex].Present))) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -530,18 +523,13 @@ SmmRestoreCpu (
   }\r
 \r
   //\r
-  // Do below CPU things for native platform only\r
+  // Skip initialization if mAcpiCpuData is not valid\r
   //\r
-  if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {\r
+  if (mAcpiCpuData.NumberOfCpus > 0) {\r
     //\r
-    // Skip initialization if mAcpiCpuData is not valid\r
+    // First time microcode load and restore MTRRs\r
     //\r
-    if (mAcpiCpuData.NumberOfCpus > 0) {\r
-      //\r
-      // First time microcode load and restore MTRRs\r
-      //\r
-      EarlyInitializeCpu ();\r
-    }\r
+    EarlyInitializeCpu ();\r
   }\r
 \r
   //\r
@@ -550,18 +538,13 @@ SmmRestoreCpu (
   SmmRelocateBases ();\r
 \r
   //\r
-  // Do below CPU things for native platform only\r
+  // Skip initialization if mAcpiCpuData is not valid\r
   //\r
-  if (!FeaturePcdGet(PcdFrameworkCompatibilitySupport)) {\r
+  if (mAcpiCpuData.NumberOfCpus > 0) {\r
     //\r
-    // Skip initialization if mAcpiCpuData is not valid\r
+    // Restore MSRs for BSP and all APs\r
     //\r
-    if (mAcpiCpuData.NumberOfCpus > 0) {\r
-      //\r
-      // Restore MSRs for BSP and all APs\r
-      //\r
-      InitializeCpu ();\r
-    }\r
+    InitializeCpu ();\r
   }\r
 \r
   //\r
@@ -686,13 +669,6 @@ SmmReadyToLockEventNotify (
   //\r
   mAcpiCpuData.NumberOfCpus = 0;\r
 \r
-  //\r
-  // If FrameworkCompatibilitySspport is enabled, then do not copy CPU S3 Data into SMRAM\r
-  //\r
-  if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
-    goto Done;\r
-  }\r
-\r
   //\r
   // If PcdCpuS3DataAddress was never set, then do not copy CPU S3 Data into SMRAM\r
   //\r
@@ -784,6 +760,9 @@ PiCpuSmmEntry (
   UINTN                      NumberOfEnabledProcessors;\r
   UINTN                      Index;\r
   VOID                       *Buffer;\r
+  UINTN                      BufferPages;\r
+  UINTN                      TileCodeSize;\r
+  UINTN                      TileDataSize;\r
   UINTN                      TileSize;\r
   VOID                       *GuidHob;\r
   EFI_SMRAM_DESCRIPTOR       *SmramDescriptor;\r
@@ -934,13 +913,18 @@ PiCpuSmmEntry (
   //\r
   // Retrieve CPU Family\r
   //\r
-  AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);\r
+  AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);\r
   FamilyId = (RegEax >> 8) & 0xf;\r
   ModelId = (RegEax >> 4) & 0xf;\r
   if (FamilyId == 0x06 || FamilyId == 0x0f) {\r
     ModelId = ModelId | ((RegEax >> 12) & 0xf0);\r
   }\r
 \r
+  RegEdx = 0;\r
+  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);\r
+  if (RegEax >= CPUID_EXTENDED_CPU_SIG) {\r
+    AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);\r
+  }\r
   //\r
   // Determine the mode of the CPU at the time an SMI occurs\r
   //   Intel(R) 64 and IA-32 Architectures Software Developer's Manual\r
@@ -961,9 +945,13 @@ PiCpuSmmEntry (
   // specific context in a PROCESSOR_SMM_DESCRIPTOR, and the SMI entry point.  This size\r
   // is rounded up to nearest power of 2.\r
   //\r
-  TileSize = sizeof (SMRAM_SAVE_STATE_MAP) + sizeof (PROCESSOR_SMM_DESCRIPTOR) + GetSmiHandlerSize () - 1;\r
+  TileCodeSize = GetSmiHandlerSize ();\r
+  TileCodeSize = ALIGN_VALUE(TileCodeSize, SIZE_4KB);\r
+  TileDataSize = sizeof (SMRAM_SAVE_STATE_MAP) + sizeof (PROCESSOR_SMM_DESCRIPTOR);\r
+  TileDataSize = ALIGN_VALUE(TileDataSize, SIZE_4KB);\r
+  TileSize = TileDataSize + TileCodeSize - 1;\r
   TileSize = 2 * GetPowerOfTwo32 ((UINT32)TileSize);\r
-  DEBUG ((EFI_D_INFO, "SMRAM TileSize = %08x\n", TileSize));\r
+  DEBUG ((EFI_D_INFO, "SMRAM TileSize = 0x%08x (0x%08x, 0x%08x)\n", TileSize, TileCodeSize, TileDataSize));\r
 \r
   //\r
   // If the TileSize is larger than space available for the SMI Handler of CPU[i],\r
@@ -985,12 +973,14 @@ PiCpuSmmEntry (
   // Intel486 processors: FamilyId is 4\r
   // Pentium processors : FamilyId is 5\r
   //\r
+  BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));\r
   if ((FamilyId == 4) || (FamilyId == 5)) {\r
-    Buffer = AllocateAlignedPages (EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)), SIZE_32KB);\r
+    Buffer = AllocateAlignedPages (BufferPages, SIZE_32KB);\r
   } else {\r
-    Buffer = AllocatePages (EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1)));\r
+    Buffer = AllocateAlignedPages (BufferPages, SIZE_4KB);\r
   }\r
   ASSERT (Buffer != NULL);\r
+  DEBUG ((EFI_D_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE(BufferPages)));\r
 \r
   //\r
   // Allocate buffer for pointers to array in  SMM_CPU_PRIVATE_DATA.\r
@@ -1009,7 +999,6 @@ PiCpuSmmEntry (
 \r
   mSmmCpuPrivateData.SmmCoreEntryContext.CpuSaveStateSize = gSmmCpuPrivate->CpuSaveStateSize;\r
   mSmmCpuPrivateData.SmmCoreEntryContext.CpuSaveState     = gSmmCpuPrivate->CpuSaveState;\r
-  mSmmCpuSaveState.CpuSaveState = (EFI_SMM_CPU_STATE **)gSmmCpuPrivate->CpuSaveState;\r
 \r
   //\r
   // Allocate buffer for pointers to array in CPU_HOT_PLUG_DATA.\r
@@ -1150,25 +1139,6 @@ PiCpuSmmEntry (
   Status = InitializeSmmCpuServices (mSmmCpuHandle);\r
   ASSERT_EFI_ERROR (Status);\r
 \r
-  if (FeaturePcdGet (PcdFrameworkCompatibilitySupport)) {\r
-    //\r
-    // Install Framework SMM Save State Protocol into UEFI protocol database for backward compatibility\r
-    //\r
-    Status = SystemTable->BootServices->InstallMultipleProtocolInterfaces (\r
-                                          &gSmmCpuPrivate->SmmCpuHandle,\r
-                                          &gEfiSmmCpuSaveStateProtocolGuid,\r
-                                          &mSmmCpuSaveState,\r
-                                          NULL\r
-                                          );\r
-    ASSERT_EFI_ERROR (Status);\r
-    //\r
-    // The SmmStartupThisAp service in Framework SMST should always be non-null.\r
-    // Update SmmStartupThisAp pointer in PI SMST here so that PI/Framework SMM thunk\r
-    // can have it ready when constructing Framework SMST.\r
-    //\r
-    gSmst->SmmStartupThisAp = SmmStartupThisAp;\r
-  }\r
-\r
   //\r
   // register SMM Ready To Lock Protocol notification\r
   //\r
@@ -1353,9 +1323,9 @@ ConfigSmmCodeAccessCheckOnCurrentProcessor (
   NewSmmFeatureControlMsr = SmmFeatureControlMsr;\r
   if (mSmmCodeAccessCheckEnable) {\r
     NewSmmFeatureControlMsr |= SMM_CODE_CHK_EN_BIT;\r
-  }\r
-  if (FeaturePcdGet (PcdCpuSmmFeatureControlMsrLock)) {\r
-    NewSmmFeatureControlMsr |= SMM_FEATURE_CONTROL_LOCK_BIT;\r
+    if (FeaturePcdGet (PcdCpuSmmFeatureControlMsrLock)) {\r
+      NewSmmFeatureControlMsr |= SMM_FEATURE_CONTROL_LOCK_BIT;\r
+    }\r
   }\r
 \r
   //\r
@@ -1368,7 +1338,7 @@ ConfigSmmCodeAccessCheckOnCurrentProcessor (
   //\r
   // Release the spin lock user to serialize the updates to the SMM Feature Control MSR\r
   //\r
-  ReleaseSpinLock (&mConfigSmmCodeAccessCheckLock);\r
+  ReleaseSpinLock (mConfigSmmCodeAccessCheckLock);\r
 }\r
 \r
 /**\r
@@ -1386,7 +1356,7 @@ ConfigSmmCodeAccessCheck (
   //\r
   // Check to see if the Feature Control MSR is supported on this CPU\r
   //\r
-  Index = gSmst->CurrentlyExecutingCpu;\r
+  Index = gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu;\r
   if (!SmmCpuFeaturesIsSmmRegisterSupported (Index, SmmRegFeatureControl)) {\r
     mSmmCodeAccessCheckEnable = FALSE;\r
     return;\r
@@ -1398,26 +1368,19 @@ ConfigSmmCodeAccessCheck (
   //\r
   if ((AsmReadMsr64 (EFI_MSR_SMM_MCA_CAP) & SMM_CODE_ACCESS_CHK_BIT) == 0) {\r
     mSmmCodeAccessCheckEnable = FALSE;\r
-  }\r
-\r
-  //\r
-  // If the SMM Code Access Check feature is disabled and the Feature Control MSR\r
-  // is not being locked, then no additional work is required\r
-  //\r
-  if (!mSmmCodeAccessCheckEnable && !FeaturePcdGet (PcdCpuSmmFeatureControlMsrLock)) {\r
     return;\r
   }\r
 \r
   //\r
   // Initialize the lock used to serialize the MSR programming in BSP and all APs\r
   //\r
-  InitializeSpinLock (&mConfigSmmCodeAccessCheckLock);\r
+  InitializeSpinLock (mConfigSmmCodeAccessCheckLock);\r
 \r
   //\r
   // Acquire Config SMM Code Access Check spin lock.  The BSP will release the\r
   // spin lock when it is done executing ConfigSmmCodeAccessCheckOnCurrentProcessor().\r
   //\r
-  AcquireSpinLock (&mConfigSmmCodeAccessCheckLock);\r
+  AcquireSpinLock (mConfigSmmCodeAccessCheckLock);\r
 \r
   //\r
   // Enable SMM Code Access Check feature on the BSP.\r
@@ -1428,13 +1391,13 @@ ConfigSmmCodeAccessCheck (
   // Enable SMM Code Access Check feature for the APs.\r
   //\r
   for (Index = 0; Index < gSmst->NumberOfCpus; Index++) {\r
-    if (Index != gSmst->CurrentlyExecutingCpu) {\r
+    if (Index != gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu) {\r
 \r
       //\r
       // Acquire Config SMM Code Access Check spin lock.  The AP will release the\r
       // spin lock when it is done executing ConfigSmmCodeAccessCheckOnCurrentProcessor().\r
       //\r
-      AcquireSpinLock (&mConfigSmmCodeAccessCheckLock);\r
+      AcquireSpinLock (mConfigSmmCodeAccessCheckLock);\r
 \r
       //\r
       // Call SmmStartupThisAp() to enable SMM Code Access Check on an AP.\r
@@ -1445,18 +1408,47 @@ ConfigSmmCodeAccessCheck (
       //\r
       // Wait for the AP to release the Config SMM Code Access Check spin lock.\r
       //\r
-      while (!AcquireSpinLockOrFail (&mConfigSmmCodeAccessCheckLock)) {\r
+      while (!AcquireSpinLockOrFail (mConfigSmmCodeAccessCheckLock)) {\r
         CpuPause ();\r
       }\r
 \r
       //\r
       // Release the Config SMM Code Access Check spin lock.\r
       //\r
-      ReleaseSpinLock (&mConfigSmmCodeAccessCheckLock);\r
+      ReleaseSpinLock (mConfigSmmCodeAccessCheckLock);\r
     }\r
   }\r
 }\r
 \r
+/**\r
+  This API provides a way to allocate memory for page table.\r
+\r
+  This API can be called more once to allocate memory for page tables.\r
+\r
+  Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the\r
+  allocated buffer.  The buffer returned is aligned on a 4KB boundary.  If Pages is 0, then NULL\r
+  is returned.  If there is not enough memory remaining to satisfy the request, then NULL is\r
+  returned.\r
+\r
+  @param  Pages                 The number of 4 KB pages to allocate.\r
+\r
+  @return A pointer to the allocated buffer or NULL if allocation fails.\r
+\r
+**/\r
+VOID *\r
+AllocatePageTableMemory (\r
+  IN UINTN           Pages\r
+  )\r
+{\r
+  VOID  *Buffer;\r
+\r
+  Buffer = SmmCpuFeaturesAllocatePageTableMemory (Pages);\r
+  if (Buffer != NULL) {\r
+    return Buffer;\r
+  }\r
+  return AllocatePages (Pages);\r
+}\r
+\r
 /**\r
   Perform the remaining tasks.\r
 \r
@@ -1482,9 +1474,44 @@ PerformRemainingTasks (
     //\r
     ConfigSmmCodeAccessCheck ();\r
 \r
+    SmmCpuFeaturesCompleteSmmReadyToLock ();\r
+\r
     //\r
     // Clean SMM ready to lock flag\r
     //\r
     mSmmReadyToLock = FALSE;\r
   }\r
 }\r
+\r
+/**\r
+  Perform the pre tasks.\r
+\r
+**/\r
+VOID\r
+PerformPreTasks (\r
+  VOID\r
+  )\r
+{\r
+  //\r
+  // Restore SMM Configuration in S3 boot path.\r
+  //\r
+  if (mRestoreSmmConfigurationInS3) {\r
+    //\r
+    // Need make sure gSmst is correct because below function may use them.\r
+    //\r
+    gSmst->SmmStartupThisAp      = gSmmCpuPrivate->SmmCoreEntryContext.SmmStartupThisAp;\r
+    gSmst->CurrentlyExecutingCpu = gSmmCpuPrivate->SmmCoreEntryContext.CurrentlyExecutingCpu;\r
+    gSmst->NumberOfCpus          = gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus;\r
+    gSmst->CpuSaveStateSize      = gSmmCpuPrivate->SmmCoreEntryContext.CpuSaveStateSize;\r
+    gSmst->CpuSaveState          = gSmmCpuPrivate->SmmCoreEntryContext.CpuSaveState;\r
+\r
+    //\r
+    // Configure SMM Code Access Check feature if available.\r
+    //\r
+    ConfigSmmCodeAccessCheck ();\r
+\r
+    SmmCpuFeaturesCompleteSmmReadyToLock ();\r
+\r
+    mRestoreSmmConfigurationInS3 = FALSE;\r
+  }\r
+}\r