Skip to contentSkip to conversation

cpu: add device_add foo-x86_64-cpu support

RFC PATCH In review Gu Zheng 1 participant 5 messages Jun 27, 2014

lore
Share & tools
lore

Gu Zheng

author
#0 lore raw

cover cpu: add device_add foo-x86_64-cpu support

This series is based on the previous patchset from Chen Fan:
https://lists.nongnu.org/archive/html/qemu-devel/2014-05/msg02360.html

This patches try to make cpu hotplug with device_add, and make "-device foo-x86_64-cpu" available,also we can set apic-id property with command line, if without setting apic-id property, we offer the first unoccupied apic id as the default new apic id. When hotplug cpu with device_add, additional check of APIC ID will be done after cpu object initialization which was different from 'cpu_add' command that check 'ids' at the beginning.

Chen Fan (2):
cpu: introduce CpuTopoInfo structure for argument simplification
cpu: add device_add foo-x86_64-cpu support

Gu Zheng (1):
qom/cpu: move register_vmstate to common CPUClass.realizefn

 exec.c                          |   32 ++++++++++-------
 hw/intc/apic_common.c           |    3 +-
 include/hw/i386/apic_internal.h |    3 +-
 include/qom/cpu.h               |    3 ++
 qdev-monitor.c                  |    1 +
 qom/cpu.c                       |    2 +
 target-i386/cpu.c               |   76 ++++++++++++++++++++++++++++++++++++--
 target-i386/topology.h          |   51 ++++++++++++++++++--------
 8 files changed, 135 insertions(+), 36 deletions(-)
Signature · 1 line
1.7.7
author
#1 lore raw

RFC PATCH 1/3 cpu: introduce CpuTopoInfo structure for argument simplification

---
 target-i386/topology.h |   33 +++++++++++++++++----------------
 1 files changed, 17 insertions(+), 16 deletions(-)
target-i386/topology.h +17 -16
index 07a6c5f..e9ff89c 100644
@@ -47,6 +47,12 @@
  */
 typedef uint32_t apic_id_t;
 
+typedef struct X86CPUTopoInfo {
+    unsigned pkg_id;
+    unsigned core_id;
+    unsigned smt_id;
+} X86CPUTopoInfo;
+
 /* Return the bit width needed for 'count' IDs
  */
 static unsigned apicid_bitwidth_for_count(unsigned count)
@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)
  */
 static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,
                                              unsigned nr_threads,
-                                             unsigned pkg_id,
-                                             unsigned core_id,
-                                             unsigned smt_id)
+                                             const X86CPUTopoInfo *topo)
 {
-    return (pkg_id  << apicid_pkg_offset(nr_cores, nr_threads)) |
-           (core_id << apicid_core_offset(nr_cores, nr_threads)) |
-           smt_id;
+    return (topo->pkg_id  << apicid_pkg_offset(nr_cores, nr_threads)) |
+           (topo->core_id << apicid_core_offset(nr_cores, nr_threads)) |
+           topo->smt_id;
 }
 
 /* Calculate thread/core/package IDs for a specific topology,
@@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,
 static inline void x86_topo_ids_from_idx(unsigned nr_cores,
                                          unsigned nr_threads,
                                          unsigned cpu_index,
-                                         unsigned *pkg_id,
-                                         unsigned *core_id,
-                                         unsigned *smt_id)
+                                         X86CPUTopoInfo *topo)
 {
     unsigned core_index = cpu_index / nr_threads;
-    *smt_id = cpu_index % nr_threads;
-    *core_id = core_index % nr_cores;
-    *pkg_id = core_index / nr_cores;
+    topo->smt_id = cpu_index % nr_threads;
+    topo->core_id = core_index % nr_cores;
+    topo->pkg_id = core_index / nr_cores;
 }
 
 /* Make APIC ID for the CPU 'cpu_index'
@@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores,
                                                 unsigned nr_threads,
                                                 unsigned cpu_index)
 {
-    unsigned pkg_id, core_id, smt_id;
-    x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index,
-                          &pkg_id, &core_id, &smt_id);
-    return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id);
+    X86CPUTopoInfo topo;
+    x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, &topo);
+    return apicid_from_topo_ids(nr_cores, nr_threads, &topo);
 }
 
 #endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.7.7
author
#2 lore raw

Re: [Qemu-devel] [RFC PATCH 1/3] cpu: introduce CpuTopoInfo structure for argument simplification

Correct the author.
From: Chen Fan <[email protected]>

Quoted 75 lines · Gu Zheng
---
 target-i386/topology.h |   33 +++++++++++++++++----------------
 1 files changed, 17 insertions(+), 16 deletions(-)
target-i386/topology.h +17 -16
index 07a6c5f..e9ff89c 100644
@@ -47,6 +47,12 @@
  */
 typedef uint32_t apic_id_t;
 
+typedef struct X86CPUTopoInfo {
+    unsigned pkg_id;
+    unsigned core_id;
+    unsigned smt_id;
+} X86CPUTopoInfo;
+
 /* Return the bit width needed for 'count' IDs
  */
 static unsigned apicid_bitwidth_for_count(unsigned count)
@@ -92,13 +98,11 @@ static inline unsigned apicid_pkg_offset(unsigned nr_cores, unsigned nr_threads)
  */
 static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,
                                              unsigned nr_threads,
-                                             unsigned pkg_id,
-                                             unsigned core_id,
-                                             unsigned smt_id)
+                                             const X86CPUTopoInfo *topo)
 {
-    return (pkg_id  << apicid_pkg_offset(nr_cores, nr_threads)) |
-           (core_id << apicid_core_offset(nr_cores, nr_threads)) |
-           smt_id;
+    return (topo->pkg_id  << apicid_pkg_offset(nr_cores, nr_threads)) |
+           (topo->core_id << apicid_core_offset(nr_cores, nr_threads)) |
+           topo->smt_id;
 }
 
 /* Calculate thread/core/package IDs for a specific topology,
@@ -107,14 +111,12 @@ static inline apic_id_t apicid_from_topo_ids(unsigned nr_cores,
 static inline void x86_topo_ids_from_idx(unsigned nr_cores,
                                          unsigned nr_threads,
                                          unsigned cpu_index,
-                                         unsigned *pkg_id,
-                                         unsigned *core_id,
-                                         unsigned *smt_id)
+                                         X86CPUTopoInfo *topo)
 {
     unsigned core_index = cpu_index / nr_threads;
-    *smt_id = cpu_index % nr_threads;
-    *core_id = core_index % nr_cores;
-    *pkg_id = core_index / nr_cores;
+    topo->smt_id = cpu_index % nr_threads;
+    topo->core_id = core_index % nr_cores;
+    topo->pkg_id = core_index / nr_cores;
 }
 
 /* Make APIC ID for the CPU 'cpu_index'
@@ -125,10 +127,9 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores,
                                                 unsigned nr_threads,
                                                 unsigned cpu_index)
 {
-    unsigned pkg_id, core_id, smt_id;
-    x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index,
-                          &pkg_id, &core_id, &smt_id);
-    return apicid_from_topo_ids(nr_cores, nr_threads, pkg_id, core_id, smt_id);
+    X86CPUTopoInfo topo;
+    x86_topo_ids_from_idx(nr_cores, nr_threads, cpu_index, &topo);
+    return apicid_from_topo_ids(nr_cores, nr_threads, &topo);
 }
 
 #endif /* TARGET_I386_TOPOLOGY_H */
author
#3 lore raw

RFC PATCH 2/3 qom/cpu: move register_vmstate to common CPUClass.realizefn

In reply to Gu Zheng

Move cpu vmstate register from cpu_exec_init into cpu_common_realizefn, apic vmstate register into x86_cpu_apic_realize. And use the cc->get_arch_id as the instance id that suggested by Igor to fix the migration issue.

---
 exec.c                          |   32 +++++++++++++++++++-------------
 hw/intc/apic_common.c           |    3 +--
 include/hw/i386/apic_internal.h |    3 ++-
 include/qom/cpu.h               |    2 ++
 qom/cpu.c                       |    2 ++
 target-i386/cpu.c               |   12 +++++++++---
 6 files changed, 35 insertions(+), 19 deletions(-)
