@@ -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;
@@ -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;
}
@@ -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 = {
@@ -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,
@@ -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--;
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(-)