diff options
Diffstat (limited to 'UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c')
-rw-r--r-- | UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c | 166 |
1 files changed, 135 insertions, 31 deletions
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c index 6e795d1756..d2d0950f3b 100644 --- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c +++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c @@ -84,6 +84,8 @@ EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL mSmmMemoryAttribute = { EFI_CPU_INTERRUPT_HANDLER mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];
+BOOLEAN mSmmRelocated = FALSE;
+volatile BOOLEAN *mSmmInitialized = NULL;
UINT32 mBspApicId = 0;
//
@@ -383,10 +385,12 @@ SmmInitHandler ( InitializeMpSyncData ();
}
- //
- // Hook return after RSM to set SMM re-based flag
- //
- SemaphoreHook (Index, &mRebased[Index]);
+ if (!mSmmRelocated) {
+ //
+ // Hook return after RSM to set SMM re-based flag
+ //
+ SemaphoreHook (Index, &mRebased[Index]);
+ }
return;
}
@@ -396,6 +400,51 @@ SmmInitHandler ( }
/**
+ Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
+
+**/
+VOID
+ExecuteFirstSmiInit (
+ VOID
+ )
+{
+ UINTN Index;
+
+ if (mSmmInitialized == NULL) {
+ mSmmInitialized = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * mMaxNumberOfCpus);
+ }
+
+ ASSERT (mSmmInitialized != NULL);
+ if (mSmmInitialized == NULL) {
+ return;
+ }
+
+ //
+ // Reset the mSmmInitialized to false.
+ //
+ ZeroMem ((VOID *)mSmmInitialized, sizeof (BOOLEAN) * mMaxNumberOfCpus);
+
+ //
+ // Get the BSP ApicId.
+ //
+ mBspApicId = GetApicId ();
+
+ //
+ // Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) for SMM init
+ //
+ SendSmiIpi (mBspApicId);
+ SendSmiIpiAllExcludingSelf ();
+
+ //
+ // Wait for all processors to finish its 1st SMI
+ //
+ for (Index = 0; Index < mNumberOfCpus; Index++) {
+ while (!(BOOLEAN)mSmmInitialized[Index]) {
+ }
+ }
+}
+
+/**
Relocate SmmBases for each processor.
Execute on first boot and all S3 resumes
@@ -562,6 +611,11 @@ PiCpuSmmEntry ( UINTN FamilyId;
UINTN ModelId;
UINT32 Cr3;
+ EFI_HOB_GUID_TYPE *GuidHob;
+ SMM_BASE_HOB_DATA *SmmBaseHobData;
+
+ GuidHob = NULL;
+ SmmBaseHobData = NULL;
//
// Initialize address fixup
@@ -790,26 +844,54 @@ PiCpuSmmEntry ( ASSERT (TileSize <= (SMRAM_SAVE_STATE_MAP_OFFSET + sizeof (SMRAM_SAVE_STATE_MAP) - SMM_HANDLER_OFFSET));
//
- // Allocate buffer for all of the tiles.
- //
- // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
- // Volume 3C, Section 34.11 SMBASE Relocation
- // For Pentium and Intel486 processors, the SMBASE values must be
- // aligned on a 32-KByte boundary or the processor will enter shutdown
- // state during the execution of a RSM instruction.
- //
- // Intel486 processors: FamilyId is 4
- // Pentium processors : FamilyId is 5
+ // Retrive the allocated SmmBase from gSmmBaseHobGuid. If found,
+ // means the SmBase relocation has been done.
//
- BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));
- if ((FamilyId == 4) || (FamilyId == 5)) {
- Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB);
+ GuidHob = GetFirstGuidHob (&gSmmBaseHobGuid);
+ if (GuidHob != NULL) {
+ //
+ // Check whether the Required TileSize is enough.
+ //
+ if (TileSize > SIZE_8KB) {
+ DEBUG ((DEBUG_ERROR, "The Range of Smbase in SMRAM is not enough -- Required TileSize = 0x%08x, Actual TileSize = 0x%08x\n", TileSize, SIZE_8KB));
+ CpuDeadLoop ();
+ return RETURN_BUFFER_TOO_SMALL;
+ }
+
+ SmmBaseHobData = GET_GUID_HOB_DATA (GuidHob);
+
+ //
+ // Assume single instance of HOB produced, expect the HOB.NumberOfProcessors equals to the mMaxNumberOfCpus.
+ //
+ ASSERT (SmmBaseHobData->NumberOfProcessors == (UINT32)mMaxNumberOfCpus && SmmBaseHobData->ProcessorIndex == 0);
+ mSmmRelocated = TRUE;
} else {
- Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);
- }
+ //
+ // When the HOB doesn't exist, allocate new SMBASE itself.
+ //
+ DEBUG ((DEBUG_INFO, "PiCpuSmmEntry: gSmmBaseHobGuid not found!\n"));
+ //
+ // Allocate buffer for all of the tiles.
+ //
+ // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+ // Volume 3C, Section 34.11 SMBASE Relocation
+ // For Pentium and Intel486 processors, the SMBASE values must be
+ // aligned on a 32-KByte boundary or the processor will enter shutdown
+ // state during the execution of a RSM instruction.
+ //
+ // Intel486 processors: FamilyId is 4
+ // Pentium processors : FamilyId is 5
+ //
+ BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));
+ if ((FamilyId == 4) || (FamilyId == 5)) {
+ Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB);
+ } else {
+ Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);
+ }
- ASSERT (Buffer != NULL);
- DEBUG ((DEBUG_INFO, "SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages)));
+ ASSERT (Buffer != NULL);
+ DEBUG ((DEBUG_INFO, "New Allcoated SMRAM SaveState Buffer (0x%08x, 0x%08x)\n", Buffer, EFI_PAGES_TO_SIZE (BufferPages)));
+ }
//
// Allocate buffer for pointers to array in SMM_CPU_PRIVATE_DATA.
@@ -844,7 +926,8 @@ PiCpuSmmEntry ( // size for each CPU in the platform
//
for (Index = 0; Index < mMaxNumberOfCpus; Index++) {
- mCpuHotPlugData.SmBase[Index] = (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET;
+ mCpuHotPlugData.SmBase[Index] = mSmmRelocated ? (UINTN)SmmBaseHobData->SmBase[Index] : (UINTN)Buffer + Index * TileSize - SMM_HANDLER_OFFSET;
+
gSmmCpuPrivate->CpuSaveStateSize[Index] = sizeof (SMRAM_SAVE_STATE_MAP);
gSmmCpuPrivate->CpuSaveState[Index] = (VOID *)(mCpuHotPlugData.SmBase[Index] + SMRAM_SAVE_STATE_MAP_OFFSET);
gSmmCpuPrivate->Operation[Index] = SmmCpuNone;
@@ -957,17 +1040,23 @@ PiCpuSmmEntry ( InitializeSmmIdt ();
//
- // Relocate SMM Base addresses to the ones allocated from SMRAM
+ // Check whether Smm Relocation is done or not.
+ // If not, will do the SmmBases Relocation here!!!
//
- mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus);
- ASSERT (mRebased != NULL);
- SmmRelocateBases ();
+ if (!mSmmRelocated) {
+ //
+ // Relocate SMM Base addresses to the ones allocated from SMRAM
+ //
+ mRebased = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus);
+ ASSERT (mRebased != NULL);
+ SmmRelocateBases ();
- //
- // Call hook for BSP to perform extra actions in normal mode after all
- // SMM base addresses have been relocated on all CPUs
- //
- SmmCpuFeaturesSmmRelocationComplete ();
+ //
+ // Call hook for BSP to perform extra actions in normal mode after all
+ // SMM base addresses have been relocated on all CPUs
+ //
+ SmmCpuFeaturesSmmRelocationComplete ();
+ }
DEBUG ((DEBUG_INFO, "mXdSupported - 0x%x\n", mXdSupported));
@@ -999,6 +1088,21 @@ PiCpuSmmEntry ( }
//
+ // For relocated SMBASE, some MSRs & CSRs are still required to be configured in SMM Mode for SMM Initialization.
+ // Those MSRs & CSRs must be configured before normal SMI sources happen.
+ // So, here is to issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) to execute first SMI init.
+ //
+ if (mSmmRelocated) {
+ ExecuteFirstSmiInit ();
+
+ //
+ // Call hook for BSP to perform extra actions in normal mode after all
+ // SMM base addresses have been relocated on all CPUs
+ //
+ SmmCpuFeaturesSmmRelocationComplete ();
+ }
+
+ //
// Fill in SMM Reserved Regions
//
gSmmCpuPrivate->SmmReservedSmramRegion[0].SmramReservedStart = 0;
|