[edk2-devel] [PATCH v3 06/10] OvmfPkg/CpuHotplugSmm: support CPU eject

Ankur Arora ankur.a.arora at oracle.com
Fri Jan 15 07:45:29 UTC 2021


PiSmmCpuDxeSmm exposes CPU_HOT_EJECT_DATA in SMRAM which we use as a
communication channel between the two CPU hot-unplug phases.

The first phase, unplug, happens by way of CpuHotplugMmi() where we
collect CPUs that need to be unplugged and mark them for removal in
SMM data structures.

The second phase, eject, via SmmCpuFeaturesRendezvousExit() does
the actual ejection once the CPU to be ejected is in the tail end
of its SMI handling.

This commit does not contain any of the ejection machinery, only
sets up state to enable us to do that.

Cc: Laszlo Ersek <lersek at redhat.com>
Cc: Jordan Justen <jordan.l.justen at intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel at arm.com>
Cc: Igor Mammedov <imammedo at redhat.com>
Cc: Boris Ostrovsky <boris.ostrovsky at oracle.com>
Cc: Aaron Young <aaron.young at oracle.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3132
Signed-off-by: Ankur Arora <ankur.a.arora at oracle.com>
---
 OvmfPkg/CpuHotplugSmm/CpuHotplug.c      | 49 +++++++++++++++++++++++++++++++--
 OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf |  1 +
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
index 38c71bc11864..f088049c7aef 100644
--- a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
+++ b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
@@ -32,11 +32,12 @@ STATIC EFI_MM_CPU_IO_PROTOCOL *mMmCpuIo;
 //
 STATIC EFI_SMM_CPU_SERVICE_PROTOCOL *mMmCpuService;
 //
-// This structure is a communication side-channel between the
+// These structures are communication side-channels between the
 // EFI_SMM_CPU_SERVICE_PROTOCOL consumer (i.e., this driver) and provider
 // (i.e., PiSmmCpuDxeSmm).
 //
 STATIC CPU_HOT_PLUG_DATA *mCpuHotPlugData;
+STATIC CPU_HOT_EJECT_DATA *mCpuHotEjectData;
 //
 // SMRAM arrays for fetching the APIC IDs of processors with pending events (of
 // known event types), for the time of just one MMI.
@@ -317,6 +318,23 @@ Fatal:
   return EFI_INTERRUPT_PENDING;
 }
 
+VOID
+EFIAPI
+CpuEject(
+  IN UINTN ProcessorNum
+   )
+{
+  //
+  // APIC ID is UINT32, but mCpuHotEjectData->ApicIdMap[] is UINT64
+  // so use UINT64 throughout.
+  //
+  UINT64 ApicId;
+
+  ApicId = mCpuHotEjectData->ApicIdMap[ProcessorNum];
+  if (ApicId == CPU_EJECT_INVALID) {
+    return;
+  }
+}
 
 //
 // Entry point function of this driver.
@@ -368,8 +386,14 @@ CpuHotplugEntry (
   // Our DEPEX on EFI_SMM_CPU_SERVICE_PROTOCOL guarantees that PiSmmCpuDxeSmm
   // has pointed PcdCpuHotPlugDataAddress to CPU_HOT_PLUG_DATA in SMRAM.
   //
+  // Additionally, CPU HotUnplug is available only if CPU HotPlug is, so the
+  // same DEPEX also guarantees that PcdCpuHotEjectDataAddress points
+  // to CPU_HOT_EJECT_DATA in SMRAM.
+  //
   mCpuHotPlugData = (VOID *)(UINTN)PcdGet64 (PcdCpuHotPlugDataAddress);
-  if (mCpuHotPlugData == NULL) {
+  mCpuHotEjectData = (VOID *)(UINTN)PcdGet64 (PcdCpuHotEjectDataAddress);
+
+  if (mCpuHotPlugData == NULL)  {
     Status = EFI_NOT_FOUND;
     DEBUG ((DEBUG_ERROR, "%a: CPU_HOT_PLUG_DATA: %r\n", __FUNCTION__, Status));
     goto Fatal;
@@ -380,6 +404,9 @@ CpuHotplugEntry (
   if (mCpuHotPlugData->ArrayLength == 1) {
     return EFI_UNSUPPORTED;
   }
+  ASSERT (mCpuHotEjectData &&
+          (mCpuHotPlugData->ArrayLength == mCpuHotEjectData->ArrayLength));
+
   //
   // Allocate the data structures that depend on the possible CPU count.
   //
@@ -462,6 +489,24 @@ CpuHotplugEntry (
   //
   SmbaseInstallFirstSmiHandler ();
 
+  if (mCpuHotEjectData) {
+  UINT32     Idx;
+    //
+    // To do CPU eject we need to map ProcessorNum -> APIC_ID. However, by the
+    // time CpuEject() is called (via SmmCpuFeaturesRendezvousExit()), we've
+    // already called RemoveProcessor() and so the APIC ID cannot be looked up
+    // from SMM data structures.
+    //
+    // So use mCpuHotEjectData->ApicIdMap to map from ProcessorNum -> APIC_ID.
+    //
+    // Initialize to known invalid values before installing the handler.
+    //
+    for (Idx = 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) {
+      mCpuHotEjectData->ApicIdMap[Idx] = CPU_EJECT_INVALID;
+    }
+    mCpuHotEjectData->Handler = CpuEject;
+  }
+
   return EFI_SUCCESS;
 
 ReleasePostSmmPen:
diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf b/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
index 04322b0d7855..51d022e10416 100644
--- a/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
+++ b/OvmfPkg/CpuHotplugSmm/CpuHotplugSmm.inf
@@ -54,6 +54,7 @@
 
 [Pcd]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuHotPlugDataAddress                ## CONSUMES
+  gUefiCpuPkgTokenSpaceGuid.PcdCpuHotEjectDataAddress               ## CONSUMES
   gUefiOvmfPkgTokenSpaceGuid.PcdQ35SmramAtDefaultSmbase             ## CONSUMES
 
 [FeaturePcd]
-- 
2.9.3



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#70377): https://edk2.groups.io/g/devel/message/70377
Mute This Topic: https://groups.io/mt/79697148/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-






More information about the edk2-devel-archive mailing list