diff mbox

[RFC,v2,6/8] qmp: add 'cpu-del' command

Message ID 1370488621-6915-7-git-send-email-lig.fnst@cn.fujitsu.com
State New
Headers show

Commit Message

liguang June 6, 2013, 3:16 a.m. UTC
add 'cpu-del' as complementary of 'cpu-add',
cpu-del doesn't really delete a previous created
cpu for it depends on CPU-QOM which it's un-finished
yet to unrealize it.
cpu-del just records the cpu-id that guest want to
remove to keep status of ACPI cpu hot-remove process.

Signed-off-by: liguang <lig.fnst@cn.fujitsu.com>
---
 hw/i386/pc.c         |   30 ++++++++++++++++++++++++++++--
 hw/i386/pc_piix.c    |    1 +
 hw/i386/pc_q35.c     |    1 +
 include/hw/boards.h  |    5 +++--
 include/hw/i386/pc.h |    1 +
 qapi-schema.json     |   13 +++++++++++++
 qmp-commands.hx      |   23 +++++++++++++++++++++++
 qmp.c                |    9 +++++++++
 8 files changed, 79 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 4844a6b..a239892 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -55,6 +55,7 @@ 
 #include "hw/acpi/acpi.h"
 #include "hw/cpu/icc_bus.h"
 #include "hw/boards.h"
+#include "hw/acpi/ec.h"
 
 /* debug PC/ISA interrupts */
 //#define DEBUG_IRQ
@@ -926,10 +927,15 @@  void pc_hot_add_cpu(const int64_t id, Error **errp)
 {
     DeviceState *icc_bridge;
     int64_t apic_id = x86_cpu_apic_id_from_index(id);
+    uint8_t cpu_sts = ec_acpi_space_peek(EC_ACPI_SPACE_CPUS);
 
     if (cpu_exists(apic_id)) {
-        error_setg(errp, "Unable to add CPU: %" PRIi64
-                   ", it already exists", id);
+        if (cpu_sts & 1 << id) {
+            error_setg(errp, "Unable to add CPU: %" PRIi64
+                       ", it already exists", id);
+        } else {
+            ec_acpi_space_poke(EC_ACPI_SPACE_CPUS, cpu_sts | 1 << id);
+        }
         return;
     }
 
@@ -939,11 +945,31 @@  void pc_hot_add_cpu(const int64_t id, Error **errp)
         return;
     }
 
+    ec_acpi_space_poke(EC_ACPI_SPACE_CPUS, cpu_sts | 1 << id);
     icc_bridge = DEVICE(object_resolve_path_type("icc-bridge",
                                                  TYPE_ICC_BRIDGE, NULL));
     pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
 }
 
+void pc_hot_del_cpu(const int64_t id, Error **errp)
+{
+    uint8_t cpu_sts = ec_acpi_space_peek(EC_ACPI_SPACE_CPUS);
+
+    if (id >= max_cpus) {
+        error_setg(errp, "Unable to del CPU: %" PRIi64
+                   ", max allowed: %d", id, max_cpus - 1);
+        return;
+    }
+
+    if (cpu_sts & 1 << id) {
+        ec_acpi_space_poke(EC_ACPI_SPACE_CPUS, cpu_sts & ~(1 << id));
+        ec_acpi_space_poke(EC_ACPI_SPACE_CPUN, id);
+    } else {
+        error_setg(errp, "Unable to del CPU: %" PRIi64
+                   ", it was not added before.", id);
+    }
+}
+
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
 {
     int i;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index d618570..71ce2ff 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -333,6 +333,7 @@  static QEMUMachine pc_i440fx_machine_v1_5 = {
     .desc = "Standard PC (i440FX + PIIX, 1996)",
     .init = pc_init_pci,
     .hot_add_cpu = pc_hot_add_cpu,
+    .hot_del_cpu = pc_hot_del_cpu,
     .max_cpus = 255,
     .is_default = 1,
     DEFAULT_MACHINE_OPTIONS,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 7888dfe..f171ed3 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -221,6 +221,7 @@  static QEMUMachine pc_q35_machine_v1_5 = {
     .desc = "Standard PC (Q35 + ICH9, 2009)",
     .init = pc_q35_init,
     .hot_add_cpu = pc_hot_add_cpu,
+    .hot_del_cpu = pc_hot_del_cpu,
     .max_cpus = 255,
     DEFAULT_MACHINE_OPTIONS,
 };
diff --git a/include/hw/boards.h b/include/hw/boards.h
index fb7c6f1..fc6368a 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -22,7 +22,7 @@  typedef void QEMUMachineInitFunc(QEMUMachineInitArgs *args);
 
 typedef void QEMUMachineResetFunc(void);
 
-typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp);
+typedef void QEMUMachineHotAddDelCPUFunc(const int64_t id, Error **errp);
 
 typedef struct QEMUMachine {
     const char *name;
@@ -30,7 +30,8 @@  typedef struct QEMUMachine {
     const char *desc;
     QEMUMachineInitFunc *init;
     QEMUMachineResetFunc *reset;
-    QEMUMachineHotAddCPUFunc *hot_add_cpu;
+    QEMUMachineHotAddDelCPUFunc *hot_add_cpu;
+    QEMUMachineHotAddDelCPUFunc *hot_del_cpu;
     BlockInterfaceType block_default_type;
     int max_cpus;
     unsigned int no_serial:1,
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 6154058..89435f3 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -82,6 +82,7 @@  void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
+void pc_hot_del_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 FWCfgState *pc_memory_init(MemoryRegion *system_memory,
                            const char *kernel_filename,
diff --git a/qapi-schema.json b/qapi-schema.json
index ef1f657..d11e43b 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1403,6 +1403,19 @@ 
 { 'command': 'cpu-add', 'data': {'id': 'int'} }
 
 ##
+# @cpu-del
+#
+# Deletes CPU with specified ID
+#
+# @id: ID of CPU to be deleted, valid values [0..max_cpus)
+#
+# Returns: Nothing on success
+#
+# Since 1.6
+##
+{ 'command': 'cpu-del', 'data': {'id': 'int'} }
+
+##
 # @memsave:
 #
 # Save a portion of guest memory to a file.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index ffd130e..c4e77b4 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -408,6 +408,29 @@  Example:
 EQMP
 
     {
+        .name       = "cpu-del",
+        .args_type  = "id:i",
+        .mhandler.cmd_new = qmp_marshal_input_cpu_del,
+    },
+
+SQMP
+cpu-del
+-------
+
+Deletes virtual cpu
+
+Arguments:
+
+- "id": cpu id (json-int)
+
+Example:
+
+-> { "execute": "cpu-del", "arguments": { "id": 2 } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "memsave",
         .args_type  = "val:l,size:i,filename:s,cpu:i?",
         .mhandler.cmd_new = qmp_marshal_input_memsave,
diff --git a/qmp.c b/qmp.c
index 4c149b3..84dc873 100644
--- a/qmp.c
+++ b/qmp.c
@@ -118,6 +118,15 @@  void qmp_cpu_add(int64_t id, Error **errp)
     }
 }
 
+void qmp_cpu_del(int64_t id, Error **errp)
+{
+    if (current_machine->hot_del_cpu) {
+        current_machine->hot_del_cpu(id, errp);
+    } else {
+        error_setg(errp, "Not supported");
+    }
+}
+
 #ifndef CONFIG_VNC
 /* If VNC support is enabled, the "true" query-vnc command is
    defined in the VNC subsystem */