Ankur Arora f053288863 OvmfPkg/CpuHotplugSmm: do actual CPU hot-eject
Add logic in EjectCpu() to do the actual the CPU ejection.

On the BSP, ejection happens by first selecting the CPU via
its QemuSelector and then sending the QEMU "eject" command.
QEMU in-turn signals the remote VCPU thread which context-switches
the CPU out of the SMI handler.

Meanwhile the CPU being ejected, waits around in its holding
area until it is context-switched out. Note that it is possible
that a slow CPU gets ejected before it reaches the wait loop.
However, this would never happen before it has executed the
"AllCpusInSync" loop in SmiRendezvous().
It can mean that an ejected CPU does not execute code after
that point but given that the CPU state will be destroyed by
QEMU, the missed cleanup is no great loss.

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>
Message-Id: <20210312062656.2477515-10-ankur.a.arora@oracle.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
[lersek@redhat.com: unneeded inner QemuSelector declaration in EjectCpu()
 triggers VS warning #4456 (local variable shadowed); remove it]
2021-03-16 13:21:46 +00:00

49 lines
1.5 KiB
C

/** @file
Macros for accessing QEMU's CPU hotplug register block.
Copyright (C) 2019, Red Hat, Inc.
SPDX-License-Identifier: BSD-2-Clause-Patent
@par Specification Reference:
- "docs/specs/acpi_cpu_hotplug.txt" in the QEMU source tree.
The original (now "legacy") CPU hotplug interface appeared in QEMU v1.5.0.
The new ("modern") hotplug interface appeared in QEMU v2.7.0.
The macros in this header file map to the minimal subset of the modern
interface that OVMF needs.
**/
#ifndef QEMU_CPU_HOTPLUG_H_
#define QEMU_CPU_HOTPLUG_H_
#include <Base.h>
//
// Each register offset is:
// - relative to the board-dependent IO base address of the register block,
// - named QEMU_CPUHP_(R|W|RW)_*, according to the possible access modes of the
// register,
// - followed by distinguished bitmasks or values in the register.
//
#define QEMU_CPUHP_R_CMD_DATA2 0x0
#define QEMU_CPUHP_R_CPU_STAT 0x4
#define QEMU_CPUHP_STAT_ENABLED BIT0
#define QEMU_CPUHP_STAT_INSERT BIT1
#define QEMU_CPUHP_STAT_REMOVE BIT2
#define QEMU_CPUHP_STAT_EJECT BIT3
#define QEMU_CPUHP_STAT_FW_REMOVE BIT4
#define QEMU_CPUHP_RW_CMD_DATA 0x8
#define QEMU_CPUHP_W_CPU_SEL 0x0
#define QEMU_CPUHP_W_CMD 0x5
#define QEMU_CPUHP_CMD_GET_PENDING 0x0
#define QEMU_CPUHP_CMD_GET_ARCH_ID 0x3
#endif // QEMU_CPU_HOTPLUG_H_