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

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