[edk2-devel] [PATCH v1] UefiCpuPkg: Support SMM Relocated SmBase handling

Wu, Jiaxin posted 1 patch 1 year, 4 months ago
Failed in applying to current master (apply log)
There is a newer version of this series
UefiCpuPkg/Include/Guid/SmmRelocationInfoHob.h     |  36 +++
.../Library/SmmCpuFeaturesLib/CpuFeaturesLib.h     |   1 +
.../SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c     |  29 +-
.../SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf        |   3 +
.../SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf     |   1 +
.../StandaloneMmCpuFeaturesLib.inf                 |   3 +
UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c                  |  23 +-
UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c              |  60 ++++-
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c         | 292 +++++++++++++--------
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h         |  11 +-
UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf       |   1 +
UefiCpuPkg/UefiCpuPkg.dec                          |   3 +
12 files changed, 338 insertions(+), 125 deletions(-)
create mode 100644 UefiCpuPkg/Include/Guid/SmmRelocationInfoHob.h
[edk2-devel] [PATCH v1] UefiCpuPkg: Support SMM Relocated SmBase handling
Posted by Wu, Jiaxin 1 year, 4 months ago
Mainly changes as below:
1. Add Smm Relocation Info HOB, which is used to store the information of
Smm Relocated SmBase array for each Processors;
2. Combine 2 SMIs (SmmInitHandler & gcSmiHandlerTemplate) into one
(gcSmiHandlerTemplate), the new SMI handler needs to run to 2 paths: one
to SmmCpuFeaturesInitializeProcessor(), the other to SMM Core Entry Point.
3. Issue SMI IPI (All Excluding Self SMM IPI + BSP SMM IPI) for SMM init
before normal SMI sources happen.
4. Call SmmCpuFeaturesInitializeProcessor() in parallel.

Change-Id: Iec7bf25166bfeefb44a202285465a35b5debbce4
Cc: Eric Dong <eric.dong@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Zeng Star <star.zeng@intel.com>
Signed-off-by: Jiaxin Wu <jiaxin.wu@intel.com>
---
 UefiCpuPkg/Include/Guid/SmmRelocationInfoHob.h     |  36 +++
 .../Library/SmmCpuFeaturesLib/CpuFeaturesLib.h     |   1 +
 .../SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c     |  29 +-
 .../SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf        |   3 +
 .../SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf     |   1 +
 .../StandaloneMmCpuFeaturesLib.inf                 |   3 +
 UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c                  |  23 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c              |  60 ++++-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c         | 292 +++++++++++++--------
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h         |  11 +-
 UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf       |   1 +
 UefiCpuPkg/UefiCpuPkg.dec                          |   3 +
 12 files changed, 338 insertions(+), 125 deletions(-)
 create mode 100644 UefiCpuPkg/Include/Guid/SmmRelocationInfoHob.h

diff --git a/UefiCpuPkg/Include/Guid/SmmRelocationInfoHob.h b/UefiCpuPkg/Include/Guid/SmmRelocationInfoHob.h
new file mode 100644
index 0000000000..a612537975
--- /dev/null
+++ b/UefiCpuPkg/Include/Guid/SmmRelocationInfoHob.h
@@ -0,0 +1,36 @@
+/** @file
+  The Smm Relocation Info HOB is used to store the information of:
+    A. Smm Relocated SmBase array for each Processors;
+
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SMM_RELOCATION_INFO_HOB_H_
+#define _SMM_RELOCATION_INFO_HOB_H_
+
+#include <Protocol/MpService.h>
+#include <PiPei.h>
+
+#define SMM_RELOCATION_INFO_HOB_DATA_GUID \
+  { \
+    0xc2217ba7, 0x03bb, 0x4f63, {0xa6, 0x47, 0x7c, 0x25, 0xc5, 0xfc, 0x9d, 0x73}  \
+  }
+
+#pragma pack(1)
+typedef struct {
+  ///
+  /// Describes the Number of all max supported processors.
+  ///
+  UINT64                  NumberOfProcessors;
+  ///
+  /// Pointer to SmBase array for each Processors.
+  ///
+  UINT64                  SmBase[];
+} SMM_RELOCATION_INFO_HOB_DATA;
+#pragma pack()
+
+extern EFI_GUID  gSmmRelocationInfoHobGuid;
+
+#endif
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h b/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h
index fd3e902547..cf82b89d5e 100644
--- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/CpuFeaturesLib.h
@@ -7,10 +7,11 @@
 **/
 
 #ifndef CPU_FEATURES_LIB_H_
 #define CPU_FEATURES_LIB_H_
 
