Blame SOURCES/edk2-OvmfPkg-CpuHotplugSmm-fix-CPU-hotplug-race-just-befo.patch

f60719
From 4e5edfcdf5986d9e0801a976a3aa558b5f370099 Mon Sep 17 00:00:00 2001
f60719
From: Laszlo Ersek <lersek@redhat.com>
f60719
Date: Thu, 27 Aug 2020 00:21:28 +0200
f60719
Subject: [PATCH 2/5] OvmfPkg/CpuHotplugSmm: fix CPU hotplug race just before
f60719
 SMI broadcast
f60719
MIME-Version: 1.0
f60719
Content-Type: text/plain; charset=UTF-8
f60719
Content-Transfer-Encoding: 8bit
f60719
f60719
RH-Author: Laszlo Ersek (lersek)
f60719
RH-MergeRequest: 1: [RHEL-8.4.0] complete the "VCPU hotplug with SMI" OVMF feature
f60719
RH-Commit: [2/3] ea3ff703dfb7bd4f77b6807f06c89e754cc9d980 (lersek/edk2)
f60719
RH-Bugzilla: 1849177
f60719
f60719
The "virsh setvcpus" (plural) command may hot-plug several VCPUs in quick
f60719
succession -- it means a series of "device_add" QEMU monitor commands,
f60719
back-to-back.
f60719
f60719
If a "device_add" occurs *just before* ACPI raises the broadcast SMI,
f60719
then:
f60719
f60719
- OVMF processes the hot-added CPU well.
f60719
f60719
- However, QEMU's post-SMI ACPI loop -- which clears the pending events
f60719
  for the hot-added CPUs that were collected before raising the SMI -- is
f60719
  unaware of the stray CPU. Thus, the pending event is not cleared for it.
f60719
f60719
As a result of the stuck event, at the next hot-plug, OVMF tries to re-add
f60719
(relocate for the 2nd time) the already-known CPU. At that time, the AP is
f60719
already in the normal edk2 SMM busy-wait however, so it doesn't respond to
f60719
the exchange that the BSP intends to do in SmbaseRelocate(). Thus the VM
f60719
gets stuck in SMM.
f60719
f60719
(Because of the above symptom, this is not considered a security patch; it
f60719
doesn't seem exploitable by a malicious guest OS.)
f60719
f60719
In CpuHotplugMmi(), skip the supposedly hot-added CPU if it's already
f60719
known. The post-SMI ACPI loop will clear the pending event for it this
f60719
time.
f60719
f60719
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
f60719
Cc: Igor Mammedov <imammedo@redhat.com>
f60719
Cc: Jordan Justen <jordan.l.justen@intel.com>
f60719
Cc: Philippe Mathieu-Daudé <philmd@redhat.com>
f60719
Fixes: bc498ac4ca7590479cfd91ad1bb8a36286b0dc21
f60719
Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=2929
f60719
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
f60719
Message-Id: <20200826222129.25798-2-lersek@redhat.com>
f60719
Reviewed-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
f60719
(cherry picked from commit 020bb4b46d6f6708bb3358e1c738109b7908f0de)
f60719
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
f60719
---
f60719
 OvmfPkg/CpuHotplugSmm/CpuHotplug.c | 19 +++++++++++++++++++
f60719
 1 file changed, 19 insertions(+)
f60719
f60719
diff --git a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
f60719
index 20e6bec04f..cfe698ed2b 100644
f60719
--- a/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
f60719
+++ b/OvmfPkg/CpuHotplugSmm/CpuHotplug.c
f60719
@@ -193,9 +193,28 @@ CpuHotplugMmi (
f60719
   NewSlot = 0;
f60719
   while (PluggedIdx < PluggedCount) {
f60719
     APIC_ID NewApicId;
f60719
+    UINT32  CheckSlot;
f60719
     UINTN   NewProcessorNumberByProtocol;
f60719
 
f60719
     NewApicId = mPluggedApicIds[PluggedIdx];
f60719
+
f60719
+    //
f60719
+    // Check if the supposedly hot-added CPU is already known to us.
f60719
+    //
f60719
+    for (CheckSlot = 0;
f60719
+         CheckSlot < mCpuHotPlugData->ArrayLength;
f60719
+         CheckSlot++) {
f60719
+      if (mCpuHotPlugData->ApicId[CheckSlot] == NewApicId) {
f60719
+        break;
f60719
+      }
f60719
+    }
f60719
+    if (CheckSlot < mCpuHotPlugData->ArrayLength) {
f60719
+      DEBUG ((DEBUG_VERBOSE, "%a: APIC ID " FMT_APIC_ID " was hot-plugged "
f60719
+        "before; ignoring it\n", __FUNCTION__, NewApicId));
f60719
+      PluggedIdx++;
f60719
+      continue;
f60719
+    }
f60719
+
f60719
     //
f60719
     // Find the first empty slot in CPU_HOT_PLUG_DATA.
f60719
     //
f60719
-- 
f60719
2.27.0
f60719