From: "Ankur Arora" <ankur.a.arora@oracle.com>
To: devel@edk2.groups.io
Cc: lersek@redhat.com, imammedo@redhat.com,
boris.ostrovsky@oracle.com,
Ankur Arora <ankur.a.arora@oracle.com>,
Jordan Justen <jordan.l.justen@intel.com>,
Ard Biesheuvel <ard.biesheuvel@arm.com>,
Aaron Young <aaron.young@oracle.com>
Subject: [PATCH v5 7/9] OvmfPkg/CpuHotplugSmm: add CpuEject()
Date: Mon, 25 Jan 2021 22:44:38 -0800 [thread overview]
Message-ID: <20210126064440.299596-8-ankur.a.arora@oracle.com> (raw)
In-Reply-To: <20210126064440.299596-1-ankur.a.arora@oracle.com>
Add CpuEject(), which handles the CPU ejection, and provides
a holding area for said CPUs. It is called via
SmmCpuFeaturesRendezvousExit(), at the tail end of the SMI
handling.
Also UnplugCpus() now stashes APIC IDs of CPUs which need to
be ejected in CPU_HOT_EJECT_DATA.ApicIdMap. These are used by
CpuEject() to identify such CPUs.
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 | 94 +++++++++++++++++++++++++++++++++++++-
1 file changed, 93 insertions(+), 1 deletion(-)
diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
index d165d6ccea0d..99e6845a12d9 100644
--- a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
+++ b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
@@ -14,6 +14,7 @@
#include <Library/MmServicesTableLib.h> // gMmst
#include <Library/PcdLib.h> // PcdGetBool()
#include <Library/SafeIntLib.h> // SafeUintnSub()
+#include <Library/CpuHotEjectData.h> // CPU_HOT_EJECT_DATA
#include <Protocol/MmCpuIo.h> // EFI_MM_CPU_IO_PROTOCOL
#include <Protocol/SmmCpuService.h> // EFI_SMM_CPU_SERVICE_PROTOCOL
#include <Uefi/UefiBaseType.h> // EFI_STATUS
@@ -32,11 +33,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 serve as 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.
@@ -182,6 +184,43 @@ Fatal:
}
/**
+ CPU Hot-eject handler function.
+
+ If the executing CPU is not being ejected: NOP.
+ If the executing CPU is being ejected: wait in a CpuDeadLoop()
+ until ejected.
+
+ @param[in] ProcessorNum Index of executing CPU.
+**/
+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;
+ }
+
+ //
+ // CPU(s) being unplugged get here from SmmCpuFeaturesSmiRendezvousExit()
+ // after having been cleared to exit the SMI by the monarch and thus have
+ // no SMM processing remaining.
+ //
+ // Given that we cannot allow them to escape to the guest, we pen them
+ // here until the SMM monarch tells the HW to unplug them.
+ //
+ CpuDeadLoop ();
+}
+
+/**
CPU Hot-unplug MMI handler function.
@param[in] UnplugApicIds List of APIC IDs to be unplugged.
@@ -203,9 +242,11 @@ UnplugCpus(
{
EFI_STATUS Status;
UINT32 ToUnplugIdx;
+ UINT32 EjectCount;
UINTN ProcessorNum;
ToUnplugIdx = 0;
+ EjectCount = 0;
while (ToUnplugIdx < ToUnplugCount) {
APIC_ID RemoveApicId;
@@ -242,11 +283,35 @@ UnplugCpus(
DEBUG ((DEBUG_ERROR, "%a: RemoveProcessor(" FMT_APIC_ID "): %r\n",
__FUNCTION__, RemoveApicId, Status));
goto Fatal;
+ } else {
+ //
+ // Stash the APIC IDs so we can do the actual unplug later.
+ //
+ if (mCpuHotEjectData->ApicIdMap[ProcessorNum] != CPU_EJECT_INVALID) {
+ //
+ // Since ProcessorNum and APIC-ID map 1-1, so a valid
+ // mCpuHotEjectData->ApicIdMap[ProcessorNum] means something
+ // is horribly wrong.
+ //
+ DEBUG ((DEBUG_ERROR, "%a: ProcessorNum %u maps to %llx, cannot map to " FMT_APIC_ID "\n",
+ __FUNCTION__, ProcessorNum, mCpuHotEjectData->ApicIdMap[ProcessorNum], RemoveApicId));
+ goto Fatal;
+ }
+
+ mCpuHotEjectData->ApicIdMap[ProcessorNum] = (UINT64)RemoveApicId;
+ EjectCount++;
}
ToUnplugIdx++;
}
+ if (EjectCount != 0) {
+ //
+ // We have processors to be ejected; install the handler.
+ //
+ mCpuHotEjectData->Handler = CpuEject;
+ }
+
//
// We've handled this unplug.
//
@@ -445,7 +510,13 @@ CpuHotplugEntry (
// Our DEPEX on EFI_SMM_CPU_SERVICE_PROTOCOL guarantees that PiSmmCpuDxeSmm
// has pointed PcdCpuHotPlugDataAddress to CPU_HOT_PLUG_DATA in SMRAM.
//
+ // Additionally, CPU Hot-unplug 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);
+ mCpuHotEjectData = (VOID *)(UINTN)PcdGet64 (PcdCpuHotEjectDataAddress);
+
if (mCpuHotPlugData == NULL) {
Status = EFI_NOT_FOUND;
DEBUG ((DEBUG_ERROR, "%a: CPU_HOT_PLUG_DATA: %r\n", __FUNCTION__, Status));
@@ -457,6 +528,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.
//
@@ -539,6 +613,24 @@ CpuHotplugEntry (
//
SmbaseInstallFirstSmiHandler ();
+ if (mCpuHotEjectData) {
+ UINT32 Idx;
+ //
+ // For CPU ejection we need to map ProcessorNum -> APIC_ID. By the time
+ // we do that, however, the Processor's APIC ID has already been removed
+ // from SMM data structures. So we will use mCpuHotEjectData->ApicIdMap
+ // to map from ProcessorNum -> APIC_ID.
+ //
+ for (Idx = 0; Idx < mCpuHotEjectData->ArrayLength; Idx++) {
+ mCpuHotEjectData->ApicIdMap[Idx] = CPU_EJECT_INVALID;
+ }
+
+ //
+ // Wait to init the handler until an ejection is warranted
+ //
+ mCpuHotEjectData->Handler = NULL;
+ }
+
return EFI_SUCCESS;
ReleasePostSmmPen:
--
2.9.3
next prev parent reply other threads:[~2021-01-26 6:45 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-01-26 6:44 [PATCH v5 0/9] support CPU hot-unplug Ankur Arora
2021-01-26 6:44 ` [PATCH v5 1/9] OvmfPkg/CpuHotplugSmm: refactor hotplug logic Ankur Arora
2021-01-26 19:01 ` Laszlo Ersek
2021-01-26 19:04 ` Laszlo Ersek
2021-01-26 19:09 ` Laszlo Ersek
2021-01-26 19:15 ` Ankur Arora
2021-01-26 21:07 ` Laszlo Ersek
2021-01-26 21:17 ` Ankur Arora
2021-01-26 21:32 ` Laszlo Ersek
2021-01-26 22:53 ` Ankur Arora
2021-01-26 6:44 ` [PATCH v5 2/9] OvmfPkg/CpuHotplugSmm: collect hot-unplug events Ankur Arora
2021-01-26 6:44 ` [PATCH v5 3/9] OvmfPkg/CpuHotplugSmm: add Qemu Cpu Status helper Ankur Arora
2021-01-26 6:44 ` [PATCH v5 4/9] OvmfPkg/CpuHotplugSmm: introduce UnplugCpus() Ankur Arora
2021-01-26 6:44 ` [PATCH v5 5/9] OvmfPkg/CpuHotplugSmm: define CPU_HOT_EJECT_DATA Ankur Arora
2021-01-26 6:44 ` [PATCH v5 6/9] OvmfPkg/SmmCpuFeaturesLib: init CPU ejection state Ankur Arora
2021-01-26 6:44 ` Ankur Arora [this message]
2021-01-26 6:44 ` [PATCH v5 8/9] OvmfPkg/CpuHotplugSmm: add worker to do CPU ejection Ankur Arora
2021-01-26 6:44 ` [PATCH v5 9/9] OvmfPkg/SmmControl2Dxe: negotiate CPU hot-unplug Ankur Arora
2021-01-26 18:03 ` [edk2-devel] [PATCH v5 0/9] support " Laszlo Ersek
2021-01-26 20:09 ` Ankur Arora
2021-01-26 18:18 ` Laszlo Ersek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210126064440.299596-8-ankur.a.arora@oracle.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox