qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC] QMP: add query-hotpluggable-cpus
@ 2016-02-15 17:10 Igor Mammedov
  2016-02-15 17:44 ` Eric Blake
  2016-02-15 19:43 ` Markus Armbruster
  0 siblings, 2 replies; 51+ messages in thread
From: Igor Mammedov @ 2016-02-15 17:10 UTC (permalink / raw)
  To: qemu-devel
  Cc: lvivier, thuth, ehabkost, aik, agraf, abologna, bharata, pbonzini,
	afaerber, david

it will allow mgmt to query present and possible to hotplug CPUs
it is required from a target platform that wish to support
command to set board specific MachineClass.possible_cpus() hook,
which will return a list of possible CPUs with options
that would be needed for hotplugging possible CPUs.

For RFC there are:
   'arch_id': 'int' - mandatory unique CPU number,
                      for x86 it's APIC ID for ARM it's MPIDR
   'type': 'str' - CPU object type for usage with device_add

and a set of optional fields that would allows mgmt tools
to know at what granularity and where a new CPU could be
hotplugged;
[node],[socket],[core],[thread]
Hopefully that should cover needs for CPU hotplug porposes for
magor targets and we can extend structure in future adding
more fields if it will be needed.

also for present CPUs there is a 'cpu_link' field which
would allow mgmt inspect whatever object/abstraction
the target platform considers as CPU object.

For RFC purposes implements only for x86 target so far.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/i386/pc.c               | 59 ++++++++++++++++++++++++++++++++++++++++++++++
 include/hw/boards.h        |  6 +++++
 include/hw/i386/topology.h | 15 ++++++++++++
 monitor.c                  | 13 ++++++++++
 qapi-schema.json           | 30 +++++++++++++++++++++++
 qmp-commands.hx            | 26 ++++++++++++++++++++
 target-i386/cpu.c          |  2 +-
 target-i386/cpu.h          |  1 +
 8 files changed, 151 insertions(+), 1 deletion(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 87660cd..d5f1c52 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1931,6 +1931,64 @@ static unsigned pc_cpu_index_to_socket_id(unsigned cpu_index)
     return topo.pkg_id;
 }
 
