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

Ankur Arora posted 10 patches 3 years, 10 months ago
There is a newer version of this series
[edk2-devel] [PATCH v3 06/10] OvmfPkg/CpuHotplugSmm: support CPU eject
Posted by Ankur Arora 3 years, 10 months ago
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@redhat.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Cc: Igor Mammedov <imammedo@redhat.com>
Cc: Boris Ostrovsky <boris.ostrovsky@oracle.com>
Cc: Aaron Young <aaron.young@oracle.com>
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=3132
Signed-off-by: Ankur Arora <ankur.a.arora@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/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-