]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
UefiCpuPkg/PiSmmCpuDxeSmm: Consume SMM Base Hob for SmBase info
[mirror_edk2.git] / UefiCpuPkg / PiSmmCpuDxeSmm / PiSmmCpuDxeSmm.c
index 2ac655d032816ba0e8064f56a2f103cd6e4a8ca1..d2d0950f3b42cc4a94fa184e205a155d5ab5dfd3 100644 (file)
@@ -59,7 +59,6 @@ SMM_CPU_PRIVATE_DATA  *gSmmCpuPrivate = &mSmmCpuPrivateData;
 // SMM Relocation variables\r
 //\r
 volatile BOOLEAN  *mRebased;\r
-volatile BOOLEAN  mIsBsp;\r
 \r
 ///\r
 /// Handle for the SMM CPU Protocol\r
@@ -85,6 +84,10 @@ EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL  mSmmMemoryAttribute = {
 \r
 EFI_CPU_INTERRUPT_HANDLER  mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];\r
 \r
+BOOLEAN           mSmmRelocated    = FALSE;\r
+volatile BOOLEAN  *mSmmInitialized = NULL;\r
+UINT32            mBspApicId       = 0;\r
+\r
 //\r
 // SMM stack information\r
 //\r
@@ -343,8 +346,9 @@ SmmInitHandler (
   VOID\r
   )\r
 {\r
-  UINT32  ApicId;\r
-  UINTN   Index;\r
+  UINT32   ApicId;\r
+  UINTN    Index;\r
+  BOOLEAN  IsBsp;\r
 \r
   //\r
   // Update SMM IDT entries' code segment and load IDT\r
@@ -352,6 +356,8 @@ SmmInitHandler (
   AsmWriteIdtr (&gcSmiIdtr);\r
   ApicId = GetApicId ();\r
 \r
+  IsBsp = (BOOLEAN)(mBspApicId == ApicId);\r
+\r
   ASSERT (mNumberOfCpus <= mMaxNumberOfCpus);\r
 \r
   for (Index = 0; Index < mNumberOfCpus; Index++) {\r
@@ -361,7 +367,7 @@ SmmInitHandler (
       //\r
       SmmCpuFeaturesInitializeProcessor (\r
         Index,\r
-        mIsBsp,\r
+        IsBsp,\r
         gSmmCpuPrivate->ProcessorInfo,\r
         &mCpuHotPlugData\r
         );\r
@@ -371,7 +377,7 @@ SmmInitHandler (
         // Check XD and BTS features on each processor on normal boot\r
         //\r
         CheckFeatureSupported ();\r
-      } else if (mIsBsp) {\r
+      } else if (IsBsp) {\r
         //\r
         // BSP rebase is already done above.\r
         // Initialize private data during S3 resume\r
@@ -379,10 +385,12 @@ SmmInitHandler (
         InitializeMpSyncData ();\r
       }\r
 \r
-      //\r
-      // Hook return after RSM to set SMM re-based flag\r
-      //\r
-      SemaphoreHook (Index, &mRebased[Index]);\r
+      if (!mSmmRelocated) {\r
+        //\r
+        // Hook return after RSM to set SMM re-based flag\r
+        //\r
+        SemaphoreHook (Index, &mRebased[Index]);\r
+      }\r
 \r
       return;\r
     }\r
@@ -391,6 +399,51 @@ SmmInitHandler (
   ASSERT (FALSE);\r
 }\r
 \r
+/**\r
+  Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.\r
+\r
+**/\r
+VOID\r
+ExecuteFirstSmiInit (\r
+  VOID\r
+  )\r
+{\r
+  UINTN  Index;\r
+\r
+  if (mSmmInitialized == NULL) {\r
+    mSmmInitialized = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * mMaxNumberOfCpus);\r
+  }\r
+\r
+  ASSERT (mSmmInitialized != NULL);\r
+  if (mSmmInitialized == NULL) {\r
+    return;\r
+  }\r
+\r
+  //\r
+  // Reset the mSmmInitialized to false.\r
+  //\r
+  ZeroMem ((VOID *)mSmmInitialized, sizeof (BOOLEAN) * mMaxNumberOfCpus);\r
+\r
+  //\r
+  // Get the BSP ApicId.\r
+  //\r
+  mBspApicId = GetApicId ();\r
+\r
+  //\r
+  // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) for SMM init\r
+  //\r
+  SendSmiIpi (mBspApicId);\r
+  SendSmiIpiAllExcludingSelf ();\r
+\r
+  //\r
+  // Wait for all processors to finish its 1st SMI\r
+  //\r
+  for (Index = 0; Index < mNumberOfCpus; Index++) {\r
+    while (!(BOOLEAN)mSmmInitialized[Index]) {\r
+    }\r
+  }\r
+}\r
+\r
 /**\r
   Relocate SmmBases for each processor.\r
 \r
@@ -407,7 +460,6 @@ SmmRelocateBases (
   SMRAM_SAVE_STATE_MAP  BakBuf2;\r
   SMRAM_SAVE_STATE_MAP  *CpuStatePtr;\r
   UINT8                 *U8Ptr;\r
-  UINT32                ApicId;\r
   UINTN                 Index;\r
   UINTN                 BspIndex;\r
 \r
@@ -448,17 +500,16 @@ SmmRelocateBases (
   //\r
   // Retrieve the local APIC ID of current processor\r
   //\r
-  ApicId = GetApicId ();\r
+  mBspApicId = GetApicId ();\r
 \r
   //\r
   // Relocate SM bases for all APs\r
   // This is APs' 1st SMI - rebase will be done here, and APs' default SMI handler will be overridden by gcSmmInitTemplate\r
   //\r
-  mIsBsp   = FALSE;\r
   BspIndex = (UINTN)-1;\r
   for (Index = 0; Index < mNumberOfCpus; Index++) {\r
     mRebased[Index] = FALSE;\r
-    if (ApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {\r
+    if (mBspApicId != (UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId) {\r
       SendSmiIpi ((UINT32)gSmmCpuPrivate->ProcessorInfo[Index].ProcessorId);\r
       //\r
       // Wait for this AP to finish its 1st SMI\r
@@ -477,8 +528,7 @@ SmmRelocateBases (
   // Relocate BSP's SMM base\r
   //\r
   ASSERT (BspIndex != (UINTN)-1);\r
-  mIsBsp = TRUE;\r
-  SendSmiIpi (ApicId);\r
+  SendSmiIpi (mBspApicId);\r
   //\r
   // Wait for the BSP to finish its 1st SMI\r
   //\r
@@ -561,6 +611,11 @@ PiCpuSmmEntry (
   UINTN                     FamilyId;\r
   UINTN                     ModelId;\r
   UINT32                    Cr3;\r
+  EFI_HOB_GUID_TYPE         *GuidHob;\r
+  SMM_BASE_HOB_DATA         *SmmBaseHobData;\r
+\r
+  GuidHob        = NULL;\r
+  SmmBaseHobData = NULL;\r
 \r
   //\r
   // Initialize address fixup\r
@@ -789,26 +844,54 @@ PiCpuSmmEntry (
   ASSERT (TileSize <= (SMRAM_SAVE_STATE_MAP_OFFSET + sizeof (SMRAM_SAVE_STATE_MAP) - SMM_HANDLER_OFFSET));\r
 \r
   //\r
-  // Allocate buffer for all of the tiles.\r
-  //\r
-  // Intel(R) 64 and IA-32 Architectures Software Developer's Manual\r
-  // Volume 3C, Section 34.11 SMBASE Relocation\r
-  //   For Pentium and Intel486 processors, the SMBASE values must be\r
-  //   aligned on a 32-KByte boundary or the processor will enter shutdown\r
-  //   state during the execution of a RSM instruction.\r
+  // Retrive the allocated SmmBase from gSmmBaseHobGuid. If found,\r
+  // means the SmBase relocation has been done.\r
   //\r
-  // 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 = AllocateAlignedCodePages (BufferPages, SIZE_32KB);\r
+  GuidHob = GetFirstGuidHob (&gSmmBaseHobGuid);\r
+  if (GuidHob != NULL) {\r
+    //\r
+    // Check whether the Required TileSize is enough.\r
+    //\r
+    if (TileSize > SIZE_8KB) {\r
+      DEBUG ((DEBUG_ERROR, "The Range of Smbase in SMRAM is not enough -- Required TileSize = 0x%08x, Actual TileSize = 0x%08x\n", TileSize, SIZE_8KB));\r
+      CpuDeadLoop ();\r
+      return RETURN_BUFFER_TOO_SMALL;\r
+    }\r
+\r
+    SmmBaseHobData = GET_GUID_HOB_DATA (GuidHob);\r
+\r
+    //\r
+    // Assume single instance of HOB produced, expect the HOB.NumberOfProcessors equals to the mMaxNumberOfCpus.\r
+    //\r
+    ASSERT (SmmBaseHobData->NumberOfProcessors == (UINT32)mMaxNumberOfCpus && SmmBaseHobData->ProcessorIndex == 0);\r
+    mSmmRelocated = TRUE;\r
   } else {\r
-    Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);\r
-  }\r
+    //\r
+    // When the HOB doesn't exist, allocate new SMBASE itself.\r
+    //\r
+    DEBUG ((DEBUG_INFO, "PiCpuSmmEntry: gSmmBaseHobGuid not found!\n"));\r
+    //\r
+    // Allocate buffer for all of the tiles.\r
+    //\r
+    // Intel(R) 64 and IA-32 Architectures Software Developer's Manual\r
+    // Volume 3C, Section 34.11 SMBASE Relocation\r
+    //   For Pentium and Intel486 processors, the SMBASE values must be\r
+    //   aligned on a 32-KByte boundary or the processor will enter shutdown\r
+    //   state during the execution of a RSM instruction.\r
+    //\r
+    // 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 = AllocateAlignedCodePages (BufferPages, SIZE_32KB);\r
+    } else {\r
+      Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);\r
+    }\r
 \r
-  ASSERT (Buffer != NULL);\r
-  DEBUG ((DEBUG_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages)));\r
+    ASSERT (Buffer != NULL);\r
+    DEBUG ((DEBUG_INFO, "New Allcoated SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages)));\r
+  }\r
 \r
   //\r
   // Allocate buffer for pointers to array in  SMM_CPU_PRIVATE_DATA.\r
@@ -843,7 +926,8 @@ PiCpuSmmEntry (
   // size for each CPU in the platform\r
   //\r
   for (Index = 0; Index < mMaxNumberOfCpus; Index++) {\r
-    mCpuHotPlugData.SmBase[Index]           = (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET;\r
+    mCpuHotPlugData.SmBase[Index] = mSmmRelocated ? (UINTN)SmmBaseHobData->SmBase[Index] : (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET;\r
+\r
     gSmmCpuPrivate->CpuSaveStateSize[Index] = sizeof (SMRAM_SAVE_STATE_MAP);\r
     gSmmCpuPrivate->CpuSaveState[Index]     = (VOID *)(mCpuHotPlugData.SmBase[Index] + SMRAM_SAVE_STATE_MAP_OFFSET);\r
     gSmmCpuPrivate->Operation[Index]        = SmmCpuNone;\r
@@ -956,17 +1040,23 @@ PiCpuSmmEntry (
   InitializeSmmIdt ();\r
 \r
   //\r
-  // Relocate SMM Base addresses to the ones allocated from SMRAM\r
+  // Check whether Smm Relocation is done or not.\r
+  // If not, will do the SmmBases Relocation here!!!\r
   //\r
-  mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus);\r
-  ASSERT (mRebased != NULL);\r
-  SmmRelocateBases ();\r
+  if (!mSmmRelocated) {\r
+    //\r
+    // Relocate SMM Base addresses to the ones allocated from SMRAM\r
+    //\r
+    mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus);\r
+    ASSERT (mRebased != NULL);\r
+    SmmRelocateBases ();\r
 \r
-  //\r
-  // Call hook for BSP to perform extra actions in normal mode after all\r
-  // SMM base addresses have been relocated on all CPUs\r
-  //\r
-  SmmCpuFeaturesSmmRelocationComplete ();\r
+    //\r
+    // Call hook for BSP to perform extra actions in normal mode after all\r
+    // SMM base addresses have been relocated on all CPUs\r
+    //\r
+    SmmCpuFeaturesSmmRelocationComplete ();\r
+  }\r
 \r
   DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));\r
 \r
@@ -997,6 +1087,21 @@ PiCpuSmmEntry (
     }\r
   }\r
 \r
+  //\r
+  // For relocated SMBASE, some MSRs & CSRs are still required to be configured in SMM Mode for SMM Initialization.\r
+  // Those MSRs & CSRs must be configured before normal SMI sources happen.\r
+  // So, here is to issue SMI IPI (All Excluding  Self SMM IPI + BSP SMM IPI) to execute first SMI init.\r
+  //\r
+  if (mSmmRelocated) {\r
+    ExecuteFirstSmiInit ();\r
+\r
+    //\r
+    // Call hook for BSP to perform extra actions in normal mode after all\r
+    // SMM base addresses have been relocated on all CPUs\r
+    //\r
+    SmmCpuFeaturesSmmRelocationComplete ();\r
+  }\r
+\r
   //\r
   // Fill in SMM Reserved Regions\r
   //\r