+static void pc_add_possible_cpu_descriptor(HotpluggableCPUList **head,
+                                           const char *model_name,
+                                           uint32_t apic_id,
+                                           char *cpu_link)
+{
+    X86CPUTopoInfo topo;
+    HotpluggableCPUList *list_item = g_new0(HotpluggableCPUList, 1);
+    HotpluggableCPU *cpu_item = g_new0(HotpluggableCPU, 1);
+
+    cpu_item->type = x86_cpu_type_name(model_name);
+    cpu_item->arch_id = apic_id;
+    x86_topo_ids_from_apicid(apic_id, smp_cores, smp_threads, &topo);
+    cpu_item->has_socket = true;
+    cpu_item->socket = topo.pkg_id;
+    cpu_item->has_core = true;
+    cpu_item->core = topo.core_id;
+    cpu_item->has_thread = true;
+    cpu_item->thread = topo.smt_id;
+    cpu_item->has_cpu_link = cpu_link;
+    cpu_item->cpu_link = cpu_link;
+
+    list_item->value = cpu_item;
+    list_item->next = *head;
+    *head = list_item;
+}
+
+static HotpluggableCPUList *pc_possible_cpus(MachineState *machine)
+{
+    int i;
+    CPUState *cpu;
+    uint32_t apic_id;
+    gchar **model_pieces;
+    HotpluggableCPUList *head = NULL;
+    DECLARE_BITMAP(found_cpus, ACPI_CPU_HOTPLUG_ID_LIMIT);
+
+    model_pieces = g_strsplit(machine->cpu_model, ",", 2);
+
+    memset(found_cpus, 0, sizeof found_cpus);
+    CPU_FOREACH(cpu) {
+        CPUClass *cc = CPU_GET_CLASS(cpu);
+
+        apic_id = cc->get_arch_id(cpu);
+        set_bit(apic_id, found_cpus);
+        pc_add_possible_cpu_descriptor(&head, model_pieces[0], apic_id,
+                                       object_get_canonical_path(OBJECT(cpu)));
+    }
+
+
+    for (i = 0; i < max_cpus; i++) {
+        apic_id = x86_cpu_apic_id_from_index(i);
+        if (!test_bit(apic_id, found_cpus)) {
+            pc_add_possible_cpu_descriptor(&head, model_pieces[0], apic_id,
+                                           NULL);
+        }
+    }
+    return head;
+}
+
 static void pc_machine_class_init(ObjectClass *oc, void *data)
 {
     MachineClass *mc = MACHINE_CLASS(oc);
@@ -1953,6 +2011,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     pcmc->save_tsc_khz = true;
     mc->get_hotplug_handler = pc_get_hotpug_handler;
     mc->cpu_index_to_socket_id = pc_cpu_index_to_socket_id;
+    mc->possible_cpus = pc_possible_cpus;
     mc->default_boot_order = "cad";
     mc->hot_add_cpu = pc_hot_add_cpu;
     mc->max_cpus = 255;
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 0f30959..0a29cad 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -57,6 +57,11 @@ bool machine_mem_merge(MachineState *machine);
  *    Set only by old machines because they need to keep
  *    compatibility on code that exposed QEMU_VERSION to guests in
  *    the past (and now use qemu_hw_version()).
+ * @possible_cpus:
+ *    Returns a list of @HotpluggableCPU descriptors
+ *    which includes CPU IDs for present and possible to hotplug CPUs
+ *    and coresponding type an topology information.
+ *    Caller is responsible for freeing returned list.
  */
 struct MachineClass {
     /*< private >*/
@@ -99,6 +104,7 @@ struct MachineClass {
     HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
                                            DeviceState *dev);
     unsigned (*cpu_index_to_socket_id)(unsigned cpu_index);
+    HotpluggableCPUList *(*possible_cpus)(MachineState *machine);
 };
 
 /**
diff --git a/include/hw/i386/topology.h b/include/hw/i386/topology.h
index 148cc1b..9e9c00c 100644
--- a/include/hw/i386/topology.h
+++ b/include/hw/i386/topology.h
@@ -119,6 +119,21 @@ static inline void x86_topo_ids_from_idx(unsigned nr_cores,
     topo->pkg_id = core_index / nr_cores;
 }
 
+/* Calculate thread/core/package IDs for a specific topology,
+ * based on APIC ID
+ */
+static inline void x86_topo_ids_from_apicid(unsigned apicid,
+                                            unsigned nr_cores,
+                                            unsigned nr_threads,
+                                            X86CPUTopoInfo *topo)
+{
+    topo->smt_id = apicid &
+                   ~(0xFFFFFFFFUL << apicid_smt_width(nr_cores, nr_threads));
+    topo->core_id = (apicid >> apicid_core_offset(nr_cores, nr_threads)) &
+                   ~(0xFFFFFFFFUL << apicid_core_width(nr_cores, nr_threads));
+    topo->pkg_id = apicid >> apicid_pkg_offset(nr_cores, nr_threads);
+}
+
 /* Make APIC ID for the CPU 'cpu_index'
  *
  * 'cpu_index' is a sequential, contiguous ID for the CPU.
diff --git a/monitor.c b/monitor.c
index 73eac17..0c9e6ce 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4241,3 +4241,16 @@ void qmp_dump_skeys(const char *filename, Error **errp)
     error_setg(errp, QERR_FEATURE_DISABLED, "dump-skeys");
 }
 #endif
+
+HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
+{
+    MachineState *ms = MACHINE(qdev_get_machine());
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+
+    if (!mc->possible_cpus) {
+        error_setg(errp, QERR_FEATURE_DISABLED, "query-hotpluggable-cpus");
+        return NULL;
+    }
+
+    return mc->possible_cpus(ms);
+}
diff --git a/qapi-schema.json b/qapi-schema.json
index 8d04897..127ba51 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -4083,3 +4083,33 @@
 ##
 { 'enum': 'ReplayMode',
   'data': [ 'none', 'record', 'play' ] }
+
+##
+# @HotpluggableCPU
+#
+# @type: CPU object tyep for usage with device_add command
+# @arch_id: unique number designating the CPU within board
+# @node: NUMA node ID the CPU belongs to, optional
+# @socket: socket number within node/board the CPU belongs to, optional
+# @core: core number within socket the CPU belongs to, optional
+# @thread: thread number within core the CPU belongs to, optional
+# @cpu_link: link to existing CPU object is CPU is present or
+#            omitted if CPU is not present.
+#
+# Since: 2.6
+{ 'struct': 'HotpluggableCPU',
+  'data': { 'type': 'str',
+            'arch_id': 'int',
+            '*node': 'int',
+            '*socket': 'int',
+            '*core': 'int',
+            '*thread': 'int',
+            '*cpu_link': 'str'
+          }
+}
+
+##
+# @query-hotpluggable-cpus
+#
+# Since: 2.6
+{ 'command': 'query-hotpluggable-cpus', 'returns': ['HotpluggableCPU'] }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 020e5ee..cbe0ba4 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -4818,3 +4818,29 @@ Example:
                  {"type": 0, "out-pport": 0, "pport": 0, "vlan-id": 3840,
                   "pop-vlan": 1, "id": 251658240}
    ]}
+
+EQMP
+
+    {
+        .name       = "query-hotpluggable-cpus",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_query_hotpluggable_cpus,
+    },
+
+SQMP
+Show  existing/possible CPUs
+-------------------------------
+
+Arguments: None.
+
+Example for x86 target started with -smp 2,sockets=2,cores=1,threads=3,maxcpus=6:
+
+-> { "execute": "query-hotpluggable-cpus" }
+<- {"return": [
+     {"core": 0, "socket": 1, "thread": 2, "arch_id": 6, "type": "qemu64-x86_64-cpu"},
+     {"core": 0, "socket": 1, "thread": 1, "arch_id": 5, "type": "qemu64-x86_64-cpu"},
+     {"core": 0, "socket": 1, "thread": 0, "arch_id": 4, "type": "qemu64-x86_64-cpu"},
+     {"core": 0, "socket": 0, "thread": 2, "arch_id": 2, "type": "qemu64-x86_64-cpu"},
+     {"core": 0, "arch_id": 1, "socket": 0, "thread": 1, "type": "qemu64-x86_64-cpu", "cpu_link": "/machine/unattached/device[3]"},
+     {"core": 0, "arch_id": 0, "socket": 0, "thread": 0, "type": "qemu64-x86_64-cpu", "cpu_link": "/machine/unattached/device[0]"}
+   ]}'
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 3918f01..c9b33b8 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -647,7 +647,7 @@ static void add_flagname_to_bitmaps(const char *flagname,
 /* Return type name for a given CPU model name
  * Caller is responsible for freeing the returned string.
  */
-static char *x86_cpu_type_name(const char *model_name)
+char *x86_cpu_type_name(const char *model_name)
 {
     return g_strdup_printf(X86_CPU_TYPE_NAME("%s"), model_name);
 }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index a990ea7..84e8183 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -1354,4 +1354,5 @@ void enable_compat_apic_id_mode(void);
 void x86_cpu_dump_local_apic_state(CPUState *cs, FILE *f,
                                    fprintf_function cpu_fprintf, int flags);
 
+char *x86_cpu_type_name(const char *model_name);
 #endif /* CPU_I386_H */
-- 
1.8.3.1

^ permalink raw reply related	[flat|nested] 51+ messages in thread

end of thread, other threads:[~2016-03-01 18:17 UTC | newest]

Thread overview: 51+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-02-15 17:10 [Qemu-devel] [RFC] QMP: add query-hotpluggable-cpus Igor Mammedov
2016-02-15 17:44 ` Eric Blake
2016-02-16  9:58   ` Igor Mammedov
2016-02-15 19:43 ` Markus Armbruster
2016-02-16  5:48   ` David Gibson
2016-02-16 10:52     ` Igor Mammedov
2016-02-18  4:05       ` David Gibson
2016-02-18 10:55         ` Igor Mammedov
2016-02-24 11:26           ` David Gibson
2016-02-24 13:10             ` Igor Mammedov
2016-02-16 10:36   ` Igor Mammedov
2016-02-16 12:35     ` Markus Armbruster
2016-02-16 12:41       ` Andreas Färber
2016-02-16 12:58         ` Markus Armbruster
2016-02-18  3:52       ` David Gibson
2016-02-18  7:33         ` Markus Armbruster
2016-02-17 20:59     ` Eduardo Habkost
2016-02-18  3:39     ` David Gibson
2016-02-18 10:37       ` Igor Mammedov
2016-02-19  4:38         ` David Gibson
2016-02-19  9:51           ` Markus Armbruster
2016-02-19 16:11             ` Igor Mammedov
2016-02-22  2:32             ` David Gibson
2016-02-22  9:05               ` Markus Armbruster
2016-02-24  1:57                 ` David Gibson
2016-02-24  8:42                   ` Markus Armbruster
2016-02-24 10:51                     ` David Gibson
2016-02-24 11:03                       ` Igor Mammedov
2016-02-25  1:03                         ` David Gibson
2016-02-25 10:22                           ` Igor Mammedov
2016-02-19 15:49           ` Igor Mammedov
2016-02-22  2:54             ` David Gibson
2016-02-23  9:46               ` Igor Mammedov
2016-02-23 21:26                 ` Eduardo Habkost
2016-02-24  1:52                   ` David Gibson
2016-02-24 14:42                   ` Igor Mammedov
2016-02-25  1:05                     ` David Gibson
2016-02-25 17:52                     ` Eduardo Habkost
2016-02-29 15:42                       ` Igor Mammedov
2016-03-01  1:19                         ` David Gibson
2016-03-01 10:49                           ` Igor Mammedov
2016-03-01 18:17                             ` Igor Mammedov
2016-03-01 14:02                         ` Eduardo Habkost
2016-02-24  1:54                 ` David Gibson
2016-02-24 14:17                   ` Igor Mammedov
2016-02-25  1:25                     ` David Gibson
2016-02-25 12:43                       ` Igor Mammedov
2016-02-26  4:12                         ` David Gibson
2016-02-26 10:37                           ` Igor Mammedov
2016-02-24  8:53                 ` Markus Armbruster
2016-02-24 11:31                   ` Igor Mammedov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).