+#include <Guid/SmmRelocationInfoHob.h>
 #include <Library/SmmCpuFeaturesLib.h>
 #include <Library/BaseLib.h>
 #include <Library/PcdLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/DebugLib.h>
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c b/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c
index d5eaaa7a99..862ff921f9 100644
--- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/IntelSmmCpuFeaturesLib.c
@@ -36,10 +36,15 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 // Set default value to assume IA-32 Architectural MSRs are used
 //
 UINT32  mSmrrPhysBaseMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSBASE;
 UINT32  mSmrrPhysMaskMsr = SMM_FEATURES_LIB_IA32_SMRR_PHYSMASK;
 
+//
+// Indicate Smm Relocation done or not
+//
+BOOLEAN                  mSmmRelocationDone;
+
 //
 // Set default value to assume MTRRs need to be configured on each SMI
 //
 BOOLEAN  mNeedConfigureMtrrs = TRUE;
 
@@ -63,10 +68,14 @@ CpuFeaturesLibInitialization (
   UINT32  RegEax;
   UINT32  RegEdx;
   UINTN   FamilyId;
   UINTN   ModelId;
 
+  EFI_HOB_GUID_TYPE* GuidHob;
+
+  GuidHob = NULL;
+
   //
   // Retrieve CPU Family and Model
   //
   AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, &RegEdx);
   FamilyId = (RegEax >> 8) & 0xf;
