From: Chen Fan <chen.fan.f...@cn.fujitsu.com> When OS ejected a vcpu (like: echo 1 > /sys/bus/acpi/devices/LNXCPUXX/eject), it would call acpi EJ0 method, the firmware need to write the new cpumap, QEMU would know which vcpu need to be ejected.
Signed-off-by: Chen Fan <chen.fan.f...@cn.fujitsu.com> Signed-off-by: Gu Zheng <guz.f...@cn.fujitsu.com> Signed-off-by: Zhu Guihua <zhugh.f...@cn.fujitsu.com> --- hw/acpi/cpu_hotplug.c | 42 ++++++++++++++++++++++++++++++++++++++- hw/core/qdev.c | 2 +- hw/i386/acpi-dsdt-cpu-hotplug.dsl | 16 ++++++++++++++- include/hw/acpi/cpu_hotplug.h | 1 + include/hw/qdev-core.h | 1 + 5 files changed, 59 insertions(+), 3 deletions(-) diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c index c47909c..1874ee0 100644 --- a/hw/acpi/cpu_hotplug.c +++ b/hw/acpi/cpu_hotplug.c @@ -17,6 +17,26 @@ typedef enum STS_OPT { CLEAR, } STS_OPT; +static void acpi_eject_vcpu(AcpiCpuHotplug *cpus_status, int64_t cpu_id) +{ + CPUState *cpu; + + CPU_FOREACH(cpu) { + CPUClass *cc = CPU_GET_CLASS(cpu); + int64_t id = cc->get_arch_id(cpu); + HotplugHandler *hotplug_ctrl; + + if (cpu_id == id) { + cpus_status->old_sts[cpu_id / 8] &= ~(1 << (cpu_id % 8)); + cpus_status->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8)); + + hotplug_ctrl = qdev_get_hotplug_handler(DEVICE(cpu)); + hotplug_handler_unplug(hotplug_ctrl, DEVICE(cpu), NULL); + break; + } + } +} + static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size) { AcpiCpuHotplug *cpus = opaque; @@ -28,7 +48,26 @@ static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size) static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data, unsigned int size) { - /* TODO: implement VCPU removal on guest signal that CPU can be removed */ + AcpiCpuHotplug *cpus = opaque; + uint8_t val; + int i; + int64_t cpu_id = -1; + + val = cpus->old_sts[addr] ^ data; + + if (val == 0) { + return; + } + + for (i = 0; i < 8; i++) { + if (val & 1 << i) { + cpu_id = 8 * addr + i; + } + } + + if (cpu_id != -1) { + acpi_eject_vcpu(cpus, cpu_id); + } } static const MemoryRegionOps AcpiCpuHotplug_ops = { @@ -56,6 +95,7 @@ static void acpi_update_cpu_present_bit(AcpiCpuHotplug *g, CPUState *cpu, switch (opt) { case SET: g->sts[cpu_id / 8] |= (1 << (cpu_id % 8)); + g->old_sts[cpu_id / 8] |= (1 << (cpu_id % 8)); break; case CLEAR: g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8)); diff --git a/hw/core/qdev.c b/hw/core/qdev.c index 2eacac0..2f3d1df 100644 --- a/hw/core/qdev.c +++ b/hw/core/qdev.c @@ -273,7 +273,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, dev->alias_required_for_version = required_for_version; } -static HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) +HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev) { HotplugHandler *hotplug_ctrl = NULL; diff --git a/hw/i386/acpi-dsdt-cpu-hotplug.dsl b/hw/i386/acpi-dsdt-cpu-hotplug.dsl index 268d870..e03517f 100644 --- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl +++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl @@ -50,7 +50,21 @@ Scope(\_SB) { } Method(CPEJ, 2, NotSerialized) { // _EJ0 method - eject callback - Sleep(200) + Store(Zero, Index(CPON, ToInteger(Arg0))) + Store(PRS, Local5) + // Local0 = the index of cpu bitmap + Store(ShiftRight(ToInteger(Arg0), 3), Local0) + // Local1 = the subobject of PRS with dereferece + Store(DerefOf(Index(PRS, Local0)), Local1) + // Local2 = the bit index in cpu bitmap + And(ToInteger(Arg0), 0x7, Local2) + Store(One, Local3) + ShiftLeft(Local3, Local2, Local3) + Not(Local3, Local3) + // discard the bit index in cpu bitmap + And(Local1, Local3, Local1) + Store(Local1, Index(Local5, Local0)) + Store(Local5, PRS) } #define CPU_STATUS_LEN ACPI_GPE_PROC_LEN diff --git a/include/hw/acpi/cpu_hotplug.h b/include/hw/acpi/cpu_hotplug.h index 0f84adb..abbb29e 100644 --- a/include/hw/acpi/cpu_hotplug.h +++ b/include/hw/acpi/cpu_hotplug.h @@ -18,6 +18,7 @@ typedef struct AcpiCpuHotplug { MemoryRegion io; uint8_t sts[ACPI_GPE_PROC_LEN]; + uint8_t old_sts[ACPI_GPE_PROC_LEN]; } AcpiCpuHotplug; void acpi_cpu_plug_cb(ACPIREGS *ar, qemu_irq irq, diff --git a/include/hw/qdev-core.h b/include/hw/qdev-core.h index 15a226f..de42e78 100644 --- a/include/hw/qdev-core.h +++ b/include/hw/qdev-core.h @@ -269,6 +269,7 @@ void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id, void qdev_unplug(DeviceState *dev, Error **errp); void qdev_simple_device_unplug_cb(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); +HotplugHandler *qdev_get_hotplug_handler(DeviceState *dev); void qdev_machine_creation_done(void); bool qdev_machine_modified(void); -- 1.9.3