[RFC 7/7] DO NOT MERGE: acpi: cpuhp: preserve always present vCPUs on unplug

Igor Mammedov posted 7 patches 1 week, 4 days ago
[RFC 7/7] DO NOT MERGE: acpi: cpuhp: preserve always present vCPUs on unplug
Posted by Igor Mammedov 1 week, 4 days ago
do not drop reference to always present vCPU and also
avoid destroying it (unparent) on unplug.

Based-on: 2d6cfbaf174 (hw/acpi: Make CPUs ACPI `presence` conditional during vCPU hot-unplug)
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 include/hw/acpi/cpu.h           |  4 +++-
 hw/acpi/acpi-cpu-hotplug-stub.c |  3 ++-
 hw/acpi/cpu.c                   | 10 ++++++++--
 hw/acpi/cpu_hotplug.c           |  2 +-
 hw/acpi/generic_event_device.c  |  2 +-
 5 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/include/hw/acpi/cpu.h b/include/hw/acpi/cpu.h
index e9e9c28359..f6708cafba 100644
--- a/include/hw/acpi/cpu.h
+++ b/include/hw/acpi/cpu.h
@@ -36,6 +36,7 @@ typedef struct CPUHotplugState {
     uint32_t selector;
     uint8_t command;
     uint32_t dev_count;
+    bool always_present_cpus;
     AcpiCpuStatus *devs;
 } CPUHotplugState;
 
@@ -50,7 +51,8 @@ void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st,
                         DeviceState *dev, Error **errp);
 
 void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
-                         CPUHotplugState *state, hwaddr base_addr);
+                         CPUHotplugState *state, hwaddr base_addr,
+                         bool always_present_cpus);
 
 typedef struct CPUHotplugFeatures {
     bool acpi_1_compatible;
diff --git a/hw/acpi/acpi-cpu-hotplug-stub.c b/hw/acpi/acpi-cpu-hotplug-stub.c
index c6c61bb9cd..748fd04006 100644
--- a/hw/acpi/acpi-cpu-hotplug-stub.c
+++ b/hw/acpi/acpi-cpu-hotplug-stub.c
@@ -20,7 +20,8 @@ void legacy_acpi_cpu_hotplug_init(MemoryRegion *parent, Object *owner,
 }
 
 void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
-                         CPUHotplugState *state, hwaddr base_addr)
+                         CPUHotplugState *state, hwaddr base_addr,
+                         bool always_present_cpus)
 {
     return;
 }
diff --git a/hw/acpi/cpu.c b/hw/acpi/cpu.c
index 992ae5d233..d85d4add60 100644
--- a/hw/acpi/cpu.c
+++ b/hw/acpi/cpu.c
@@ -145,7 +145,6 @@ static void cpu_hotplug_wr(void *opaque, hwaddr addr, uint64_t data,
             dev = DEVICE(cdev->cpu);
             hotplug_ctrl = qdev_get_hotplug_handler(dev);
             hotplug_handler_unplug(hotplug_ctrl, dev, NULL);
-            object_unparent(OBJECT(dev));
             cdev->fw_remove = false;
         } else if (data & 16) {
             if (!cdev->cpu || cdev->cpu == first_cpu) {
@@ -215,7 +214,8 @@ static const MemoryRegionOps cpu_hotplug_ops = {
 };
 
 void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
-                         CPUHotplugState *state, hwaddr base_addr)
+                         CPUHotplugState *state, hwaddr base_addr,
+                         bool always_present_cpus)
 {
     MachineState *machine = MACHINE(qdev_get_machine());
     MachineClass *mc = MACHINE_GET_CLASS(machine);
@@ -226,6 +226,7 @@ void cpu_hotplug_hw_init(MemoryRegion *as, Object *owner,
     id_list = mc->possible_cpu_arch_ids(machine);
     state->dev_count = id_list->len;
     state->devs = g_new0(typeof(*state->devs), state->dev_count);
+    state->always_present_cpus = always_present_cpus;
     for (i = 0; i < id_list->len; i++) {
         state->devs[i].cpu =  CPU(id_list->cpus[i].cpu);
         state->devs[i].arch_id = id_list->cpus[i].arch_id;
@@ -286,12 +287,17 @@ void acpi_cpu_unplug_cb(CPUHotplugState *cpu_st,
 {
     AcpiCpuStatus *cdev;
 
+    if (cpu_st->always_present_cpus) {
+        return;
+    }
+
     cdev = get_cpu_status(cpu_st, dev);
     if (!cdev) {
         return;
     }
 
     cdev->cpu = NULL;
+    object_unparent(OBJECT(dev));
 }
 
 static const VMStateDescription vmstate_cpuhp_sts = {
diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index 83b8bc5deb..8c3618680f 100644
--- a/hw/acpi/cpu_hotplug.c
+++ b/hw/acpi/cpu_hotplug.c
@@ -115,7 +115,7 @@ void acpi_switch_to_modern_cphp(AcpiCpuHotplug *gpe_cpu,
     MemoryRegion *parent = pci_address_space_io(PCI_DEVICE(gpe_cpu->device));
 
     memory_region_del_subregion(parent, &gpe_cpu->io);
-    cpu_hotplug_hw_init(parent, gpe_cpu->device, cpuhp_state, io_port);
+    cpu_hotplug_hw_init(parent, gpe_cpu->device, cpuhp_state, io_port, false);
 }
 
 void build_legacy_cpu_hotplug_aml(Aml *ctx, MachineState *machine,
diff --git a/hw/acpi/generic_event_device.c b/hw/acpi/generic_event_device.c
index 663d9cb093..9099b76f80 100644
--- a/hw/acpi/generic_event_device.c
+++ b/hw/acpi/generic_event_device.c
@@ -427,7 +427,7 @@ static void acpi_ged_realize(DeviceState *dev, Error **errp)
                                 ACPI_CPU_HOTPLUG_REG_LEN);
             sysbus_init_mmio(sbd, &s->container_cpuhp);
             cpu_hotplug_hw_init(&s->container_cpuhp, OBJECT(dev),
-                                &s->cpuhp_state, 0);
+                                &s->cpuhp_state, 0, false);
             break;
         }
         ged_events--;
-- 
2.43.0