@@ -142,10 +151,18 @@ CpuFeaturesLibInitialization (
   //
   // Allocate array for state of SMRR enable on all CPUs
   //
   mSmrrEnabled = (BOOLEAN *)AllocatePool (sizeof (BOOLEAN) * GetCpuMaxLogicalProcessorNumber ());
   ASSERT (mSmrrEnabled != NULL);
+
+  //
+  // If gSmmRelocationInfoHobGuid found, means Smm Relocation has been done.
+  //
+  GuidHob = GetFirstGuidHob (&gSmmRelocationInfoHobGuid);
+  if (GuidHob != NULL) {
+    mSmmRelocationDone = TRUE;
+  }
 }
 
 /**
   Called during the very first SMI into System Management Mode to initialize
   CPU features, including SMBASE, for the currently executing CPU.  Since this
@@ -184,15 +201,17 @@ SmmCpuFeaturesInitializeProcessor (
   UINT32                RegEax;
   UINT32                RegEdx;
   UINTN                 FamilyId;
   UINTN                 ModelId;
 
-  //
-  // Configure SMBASE.
-  //
-  CpuState             = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
-  CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+  if (!mSmmRelocationDone) {
+    //
+    // Configure SMBASE.
+    //
+    CpuState             = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
+    CpuState->x86.SMBASE = (UINT32)CpuHotPlugData->SmBase[CpuIndex];
+  }
 
   //
   // Intel(R) 64 and IA-32 Architectures Software Developer's Manual
   // Volume 3C, Section 35.2 MSRs in the Intel(R) Core(TM) 2 Processor Family
   //
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
index 9ac7dde78f..082e142580 100644
--- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLib.inf
@@ -32,10 +32,13 @@
   BaseLib
   PcdLib
   MemoryAllocationLib
   DebugLib
 
+[Guids]
+  gSmmRelocationInfoHobGuid                ## CONSUMES
+
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
 
 [FeaturePcd]
   gUefiCpuPkgTokenSpaceGuid.PcdSmrrEnable  ## CONSUMES
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
index 86d367e0a0..a9d9ab4972 100644
--- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/SmmCpuFeaturesLibStm.inf
@@ -62,10 +62,11 @@
 
 [Guids]
   gMsegSmramGuid                           ## SOMETIMES_CONSUMES ## HOB
   gEfiAcpi20TableGuid                      ## SOMETIMES_CONSUMES ## SystemTable
   gEfiAcpi10TableGuid                      ## SOMETIMES_CONSUMES ## SystemTable
+  gSmmRelocationInfoHobGuid                ## CONSUMES
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMsegSize                         ## SOMETIMES_CONSUMES
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmStmExceptionStackSize         ## SOMETIMES_CONSUMES
diff --git a/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf b/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
index b1f60a5505..3a23e62be3 100644
--- a/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
+++ b/UefiCpuPkg/Library/SmmCpuFeaturesLib/StandaloneMmCpuFeaturesLib.inf
@@ -33,10 +33,13 @@
   BaseLib
   DebugLib
   MemoryAllocationLib
   PcdLib
 
+[Guids]
+  gSmmRelocationInfoHobGuid                ## CONSUMES
+
 [FixedPcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber        ## SOMETIMES_CONSUMES
 
 [FeaturePcd]
   gUefiCpuPkgTokenSpaceGuid.PcdSmrrEnable  ## CONSUMES
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
index fb4a44eab6..32eaa62fd4 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/CpuS3.c
@@ -765,10 +765,13 @@ SmmRestoreCpu (
   SMM_S3_RESUME_STATE       *SmmS3ResumeState;
   IA32_DESCRIPTOR           Ia32Idtr;
   IA32_DESCRIPTOR           X64Idtr;
   IA32_IDT_GATE_DESCRIPTOR  IdtEntryTable[EXCEPTION_VECTOR_NUMBER];
   EFI_STATUS                Status;
+  EFI_HOB_GUID_TYPE*        GuidHob;
+
+  GuidHob = NULL;
 
   DEBUG ((DEBUG_INFO, "SmmRestoreCpu()\n"));
 
   mSmmS3Flag = TRUE;
 
@@ -822,13 +825,29 @@ SmmRestoreCpu (
     //
     InitializeCpuBeforeRebase ();
   }
 
   //
-  // Restore SMBASE for BSP and all APs
+  // Retrive the allocated SmmBase from gSmmRelocationInfoHobGuid
+  //
+  GuidHob = GetFirstGuidHob (&gSmmRelocationInfoHobGuid);
+  if (GuidHob != NULL) {
+    mSmmRelocated = TRUE;
+  } else {
+    mSmmRelocated = FALSE;
+  }
+
   //
-  SmmRelocateBases ();
+  // Check whether Smm Relocation is done or not.
+  // If not, will do the SmmBases Relocation here!!!
+  //
+  if (!mSmmRelocated) {
+    //
+    // Restore SMBASE for BSP and all APs
+    //
+    SmmRelocateBases ();
+  }
 
   //
   // Skip initialization if mAcpiCpuData is not valid
   //
   if (mAcpiCpuData.NumberOfCpus > 0) {
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
index a0967eb69c..bc670c1baa 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/MpService.c
@@ -1700,10 +1700,45 @@ CpuSmmDebugExit (
       CpuSaveState->x64._DR6 = AsmReadDr6 ();
     }
   }
 }
 
+/**
+  Perform SmbaseRelocationPostSmmInit for CpuIndex, this should be done before
+  normal SMI sources happen.
+
+  @param[in] CpuIndex             CPU Index
+
+**/
+VOID
+SmbaseRelocationPostSmmInit (
+  IN      UINTN     CpuIndex
+  )
+{
+  //
+  // Update SMM IDT entries' code segment and load IDT
+  //
+  AsmWriteIdtr (&gcSmiIdtr);
+
+  //
+  // Initialize SMM specific features on the currently executing CPU
+  //
+  SmmCpuFeaturesInitializeProcessor (
+    CpuIndex,
+    (mBspApicId == GetApicId ()) ? TRUE : FALSE,
+    gSmmCpuPrivate->ProcessorInfo,
+    &mCpuHotPlugData
+    );
+
+  if (!mSmmS3Flag) {
+    //
+    // Check XD and BTS features on each processor on normal boot
+    //
+    CheckFeatureSupported ();
+  }
+}
+
 /**
   C function for SMI entry, each processor comes here upon SMI trigger.
 
   @param    CpuIndex              CPU Index
 
@@ -1728,10 +1763,29 @@ SmiRendezvous (
   // when using on-demand paging for above 4G memory.
   //
   Cr2 = 0;
   SaveCr2 (&Cr2);
 
+  if (mSmmRelocated && !mSmmInitialized[CpuIndex]) {
+    //
+    // Perform SmbaseRelocationPostSmmInit for CpuIndex
+    //
+    SmbaseRelocationPostSmmInit (CpuIndex);
+
+    //
+    // Restore Cr2
+    //
+    RestoreCr2 (Cr2);
+
+    //
+    // Mark the first SMI init for CpuIndex has been done so as to avoid the reentry.
+    //
+    mSmmInitialized[CpuIndex] = TRUE;
+
+    return;
+  }
+
   //
   // Call the user register Startup function first.
   //
   if (mSmmMpSyncData->StartupProcedure != NULL) {
     mSmmMpSyncData->StartupProcedure (mSmmMpSyncData->StartupProcArgs);
@@ -1882,13 +1936,13 @@ Exit:
   //
   RestoreCr2 (Cr2);
 }
 
 /**
-  Initialize PackageBsp Info. Processor specified by mPackageFirstThreadIndex[PackageIndex]
-  will do the package-scope register programming. Set default CpuIndex to (UINT32)-1, which
-  means not specified yet.
+  Initialize mPackageFirstThreadIndex Info. Processor specified by mPackageFirstThreadIndex[PackageIndex]
+  will do the package-scope register programming. Set default CpuIndex to (UINT32)-1, which means not
+  specified yet.
 
 **/
 VOID
 InitPackageFirstThreadIndexInfo (
   VOID
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
index 655175a2c6..c8606f3bd4 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.c
@@ -83,10 +83,14 @@ EDKII_SMM_MEMORY_ATTRIBUTE_PROTOCOL  mSmmMemoryAttribute = {
   EdkiiSmmClearMemoryAttributes
 };
 
 EFI_CPU_INTERRUPT_HANDLER  mExternalVectorTable[EXCEPTION_VECTOR_NUMBER];
 
+BOOLEAN                    mSmmRelocated = FALSE;
+BOOLEAN                    *mSmmInitialized = NULL;
+UINT32                     mBspApicId = 0;
+
 //
 // SMM stack information
 //
 UINTN  mSmmStackArrayBase;
 UINTN  mSmmStackArrayEnd;
@@ -543,28 +547,33 @@ EFIAPI
 PiCpuSmmEntry (
   IN EFI_HANDLE        ImageHandle,
   IN EFI_SYSTEM_TABLE  *SystemTable
   )
 {
-  EFI_STATUS                Status;
-  EFI_MP_SERVICES_PROTOCOL  *MpServices;
-  UINTN                     NumberOfEnabledProcessors;
-  UINTN                     Index;
-  VOID                      *Buffer;
-  UINTN                     BufferPages;
-  UINTN                     TileCodeSize;
-  UINTN                     TileDataSize;
-  UINTN                     TileSize;
-  UINT8                     *Stacks;
-  VOID                      *Registration;
-  UINT32                    RegEax;
-  UINT32                    RegEbx;
-  UINT32                    RegEcx;
-  UINT32                    RegEdx;
-  UINTN                     FamilyId;
-  UINTN                     ModelId;
-  UINT32                    Cr3;
+  EFI_STATUS                   Status;
+  EFI_MP_SERVICES_PROTOCOL     *MpServices;
+  UINTN                        NumberOfEnabledProcessors;
+  UINTN                        Index;
+  VOID                         *Buffer;
+  UINTN                        BufferPages;
+  UINTN                        TileCodeSize;
+  UINTN                        TileDataSize;
+  UINTN                        TileSize;
+  UINT8                        *Stacks;
+  VOID                         *Registration;
+  UINT32                       RegEax;
+  UINT32                       RegEbx;
+  UINT32                       RegEcx;
+  UINT32                       RegEdx;
+  UINTN                        FamilyId;
+  UINTN                        ModelId;
+  UINT32                       Cr3;
+  EFI_HOB_GUID_TYPE*           GuidHob;
+  SMM_RELOCATION_INFO_HOB_DATA *SmmRelocationInfoHobData;
+
+  GuidHob = NULL;
+  SmmRelocationInfoHobData = NULL;
 
   //
   // Initialize address fixup
   //
   PiSmmCpuSmmInitFixupAddress ();
@@ -634,18 +643,80 @@ PiCpuSmmEntry (
     mMaxNumberOfCpus = mNumberOfCpus;
   }
 
   gSmmCpuPrivate->SmmCoreEntryContext.NumberOfCpus = mMaxNumberOfCpus;
 
+  //
+  // Retrieve CPU Family
+  //
+  AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
+  FamilyId = (RegEax >> 8) & 0xf;
+  ModelId  = (RegEax >> 4) & 0xf;
+  if ((FamilyId == 0x06) || (FamilyId == 0x0f)) {
+    ModelId = ModelId | ((RegEax >> 12) & 0xf0);
+  }
+
+  RegEdx = 0;
+  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
+  if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
+    AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
+  }
+
+  //
+  // Determine the mode of the CPU at the time an SMI occurs
+  //   Intel(R) 64 and IA-32 Architectures Software Developer's Manual
+  //   Volume 3C, Section 34.4.1.1
+  //
+  mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;
+  if ((RegEdx & BIT29) != 0) {
+    mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
+  }
+
+  if (FamilyId == 0x06) {
+    if ((ModelId == 0x17) || (ModelId == 0x0f) || (ModelId == 0x1c)) {
+      mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
+    }
+  }
+
+  DEBUG ((DEBUG_INFO, "PcdControlFlowEnforcementPropertyMask = %d\n", PcdGet32 (PcdControlFlowEnforcementPropertyMask)));
+  if (PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) {
+    AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL);
+    if (RegEax >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {
+      AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, &RegEdx);
+      DEBUG ((DEBUG_INFO, "CPUID[7/0] ECX - 0x%08x\n", RegEcx));
+      DEBUG ((DEBUG_INFO, "  CET_SS  - 0x%08x\n", RegEcx & CPUID_CET_SS));
+      DEBUG ((DEBUG_INFO, "  CET_IBT - 0x%08x\n", RegEdx & CPUID_CET_IBT));
+      if ((RegEcx & CPUID_CET_SS) == 0) {
+        mCetSupported = FALSE;
+        PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+      }
+
+      if (mCetSupported) {
+        AsmCpuidEx (CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF, NULL, &RegEbx, &RegEcx, NULL);
+        DEBUG ((DEBUG_INFO, "CPUID[D/1] EBX - 0x%08x, ECX - 0x%08x\n", RegEbx, RegEcx));
+        AsmCpuidEx (CPUID_EXTENDED_STATE, 11, &RegEax, NULL, &RegEcx, NULL);
+        DEBUG ((DEBUG_INFO, "CPUID[D/11] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));
+        AsmCpuidEx (CPUID_EXTENDED_STATE, 12, &RegEax, NULL, &RegEcx, NULL);
+        DEBUG ((DEBUG_INFO, "CPUID[D/12] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));
+      }
+    } else {
+      mCetSupported = FALSE;
+      PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+    }
+  } else {
+    mCetSupported = FALSE;
+    PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
+  }
+
   //
   // The CPU save state and code for the SMI entry point are tiled within an SMRAM
   // allocated buffer.  The minimum size of this buffer for a uniprocessor system
-  // is 32 KB, because the entry point is SMBASE + 32KB, and CPU save state area
-  // just below SMBASE + 64KB.  If more than one CPU is present in the platform,
+  // is 32 KB, because the entry point is SMBASE + 32KB (8000h), and CPU save state area
+  // just below SMBASE + 64KB (from FC00 to FFFFh).  If more than one CPU is present in the platform,
   // then the SMI entry point and the CPU save state areas can be tiles to minimize
   // the total amount SMRAM required for all the CPUs.  The tile size can be computed
-  // by adding the   // CPU save state size, any extra CPU specific context, and
+  // by adding the CPU save state size, any extra CPU specific context, and
   // the size of code that must be placed at the SMI entry point to transfer
   // control to a C function in the native SMM execution mode.  This size is
   // rounded up to the nearest power of 2 to give the tile size for a each CPU.
   // The total amount of memory required is the maximum number of CPUs that
   // platform supports times the tile size.  The picture below shows the tiling,
@@ -657,11 +728,11 @@ PiCpuSmmEntry (
   //  |   CPU m+1 Extra Data        |
   //  +-----------------------------+
   //  |   Padding                   |
   //  +-----------------------------+
   //  |   CPU 2m  SMI Entry         |
-  //  +#############################+  <-- Base of allocated buffer + 64 KB
+  //  +#############################+
   //  |   CPU m-1 Save State        |
   //  +-----------------------------+
   //  |   CPU m-1 Extra Data        |
   //  +-----------------------------+
   //  |   Padding                   |
@@ -675,19 +746,19 @@ PiCpuSmmEntry (
   //  |   CPU 2 Extra Data          |
   //  +-----------------------------+
   //  |   Padding                   |
   //  +-----------------------------+
   //  |   CPU m+1 SMI Entry         |
-  //  +=============================+  <-- Base of allocated buffer + 32 KB
+  //  +=============================+  <-- Base of allocated buffer + 32 KB + TileSize
   //  |   CPU 1 Save State          |
   //  +-----------------------------+
   //  |   CPU 1 Extra Data          |
   //  +-----------------------------+
   //  |   Padding                   |
   //  +-----------------------------+
   //  |   CPU m SMI Entry           |
-  //  +#############################+  <-- Base of allocated buffer + 32 KB == CPU 0 SMBASE + 64 KB
+  //  +#############################+  <-- Base of allocated buffer + 32 KB (0x8000) == CPU 0 SMBASE + 64 KB
   //  |   CPU 0 Save State          |
   //  +-----------------------------+
   //  |   CPU 0 Extra Data          |
   //  +-----------------------------+
   //  |   Padding                   |
@@ -703,73 +774,10 @@ PiCpuSmmEntry (
   //  |   Padding                   |
   //  +-----------------------------+
   //  |   CPU 0 SMI Entry           |
   //  +#############################+  <-- Base of allocated buffer == CPU 0 SMBASE + 32 KB
   //
-
-  //
-  // Retrieve CPU Family
-  //
-  AsmCpuid (CPUID_VERSION_INFO, &RegEax, NULL, NULL, NULL);
-  FamilyId = (RegEax >> 8) & 0xf;
-  ModelId  = (RegEax >> 4) & 0xf;
-  if ((FamilyId == 0x06) || (FamilyId == 0x0f)) {
-    ModelId = ModelId | ((RegEax >> 12) & 0xf0);
-  }
-
-  RegEdx = 0;
-  AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL);
-  if (RegEax >= CPUID_EXTENDED_CPU_SIG) {
-    AsmCpuid (CPUID_EXTENDED_CPU_SIG, NULL, NULL, NULL, &RegEdx);
-  }
-
-  //
-  // Determine the mode of the CPU at the time an SMI occurs
-  //   Intel(R) 64 and IA-32 Architectures Software Developer's Manual
-  //   Volume 3C, Section 34.4.1.1
-  //
-  mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_32BIT;
-  if ((RegEdx & BIT29) != 0) {
-    mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
-  }
-
-  if (FamilyId == 0x06) {
-    if ((ModelId == 0x17) || (ModelId == 0x0f) || (ModelId == 0x1c)) {
-      mSmmSaveStateRegisterLma = EFI_SMM_SAVE_STATE_REGISTER_LMA_64BIT;
-    }
-  }
-
-  DEBUG ((DEBUG_INFO, "PcdControlFlowEnforcementPropertyMask = %d\n", PcdGet32 (PcdControlFlowEnforcementPropertyMask)));
-  if (PcdGet32 (PcdControlFlowEnforcementPropertyMask) != 0) {
-    AsmCpuid (CPUID_SIGNATURE, &RegEax, NULL, NULL, NULL);
-    if (RegEax >= CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS) {
-      AsmCpuidEx (CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS, CPUID_STRUCTURED_EXTENDED_FEATURE_FLAGS_SUB_LEAF_INFO, NULL, NULL, &RegEcx, &RegEdx);
-      DEBUG ((DEBUG_INFO, "CPUID[7/0] ECX - 0x%08x\n", RegEcx));
-      DEBUG ((DEBUG_INFO, "  CET_SS  - 0x%08x\n", RegEcx & CPUID_CET_SS));
-      DEBUG ((DEBUG_INFO, "  CET_IBT - 0x%08x\n", RegEdx & CPUID_CET_IBT));
-      if ((RegEcx & CPUID_CET_SS) == 0) {
-        mCetSupported = FALSE;
-        PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
-      }
-
-      if (mCetSupported) {
-        AsmCpuidEx (CPUID_EXTENDED_STATE, CPUID_EXTENDED_STATE_SUB_LEAF, NULL, &RegEbx, &RegEcx, NULL);
-        DEBUG ((DEBUG_INFO, "CPUID[D/1] EBX - 0x%08x, ECX - 0x%08x\n", RegEbx, RegEcx));
-        AsmCpuidEx (CPUID_EXTENDED_STATE, 11, &RegEax, NULL, &RegEcx, NULL);
-        DEBUG ((DEBUG_INFO, "CPUID[D/11] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));
-        AsmCpuidEx (CPUID_EXTENDED_STATE, 12, &RegEax, NULL, &RegEcx, NULL);
-        DEBUG ((DEBUG_INFO, "CPUID[D/12] EAX - 0x%08x, ECX - 0x%08x\n", RegEax, RegEcx));
-      }
-    } else {
-      mCetSupported = FALSE;
-      PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
-    }
-  } else {
-    mCetSupported = FALSE;
-    PatchInstructionX86 (mPatchCetSupported, mCetSupported, 1);
-  }
-
   //
   // Compute tile size of buffer required to hold the CPU SMRAM Save State Map, extra CPU
   // specific context start starts at SMBASE + SMM_PSD_OFFSET, and the SMI entry point.
   // This size is rounded up to nearest power of 2.
   //
@@ -789,30 +797,51 @@ PiCpuSmmEntry (
   // context must be reduced.
   //
   ASSERT (TileSize <= (SMRAM_SAVE_STATE_MAP_OFFSET + sizeof (SMRAM_SAVE_STATE_MAP) - SMM_HANDLER_OFFSET));
 
   //
-  // Allocate buffer for all of the tiles.
+  // Check whether the Required TileSize is enough.
   //
-  // 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.
+  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));
+    ASSERT (TileSize <= SIZE_8KB);
+    return RETURN_BUFFER_TOO_SMALL;
+  }
+
   //
-  // Intel486 processors: FamilyId is 4
-  // Pentium processors : FamilyId is 5
+  // Retrive the allocated SmmBase from gSmmRelocationInfoHobGuid
   //
-  BufferPages = EFI_SIZE_TO_PAGES (SIZE_32KB + TileSize * (mMaxNumberOfCpus - 1));
-  if ((FamilyId == 4) || (FamilyId == 5)) {
-    Buffer = AllocateAlignedCodePages (BufferPages, SIZE_32KB);
+  GuidHob = GetFirstGuidHob (&gSmmRelocationInfoHobGuid);
+  if (GuidHob != NULL) {
+    SmmRelocationInfoHobData = GET_GUID_HOB_DATA (GuidHob);
+
+    ASSERT (SmmRelocationInfoHobData->NumberOfProcessors == mMaxNumberOfCpus);
+    mSmmRelocated = TRUE;
   } else {
-    Buffer = AllocateAlignedCodePages (BufferPages, SIZE_4KB);
-  }
+    DEBUG ((DEBUG_INFO, "PiCpuStandaloneMmEntry: gSmmRelocationInfoHobGuid 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.
   //
   gSmmCpuPrivate->ProcessorInfo = (EFI_PROCESSOR_INFORMATION *)AllocatePool (sizeof (EFI_PROCESSOR_INFORMATION) * mMaxNumberOfCpus);
@@ -843,11 +872,12 @@ PiCpuSmmEntry (
   // Retrieve APIC ID of each enabled processor from the MP Services protocol.
   // Also compute the SMBASE address, CPU Save State address, and CPU Save state
   // 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 ? SmmRelocationInfoHobData->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;
 
     if (Index < mNumberOfCpus) {
@@ -956,21 +986,27 @@ PiCpuSmmEntry (
   // Initialize IDT
   //
   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));
 
   //
   // SMM Time initialization
@@ -997,10 +1033,42 @@ 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) for SMM init
+  //
+  if (mSmmRelocated) {
+    mSmmInitialized = (BOOLEAN *)AllocateZeroPool (sizeof (BOOLEAN) * mMaxNumberOfCpus);
+    ASSERT (mSmmInitialized != NULL);
+
+    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 (!mSmmInitialized[Index]) {
+      }
+    }
+
+    //
+    // 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;
   gSmmCpuPrivate->SmmReservedSmramRegion[0].SmramReservedSize  = 0;
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
index 5f0a38e400..4ccaba82f5 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.h
@@ -23,10 +23,11 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Protocol/MmMp.h>
 
 #include <Guid/AcpiS3Context.h>
 #include <Guid/MemoryAttributesTable.h>
 #include <Guid/PiSmmMemoryAttributesTable.h>
+#include <Guid/SmmRelocationInfoHob.h>
 
 #include <Library/BaseLib.h>
 #include <Library/IoLib.h>
 #include <Library/TimerLib.h>
 #include <Library/SynchronizationLib.h>
@@ -400,10 +401,14 @@ WriteSaveStateRegister (
   IN EFI_SMM_SAVE_STATE_REGISTER  Register,
   IN UINTN                        Width,
   IN CONST VOID                   *Buffer
   );
 
+extern BOOLEAN            mSmmRelocated;
+extern BOOLEAN            *mSmmInitialized;
+extern UINT32             mBspApicId;
+
 extern CONST UINT8        gcSmmInitTemplate[];
 extern CONST UINT16       gcSmmInitSize;
 X86_ASSEMBLY_PATCH_LABEL  gPatchSmmCr0;
 extern UINT32             mSmmCr0;
 X86_ASSEMBLY_PATCH_LABEL  gPatchSmmCr3;
@@ -1486,13 +1491,13 @@ RegisterStartupProcedure (
   IN     EFI_AP_PROCEDURE  Procedure,
   IN OUT VOID              *ProcedureArguments OPTIONAL
   );
 
 /**
-  Initialize PackageBsp Info. Processor specified by mPackageFirstThreadIndex[PackageIndex]
-  will do the package-scope register programming. Set default CpuIndex to (UINT32)-1, which
-  means not specified yet.
+  Initialize mPackageFirstThreadIndex Info. Processor specified by mPackageFirstThreadIndex[PackageIndex]
+  will do the package-scope register programming. Set default CpuIndex to (UINT32)-1, which means not
+  specified yet.
 
 **/
 VOID
 InitPackageFirstThreadIndexInfo (
   VOID
diff --git a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
index b4b327f60c..7b6f52ef6f 100644
--- a/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
+++ b/UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf
@@ -112,10 +112,11 @@
 
 [Guids]
   gEfiAcpiVariableGuid                     ## SOMETIMES_CONSUMES ## HOB # it is used for S3 boot.
   gEdkiiPiSmmMemoryAttributesTableGuid     ## CONSUMES ## SystemTable
   gEfiMemoryAttributesTableGuid            ## CONSUMES ## SystemTable
+  gSmmRelocationInfoHobGuid                ## CONSUMES
 
 [FeaturePcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmDebug                         ## CONSUMES
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmBlockStartupThisAp            ## CONSUMES
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmEnableBspElection             ## CONSUMES
diff --git a/UefiCpuPkg/UefiCpuPkg.dec b/UefiCpuPkg/UefiCpuPkg.dec
index cff239d528..d46791eb81 100644
--- a/UefiCpuPkg/UefiCpuPkg.dec
+++ b/UefiCpuPkg/UefiCpuPkg.dec
@@ -76,10 +76,13 @@
   gEdkiiCpuFeaturesInitDoneGuid  = { 0xc77c3a41, 0x61ab, 0x4143, { 0x98, 0x3e, 0x33, 0x39, 0x28, 0x6, 0x28, 0xe5 }}
 
   ## Include/Guid/MicrocodePatchHob.h
   gEdkiiMicrocodePatchHobGuid    = { 0xd178f11d, 0x8716, 0x418e, { 0xa1, 0x31, 0x96, 0x7d, 0x2a, 0xc4, 0x28, 0x43 }}
 
+  ## Include/Guid/SmmRelocationInfoHob.h
+  gSmmRelocationInfoHobGuid      = { 0xc2217ba7, 0x03bb, 0x4f63, {0xa6, 0x47, 0x7c, 0x25, 0xc5, 0xfc, 0x9d, 0x73 }}
+
 [Protocols]
   ## Include/Protocol/SmmCpuService.h
   gEfiSmmCpuServiceProtocolGuid   = { 0x1d202cab, 0xc8ab, 0x4d5c, { 0x94, 0xf7, 0x3c, 0xfc, 0xc0, 0xd3, 0xd3, 0x35 }}
   gEdkiiSmmCpuRendezvousProtocolGuid = { 0xaa00d50b, 0x4911, 0x428f, { 0xb9, 0x1a, 0xa5, 0x9d, 0xdb, 0x13, 0xe2, 0x4c }}
 
-- 
2.16.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#97748): https://edk2.groups.io/g/devel/message/97748
Mute This Topic: https://groups.io/mt/95858804/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-