During any vCPU hot-(un)plug operation, the running guest VM must be notified about the addition of a new vCPU or the removal of an existing vCPU. This notification is handled via an ACPI GED event, which is eventually demultiplexed into a vCPU hotplug event, and then further into a specific hot-(un)plug event for the *targeted* vCPU.
Introduce the required ACPI calls into the existing hot-(un)plug hooks, allowing ACPI GED events to be triggered from QEMU to the guest VM. Co-developed-by: Keqian Zhu <zhukeqi...@huawei.com> Signed-off-by: Keqian Zhu <zhukeqi...@huawei.com> Signed-off-by: Salil Mehta <salil.me...@huawei.com> --- hw/arm/virt.c | 39 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 36 insertions(+), 3 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index b1eba8de8c..15d9c2d8ac 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -3181,6 +3181,7 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, { VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); CPUState *cs = CPU(dev); + Error *local_err = NULL; CPUArchId *cpu_slot; /* insert the cold/hot-plugged vcpu in the slot */ @@ -3213,8 +3214,18 @@ static void virt_cpu_plug(HotplugHandler *hotplug_dev, DeviceState *dev, * hot-plugged, the guest is also notified. */ if (vms->acpi_dev) { - /* TODO: update acpi hotplug state. Send cpu hotplug event to guest */ + HotplugHandlerClass *hhc; + /* update acpi hotplug state and send cpu hotplug event to guest */ + hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev); + hhc->plug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err); + if (local_err) { + goto fail; + } } + + return; +fail: + error_propagate(errp, local_err); } static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev, @@ -3223,7 +3234,9 @@ static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev, MachineClass *mc = MACHINE_GET_CLASS(qdev_get_machine()); VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); ARMCPU *cpu = ARM_CPU(dev); + HotplugHandlerClass *hhc; CPUState *cs = CPU(dev); + Error *local_err = NULL; if (!vms->acpi_dev) { error_setg(errp, "GED does not exists or device is not realized!"); @@ -3242,14 +3255,25 @@ static void virt_cpu_unplug_request(HotplugHandler *hotplug_dev, return; } - /* TODO: request cpu hotplug from guest */ + /* request cpu hotplug from guest */ + hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev); + hhc->unplug_request(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err); + if (local_err) { + goto fail; + } + + return; +fail: + error_propagate(errp, local_err); } static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp) { VirtMachineState *vms = VIRT_MACHINE(hotplug_dev); + HotplugHandlerClass *hhc; CPUState *cs = CPU(dev); + Error *local_err = NULL; CPUArchId *cpu_slot; if (!vms->acpi_dev) { @@ -3259,7 +3283,12 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, cpu_slot = virt_find_cpu_slot(cs); - /* TODO: update the acpi cpu hotplug state for cpu hot-unplug */ + /* update the acpi cpu hotplug state for cpu hot-unplug */ + hhc = HOTPLUG_HANDLER_GET_CLASS(vms->acpi_dev); + hhc->unplug(HOTPLUG_HANDLER(vms->acpi_dev), dev, &local_err); + if (local_err) { + goto fail; + } unwire_gic_cpu_irqs(vms, cs); virt_update_gic(vms, cs, false); @@ -3274,6 +3303,10 @@ static void virt_cpu_unplug(HotplugHandler *hotplug_dev, DeviceState *dev, dev->opts = NULL; cpu_slot->cpu = NULL; + + return; +fail: + error_propagate(errp, local_err); } static void virt_machine_device_pre_plug_cb(HotplugHandler *hotplug_dev, -- 2.34.1