Patchwork [RFC,qom-cpu,v3,08/10] i386: implement pc interface pc_hot_del_cpu()

login
register
mail settings
Submitter chenfan
Date Sept. 16, 2013, 2:40 a.m.
Message ID <443499ed1c9978b00f3bdef3218203fc3d3d81e5.1379062188.git.chen.fan.fnst@cn.fujitsu.com>
Download mbox | patch
Permalink /patch/275099/
State New
Headers show

Comments

chenfan - Sept. 16, 2013, 2:40 a.m.
Implement cpu interface pc_hot_del_cpu() for unrealizing device vCPU.
emiting vcpu-remove notifier to ACPI, then ACPI could send sci interrupt
to OS for hot-remove vcpu.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/i386/pc.c | 30 ++++++++++++++++++++++++++++--
 qom/cpu.c    | 12 ++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)

Patch

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 8ab6e4f..ce7b20f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -958,8 +958,34 @@  void pc_hot_add_cpu(const int64_t id, Error **errp)
 
 void pc_hot_del_cpu(const int64_t id, Error **errp)
 {
-    /* TODO: hot remove vCPU. */
-    error_setg(errp, "Hot-remove CPU is not supported.");
+    CPUState *cpu;
+    bool found = false;
+    X86CPUClass *xcc;
+
+    CPU_FOREACH(cpu) {
+        CPUClass *cc = CPU_GET_CLASS(cpu);
+        int64_t cpuid = cc->get_arch_id(cpu);
+
+        if (cpuid == id) {
+            found = true;
+            break;
+        }
+    }
+
+    if (!found) {
+        error_setg(errp, "Unable to find cpu-index: %" PRIi64
+                   ", it doesn't exist or has been deleted.", id);
+        return;
+    }
+
+    if (cpu == first_cpu && !CPU_NEXT(cpu)) {
+        error_setg(errp, "Unable to delete the last "
+                   "one cpu when VM running.");
+        return;
+    }
+
+    xcc = X86_CPU_GET_CLASS(DEVICE(cpu));
+    xcc->parent_unrealize(DEVICE(cpu), errp);
 }
 
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
diff --git a/qom/cpu.c b/qom/cpu.c
index c6d7ebc..b413a4c 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -227,6 +227,17 @@  static void cpu_common_realizefn(DeviceState *dev, Error **errp)
     }
 }
 
+static void cpu_common_unrealizefn(DeviceState *dev, Error **errp)
+{
+    CPUNotifier notifier;
+
+    notifier.dev = dev;
+    notifier.type = UNPLUG;
+
+    notifier_list_notify(&cpu_hotplug_notifiers, &notifier);
+}
+
+
 static void cpu_common_initfn(Object *obj)
 {
     CPUState *cpu = CPU(obj);
@@ -257,6 +268,7 @@  static void cpu_class_init(ObjectClass *klass, void *data)
     k->gdb_read_register = cpu_common_gdb_read_register;
     k->gdb_write_register = cpu_common_gdb_write_register;
     dc->realize = cpu_common_realizefn;
+    dc->unrealize = cpu_common_unrealizefn;
     dc->no_user = 1;
 }