exec.c +19 -13
index 4e179a6..61ad996 100644
@@ -468,10 +468,28 @@ void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as)
 }
 #endif
 
+void cpu_vmstate_register(CPUState *cpu)
+{
+    CPUClass *cc = CPU_GET_CLASS(cpu);
+    int cpu_index = cc->get_arch_id(cpu);
+
+    if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
+        vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
+    }
+#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
+    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
+                    cpu_save, cpu_load, cpu->env_ptr);
+    assert(cc->vmsd == NULL);
+    assert(qdev_get_vmsd(DEVICE(cpu)) == NULL);
+#endif
+    if (cc->vmsd != NULL) {
+        vmstate_register(NULL, cpu_index, cc->vmsd, cpu);
+    }
+}
+
 void cpu_exec_init(CPUArchState *env)
 {
     CPUState *cpu = ENV_GET_CPU(env);
-    CPUClass *cc = CPU_GET_CLASS(cpu);
     CPUState *some_cpu;
     int cpu_index;
 
@@ -494,18 +512,6 @@ void cpu_exec_init(CPUArchState *env)
 #if defined(CONFIG_USER_ONLY)
     cpu_list_unlock();
 #endif
-    if (qdev_get_vmsd(DEVICE(cpu)) == NULL) {
-        vmstate_register(NULL, cpu_index, &vmstate_cpu_common, cpu);
-    }
-#if defined(CPU_SAVE_VERSION) && !defined(CONFIG_USER_ONLY)
-    register_savevm(NULL, "cpu", cpu_index, CPU_SAVE_VERSION,
-                    cpu_save, cpu_load, env);
-    assert(cc->vmsd == NULL);
-    assert(qdev_get_vmsd(DEVICE(cpu)) == NULL);
-#endif
-    if (cc->vmsd != NULL) {
-        vmstate_register(NULL, cpu_index, cc->vmsd, cpu);
-    }
 }
 
 #if defined(TARGET_HAS_ICE)
hw/intc/apic_common.c +1 -2
index ce3d903..029f67d 100644
@@ -345,7 +345,7 @@ static int apic_dispatch_post_load(void *opaque, int version_id)
     return 0;
 }
 
