[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v3 6/7] cpu hotplug: implement function cpu_status_w
From: |
Zhu Guihua |
Subject: |
[Qemu-devel] [PATCH v3 6/7] cpu hotplug: implement function cpu_status_write() for vcpu ejection |
Date: |
Fri, 13 Feb 2015 18:40:21 +0800 |
From: Chen Fan <address@hidden>
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 <address@hidden>
Signed-off-by: Gu Zheng <address@hidden>
Signed-off-by: Zhu Guihua <address@hidden>
---
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
- [Qemu-devel] [PATCH v3 0/7] cpu: add i386 cpu hot remove support, Zhu Guihua, 2015/02/13
- [Qemu-devel] [PATCH v3 2/7] acpi/cpu: add cpu hot unplug request callback function, Zhu Guihua, 2015/02/13
- [Qemu-devel] [PATCH v3 1/7] x86: add x86_cpu_unrealizefn() for cpu apic remove, Zhu Guihua, 2015/02/13
- [Qemu-devel] [PATCH v3 3/7] acpi, pc: add cpu hot unplug request callback support, Zhu Guihua, 2015/02/13
- [Qemu-devel] [PATCH v3 4/7] acpi/cpu: add cpu hot unplug callback function, Zhu Guihua, 2015/02/13
- [Qemu-devel] [PATCH v3 5/7] acpi, pc: add cpu hot unplug callback support, Zhu Guihua, 2015/02/13
- [Qemu-devel] [PATCH v3 6/7] cpu hotplug: implement function cpu_status_write() for vcpu ejection,
Zhu Guihua <=
- [Qemu-devel] [PATCH v3 7/7] cpus: reclaim allocated vCPU objects, Zhu Guihua, 2015/02/13
- Re: [Qemu-devel] [PATCH v3 0/7] cpu: add i386 cpu hot remove support, Gu Zheng, 2015/02/23