qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 11/12] cpu hotplug: implement function cpu_status_wr


From: Gu Zheng
Subject: [Qemu-devel] [PATCH 11/12] cpu hotplug: implement function cpu_status_write() for vcpu ejection
Date: Fri, 12 Dec 2014 16:43:17 +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 |    6 ++++-
 include/hw/acpi/cpu_hotplug.h     |    1 +
 include/hw/qdev-core.h            |    1 +
 5 files changed, 49 insertions(+), 3 deletions(-)

diff --git a/hw/acpi/cpu_hotplug.c b/hw/acpi/cpu_hotplug.c
index 36feb6a..2a56df0 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 901f289..9f08fe6 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -223,7 +223,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 34aab5a..9485f12 100644
--- a/hw/i386/acpi-dsdt-cpu-hotplug.dsl
+++ b/hw/i386/acpi-dsdt-cpu-hotplug.dsl
@@ -50,7 +50,11 @@ Scope(\_SB) {
     }
     Method(CPEJ, 2, NotSerialized) {
         // _EJ0 method - eject callback
-        Sleep(200)
+        Store(Zero, Index(CPON, ToInteger(Arg0)))
+        Store(One, Local0)
+        ShiftLeft(Local0, Arg0, Local0)
+        Not(Local0, Local0)
+        And(PRS, Local0, 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 589bbe7..5b28a4f 100644
--- a/include/hw/qdev-core.h
+++ b/include/hw/qdev-core.h
@@ -263,6 +263,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.7.7




reply via email to

[Prev in Thread] Current Thread [Next in Thread]