When OS eject a vcpu (like: echo 1 > /sys/bus/acpi/devices/LNXCPUXX/eject), it will call acpi EJ0 method, the firmware will write the new cpumap, QEMU will know which vcpu need to be ejected.
Signed-off-by: Chen Fan <chen.fan.f...@cn.fujitsu.com> --- hw/acpi/piix4.c | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index c885690..1aaa7a4 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -61,6 +61,7 @@ struct pci_status { typedef struct CPUStatus { uint8_t sts[PIIX4_PROC_LEN]; + uint8_t old_sts[PIIX4_PROC_LEN]; } CPUStatus; typedef struct PIIX4PMState { @@ -610,6 +611,12 @@ static const MemoryRegionOps piix4_pci_ops = { }, }; +static void acpi_piix_eject_vcpu(int64_t cpuid) +{ + /* TODO: eject a vcpu, release allocated vcpu and exit the vcpu pthread. */ + PIIX4_DPRINTF("vcpu: %" PRIu64 " need to be ejected.\n", cpuid); +} + static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size) { PIIX4PMState *s = opaque; @@ -622,7 +629,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 */ + PIIX4PMState *s = opaque; + CPUStatus *cpus = &s->gpe_cpu; + uint8_t val; + int i; + int64_t cpuid = 0; + + val = cpus->old_sts[addr] ^ data; + + if (val == 0) + return; + + for (i = 0; i < 8; i++) { + if (val & 1 << i) { + cpuid = 8 * addr + i; + } + } + + if (cpuid != 0) { + acpi_piix_eject_vcpu(cpuid); + } } static const MemoryRegionOps cpu_hotplug_ops = { @@ -647,11 +673,17 @@ static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu, ACPIGPE *gpe = &s->ar.gpe; CPUClass *k = CPU_GET_CLASS(cpu); int64_t cpu_id; + int i; assert(s != NULL); *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS; cpu_id = k->get_arch_id(CPU(cpu)); + + for (i = 0; i < PIIX4_PROC_LEN; i++) { + g->old_sts[i] = g->sts[i]; + } + if (action == PLUG) { g->sts[cpu_id / 8] |= (1 << (cpu_id % 8)); } else { @@ -675,6 +707,7 @@ static void piix4_init_cpu_status(CPUState *cpu, void *data) g_assert((id / 8) < PIIX4_PROC_LEN); g->sts[id / 8] |= (1 << (id % 8)); + g->old_sts[id / 8] |= (1 << (id % 8)); } static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev, -- 1.8.1.4