-static const VMStateDescription vmstate_apic_common = {
+const VMStateDescription vmstate_apic_common = {
     .name = "apic",
     .version_id = 3,
     .minimum_version_id = 3,
@@ -391,7 +391,6 @@ static void apic_common_class_init(ObjectClass *klass, void *data)
     ICCDeviceClass *idc = ICC_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
-    dc->vmsd = &vmstate_apic_common;
     dc->reset = apic_reset_common;
     dc->props = apic_properties_common;
     idc->realize = apic_common_realize;
include/hw/i386/apic_internal.h +2 -1
index 83e2a42..8a645cf 100644
@@ -23,6 +23,7 @@
 #include "exec/memory.h"
 #include "hw/cpu/icc_bus.h"
 #include "qemu/timer.h"
+#include "migration/vmstate.h"
 
 /* APIC Local Vector Table */
 #define APIC_LVT_TIMER                  0
@@ -136,7 +137,7 @@ typedef struct VAPICState {
 } QEMU_PACKED VAPICState;
 
 extern bool apic_report_tpr_access;
-
+extern const VMStateDescription vmstate_apic_common;
 void apic_report_irq_delivered(int delivered);
 bool apic_next_timer(APICCommonState *s, int64_t current_time);
 void apic_enable_tpr_access_reporting(DeviceState *d, bool enable);
include/qom/cpu.h +2 -0
index 4b352a2..87eecd2 100644
@@ -548,6 +548,8 @@ void cpu_interrupt(CPUState *cpu, int mask);
 
 #endif /* USER_ONLY */
 
+void cpu_vmstate_register(CPUState *cpu);
+
 #ifdef CONFIG_SOFTMMU
 static inline void cpu_unassigned_access(CPUState *cpu, hwaddr addr,
                                          bool is_write, bool is_exec,
qom/cpu.c +2 -0
index fada2d4..5158343 100644
@@ -296,6 +296,8 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cpu = CPU(dev);
 
+    cpu_vmstate_register(cpu);
+
     if (dev->hotplugged) {
         cpu_synchronize_post_init(cpu);
         notifier_list_notify(&cpu_added_notifiers, dev);
target-i386/cpu.c +9 -3
index 8983457..10f6d53 100644
@@ -2554,13 +2554,19 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
 
 static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
 {
-    if (cpu->apic_state == NULL) {
+    DeviceState *apic_state = cpu->apic_state;
+    CPUClass *cc = CPU_GET_CLASS(CPU(cpu));
+
+    if (apic_state == NULL) {
         return;
     }
 
-    if (qdev_init(cpu->apic_state)) {
+    vmstate_register(0, cc->get_arch_id(CPU(cpu)),
+            &vmstate_apic_common, apic_state);
+
+    if (qdev_init(apic_state)) {
         error_setg(errp, "APIC device '%s' could not be initialized",
-                   object_get_typename(OBJECT(cpu->apic_state)));
+            object_get_typename(OBJECT(cpu->apic_state)));
         return;
     }
 }
Signature · 1 line
1.7.7
author
#4 lore raw

RFC PATCH 3/3 cpu: add device_add foo-x86_64-cpu support

In reply to Gu Zheng

From: Chen Fan <[email protected]>

Add support to device_add foo-x86_64-cpu, and additional checks of apic id are added into x86_cpuid_set_apic_id() and x86_cpu_apic_create() for duplicate. Besides, in order to support "device/device_add foo-x86_64-cpu" which without specified apic id, we add a new function get_free_apic_id() to provide the first free apid id each time to avoid apic id duplicate.

---
 include/qom/cpu.h      |    1 +
 qdev-monitor.c         |    1 +
 target-i386/cpu.c      |   64 +++++++++++++++++++++++++++++++++++++++++++++++-
 target-i386/topology.h |   18 +++++++++++++
 4 files changed, 83 insertions(+), 1 deletions(-)
include/qom/cpu.h +1 -0
index 87eecd2..87bd652 100644
@@ -291,6 +291,7 @@ struct CPUState {
 QTAILQ_HEAD(CPUTailQ, CPUState);
 extern struct CPUTailQ cpus;
 #define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
+#define CPU_REMOVE(cpu) QTAILQ_REMOVE(&cpus, cpu, node)
 #define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node)
 #define CPU_FOREACH_SAFE(cpu, next_cpu) \
     QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
qdev-monitor.c +1 -0
index f87f3d8..48327c8 100644
@@ -24,6 +24,7 @@
 #include "qmp-commands.h"
 #include "sysemu/arch_init.h"
 #include "qemu/config-file.h"
+#include "qom/object_interfaces.h"
 
 /*
  * Aliases were a bad idea from the start.  Let's keep them
target-i386/cpu.c +63 -1

143 lines not on this page · raw message

target-i386/topology.h +18 -0
index e9ff89c..dcb4988 100644
@@ -132,4 +132,22 @@ static inline apic_id_t x86_apicid_from_cpu_idx(unsigned nr_cores,
     return apicid_from_topo_ids(nr_cores, nr_threads, &topo);
 }
 
+/* Calculate CPU topology based on CPU APIC ID.
+ */
+static inline void x86_topo_ids_from_apic_id(unsigned nr_cores,
+                                             unsigned nr_threads,
+                                             apic_id_t apic_id,
+                                             X86CPUTopoInfo *topo)
+{
+    unsigned offset_mask;
+    topo->pkg_id = apic_id >> apicid_pkg_offset(nr_cores, nr_threads);
+
+    offset_mask = (1L << apicid_pkg_offset(nr_cores, nr_threads)) - 1;
+    topo->core_id = (apic_id & offset_mask)
+                     >> apicid_core_offset(nr_cores, nr_threads);
+
+    offset_mask = (1L << apicid_core_offset(nr_cores, nr_threads)) - 1;
+    topo->smt_id = apic_id & offset_mask;
+}
+
 #endif /* TARGET_I386_TOPOLOGY_H */
Signature · 1 line
1.7.7