* [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support
@ 2014-05-13 10:08 Chen Fan
2014-05-13 10:08 ` [Qemu-devel] [RFC 1/3] using CPUMASK bitmaps to calculate cpu index Chen Fan
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Chen Fan @ 2014-05-13 10:08 UTC (permalink / raw)
To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber, Eduardo Habkost
this patches tried to make cpu hotplug with device_add,
and made -device foo-x86_64-cpu available,also we can
set apic-id property with command line, if without setting
apic-id property, we added first unoccupied apic id as the
default new apic id. and hotplug cpu with device_add, we
must make check of APIC ID after cpu object initialization
that was different from 'cpu_add' command which check 'ids'
at the beginning.
Chen Fan (3):
using CPUMASK bitmaps to calculate cpu index
cpu: introduce CpuTopoInfo structure for argument simplification
cpu: add device_add foo-x86_64-cpu support
exec.c | 9 +++--
include/qom/cpu.h | 11 ++++++
include/sysemu/sysemu.h | 7 ----
qdev-monitor.c | 11 ++++++
target-i386/cpu.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++-
target-i386/topology.h | 51 ++++++++++++++++++---------
6 files changed, 151 insertions(+), 29 deletions(-)
--
1.8.1.4
^ permalink raw reply [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC 1/3] using CPUMASK bitmaps to calculate cpu index
2014-05-13 10:08 [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
@ 2014-05-13 10:08 ` Chen Fan
2014-05-22 13:26 ` Igor Mammedov
2014-05-13 10:08 ` [Qemu-devel] [RFC 2/3] cpu: introduce CpuTopoInfo structure for argument simplification Chen Fan
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Chen Fan @ 2014-05-13 10:08 UTC (permalink / raw)
To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber, Eduardo Habkost
instead of seeking the number of CPUs, using CPUMASK bitmaps to
calculate the cpu index, also would be a gread benefit to remove
cpu index.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
exec.c | 9 ++++-----
include/qom/cpu.h | 9 +++++++++
include/sysemu/sysemu.h | 7 -------
3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/exec.c b/exec.c
index cf12049..2948841 100644
--- a/exec.c
+++ b/exec.c
@@ -473,16 +473,15 @@ void cpu_exec_init(CPUArchState *env)
{
CPUState *cpu = ENV_GET_CPU(env);
CPUClass *cc = CPU_GET_CLASS(cpu);
- CPUState *some_cpu;
int cpu_index;
#if defined(CONFIG_USER_ONLY)
cpu_list_lock();
#endif
- cpu_index = 0;
- CPU_FOREACH(some_cpu) {
- cpu_index++;
- }
+ cpu_index = find_first_zero_bit(cc->cpu_present_mask,
+ MAX_CPUMASK_BITS);
+ set_bit(cpu_index, cc->cpu_present_mask);
+
cpu->cpu_index = cpu_index;
cpu->numa_node = 0;
QTAILQ_INIT(&cpu->breakpoints);
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index df977c8..b8f46b1 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -70,6 +70,13 @@ typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
struct TranslationBlock;
+/* The following shall be true for all CPUs:
+ * cpu->cpu_index < max_cpus <= MAX_CPUMASK_BITS
+ *
+ * Note that cpu->get_arch_id() may be larger than MAX_CPUMASK_BITS.
+ */
+#define MAX_CPUMASK_BITS 255
+
/**
* CPUClass:
* @class_by_name: Callback to map -cpu command line model name to an
@@ -142,6 +149,8 @@ typedef struct CPUClass {
const struct VMStateDescription *vmsd;
int gdb_num_core_regs;
const char *gdb_core_xml_file;
+
+ DECLARE_BITMAP(cpu_present_mask, MAX_CPUMASK_BITS);
} CPUClass;
#ifdef HOST_WORDS_BIGENDIAN
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index ba5c7f8..04edb8b 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -134,13 +134,6 @@ extern QEMUClockType rtc_clock;
#define MAX_NODES 64
-/* The following shall be true for all CPUs:
- * cpu->cpu_index < max_cpus <= MAX_CPUMASK_BITS
- *
- * Note that cpu->get_arch_id() may be larger than MAX_CPUMASK_BITS.
- */
-#define MAX_CPUMASK_BITS 255
-
extern int nb_numa_nodes;
extern uint64_t node_mem[MAX_NODES];
extern unsigned long *node_cpumask[MAX_NODES];
--
1.8.1.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC 2/3] cpu: introduce CpuTopoInfo structure for argument simplification
2014-05-13 10:08 [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
2014-05-13 10:08 ` [Qemu-devel] [RFC 1/3] using CPUMASK bitmaps to calculate cpu index Chen Fan
@ 2014-05-13 10:08 ` Chen Fan
2014-05-13 10:08 ` [Qemu-devel] [RFC 3/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
2014-05-22 2:33 ` [Qemu-devel] [RFC 0/3] " chen.fan.fnst
3 siblings, 0 replies; 10+ messages in thread
From: Chen Fan @ 2014-05-13 10:08 UTC (permalink / raw)
To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber, Eduardo Habkost
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
Reviewed-by: Eduardo Habkost <ehabkost@redhat.com>
---
target-i386/topology.h | 33 +++++++++++++++++----------------
1 file changed, 17 insertions(+), 16 deletions(-)
diff --git a/target-i386/topology.h b/target-i386/topology.h
index 07a6c5f..e9ff89c 100644
--- a/target-i386/topology.h
+++ b/target-i386/topology.h
@@ -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 */
--
1.8.1.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [Qemu-devel] [RFC 3/3] cpu: add device_add foo-x86_64-cpu support
2014-05-13 10:08 [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
2014-05-13 10:08 ` [Qemu-devel] [RFC 1/3] using CPUMASK bitmaps to calculate cpu index Chen Fan
2014-05-13 10:08 ` [Qemu-devel] [RFC 2/3] cpu: introduce CpuTopoInfo structure for argument simplification Chen Fan
@ 2014-05-13 10:08 ` Chen Fan
2014-05-22 13:55 ` Igor Mammedov
2014-05-22 2:33 ` [Qemu-devel] [RFC 0/3] " chen.fan.fnst
3 siblings, 1 reply; 10+ messages in thread
From: Chen Fan @ 2014-05-13 10:08 UTC (permalink / raw)
To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber, Eduardo Habkost
In order to implement adding cpu with device_add, we should make the
check of APIC ID after object_init(), so add UserCreatable complete
method for checking APIC ID availability, and introduce cpu_physid_mask
for saving occupied APIC ID, then we could use -device foo-x86_64-cpu
without setting apic-id property to add default APIC IDs.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
include/qom/cpu.h | 2 ++
qdev-monitor.c | 11 ++++++
target-i386/cpu.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++-
target-i386/topology.h | 18 ++++++++++
4 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index b8f46b1..8ba9f7b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -151,6 +151,7 @@ typedef struct CPUClass {
const char *gdb_core_xml_file;
DECLARE_BITMAP(cpu_present_mask, MAX_CPUMASK_BITS);
+ DECLARE_BITMAP(cpu_physid_mask, MAX_CPUMASK_BITS);
} CPUClass;
#ifdef HOST_WORDS_BIGENDIAN
@@ -296,6 +297,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)
diff --git a/qdev-monitor.c b/qdev-monitor.c
index 02cbe43..36c200e 100644
--- a/qdev-monitor.c
+++ b/qdev-monitor.c
@@ -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
@@ -556,6 +557,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
return NULL;
}
+ user_creatable_complete(OBJECT(dev), &err);
+ if (err != NULL) {
+ qerror_report_err(err);
+ error_free(err);
+ object_unparent(OBJECT(dev));
+ object_unref(OBJECT(dev));
+ qerror_report(QERR_DEVICE_INIT_FAILED, driver);
+ return NULL;
+ }
+
dev->opts = opts;
object_property_set_bool(OBJECT(dev), true, "realized", &err);
if (err != NULL) {
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index 8f193a9..56cc3ad 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -48,6 +48,7 @@
#include "hw/i386/apic_internal.h"
#endif
+#include "qom/object_interfaces.h"
/* Cache topology CPUID constants: */
@@ -158,7 +159,7 @@
#define L2_ITLB_4K_ASSOC 4
#define L2_ITLB_4K_ENTRIES 512
-
+static int64_t cpu_2_physid[MAX_CPUMASK_BITS];
static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
uint32_t vendor2, uint32_t vendor3)
@@ -1546,12 +1547,16 @@ static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
const char *name, Error **errp)
{
+ CPUState *cs = CPU(obj);
+ CPUClass *cc = CPU_GET_CLASS(obj);
X86CPU *cpu = X86_CPU(obj);
DeviceState *dev = DEVICE(obj);
const int64_t min = 0;
const int64_t max = UINT32_MAX;
Error *error = NULL;
int64_t value;
+ X86CPUTopoInfo topo;
+ int64_t phys_id;
if (dev->realized) {
error_setg(errp, "Attempt to set property '%s' on '%s' after "
@@ -1571,10 +1576,28 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
return;
}
+ if (value > x86_cpu_apic_id_from_index(max_cpus - 1)) {
+ error_setg(errp, "CPU with APIC ID %" PRIi64
+ " is more than MAX APIC ID limits", value);
+ return;
+ }
+
+ x86_topo_ids_from_apic_id(smp_cores, smp_threads, value, &topo);
+ if (topo.smt_id >= smp_threads || topo.core_id >= smp_cores) {
+ error_setg(errp, "CPU with APIC ID %" PRIi64 " does not match "
+ "topology configuration.", value);
+ return;
+ }
+
if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
return;
}
+
+ phys_id = (topo.smt_id + topo.core_id * smp_threads
+ + topo.pkg_id * smp_cores * smp_threads);
+ set_bit(phys_id, cc->cpu_physid_mask);
+ cpu_2_physid[cs->cpu_index] = phys_id;
cpu->env.cpuid_apic_id = value;
}
@@ -1999,12 +2022,57 @@ out:
return cpu;
}
+static void x86_cpu_cpudef_instance_init(Object *obj)
+{
+ DeviceState *dev = DEVICE(obj);
+ X86CPU *cpu = X86_CPU(obj);
+ CPUX86State *env = &cpu->env;
+
+ dev->hotplugged = true;
+
+ env->cpuid_apic_id = ~0U;
+}
+
+static void x86_cpu_cpudef_complete(UserCreatable *uc, Error **errp)
+{
+ CPUState *cs = CPU(uc);
+ X86CPU *cpu = X86_CPU(uc);
+ CPUClass *cc = CPU_GET_CLASS(OBJECT(uc));
+ int64_t phys_id;
+
+ if (cpu->env.cpuid_apic_id != ~0U) {
+ return;
+ }
+
+ phys_id = find_first_zero_bit(cc->cpu_physid_mask, MAX_CPUMASK_BITS);
+ if (phys_id > max_cpus - 1) {
+ error_setg(errp, "Unable to add CPU %" PRIi64 " is larger than "
+ "max allowed: %d", phys_id, max_cpus - 1);
+ return;
+ }
+
+ set_bit(phys_id, cc->cpu_physid_mask);
+ cpu_2_physid[cs->cpu_index] = phys_id;
+ cpu->env.cpuid_apic_id = x86_cpu_apic_id_from_index(phys_id);
+}
+
static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
{
X86CPUDefinition *cpudef = data;
X86CPUClass *xcc = X86_CPU_CLASS(oc);
+ DeviceClass *dc = DEVICE_CLASS(oc);
+ UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
+ int i;
xcc->cpu_def = cpudef;
+
+ ucc->complete = x86_cpu_cpudef_complete;
+
+ dc->cannot_instantiate_with_device_add_yet = false;
+
+ for (i = 0; i < MAX_CPUMASK_BITS; i++) {
+ cpu_2_physid[i] = -1;
+ }
}
static void x86_register_cpudef_type(X86CPUDefinition *def)
@@ -2013,8 +2081,14 @@ static void x86_register_cpudef_type(X86CPUDefinition *def)
TypeInfo ti = {
.name = typename,
.parent = TYPE_X86_CPU,
+ .instance_size = sizeof(X86CPU),
+ .instance_init = x86_cpu_cpudef_instance_init,
.class_init = x86_cpu_cpudef_class_init,
.class_data = def,
+ .interfaces = (InterfaceInfo[]) {
+ { TYPE_USER_CREATABLE },
+ { }
+ }
};
type_register(&ti);
@@ -2738,6 +2812,20 @@ static void x86_cpu_initfn(Object *obj)
}
}
+static void x86_cpu_finalizefn(Object *obj)
+{
+ CPUState *cs = CPU(obj);
+ CPUClass *cc = CPU_GET_CLASS(obj);
+
+ CPU_REMOVE(cs);
+
+ clear_bit(cs->cpu_index, cc->cpu_present_mask);
+ if (cpu_2_physid[cs->cpu_index] != -1) {
+ clear_bit(cpu_2_physid[cs->cpu_index], cc->cpu_physid_mask);
+ cpu_2_physid[cs->cpu_index] = -1;
+ }
+}
+
static int64_t x86_cpu_get_arch_id(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -2837,6 +2925,7 @@ static const TypeInfo x86_cpu_type_info = {
.parent = TYPE_CPU,
.instance_size = sizeof(X86CPU),
.instance_init = x86_cpu_initfn,
+ .instance_finalize = x86_cpu_finalizefn,
.abstract = true,
.class_size = sizeof(X86CPUClass),
.class_init = x86_cpu_common_class_init,
diff --git a/target-i386/topology.h b/target-i386/topology.h
index e9ff89c..dcb4988 100644
--- a/target-i386/topology.h
+++ b/target-i386/topology.h
@@ -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 */
--
1.8.1.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support
2014-05-13 10:08 [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
` (2 preceding siblings ...)
2014-05-13 10:08 ` [Qemu-devel] [RFC 3/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
@ 2014-05-22 2:33 ` chen.fan.fnst
2014-05-22 10:49 ` Andreas Färber
2014-05-22 13:33 ` Igor Mammedov
3 siblings, 2 replies; 10+ messages in thread
From: chen.fan.fnst @ 2014-05-22 2:33 UTC (permalink / raw)
To: qemu-devel@nongnu.org; +Cc: Igor Mammedov, Andreas Färber, Eduardo Habkost
Hi,
I think if we want to use 'device/device_add' to implement CPU,
we must do some check before qemu_init_vcpu(). how can we to do that?
Thanks,
Chen
On Tue, 2014-05-13 at 18:08 +0800, Chen Fan wrote:
> this patches tried to make cpu hotplug with device_add,
> and made -device foo-x86_64-cpu available,also we can
> set apic-id property with command line, if without setting
> apic-id property, we added first unoccupied apic id as the
> default new apic id. and hotplug cpu with device_add, we
> must make check of APIC ID after cpu object initialization
> that was different from 'cpu_add' command which check 'ids'
> at the beginning.
>
> Chen Fan (3):
> using CPUMASK bitmaps to calculate cpu index
> cpu: introduce CpuTopoInfo structure for argument simplification
> cpu: add device_add foo-x86_64-cpu support
>
> exec.c | 9 +++--
> include/qom/cpu.h | 11 ++++++
> include/sysemu/sysemu.h | 7 ----
> qdev-monitor.c | 11 ++++++
> target-i386/cpu.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++-
> target-i386/topology.h | 51 ++++++++++++++++++---------
> 6 files changed, 151 insertions(+), 29 deletions(-)
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support
2014-05-22 2:33 ` [Qemu-devel] [RFC 0/3] " chen.fan.fnst
@ 2014-05-22 10:49 ` Andreas Färber
2014-05-22 14:52 ` Eduardo Habkost
2014-05-22 13:33 ` Igor Mammedov
1 sibling, 1 reply; 10+ messages in thread
From: Andreas Färber @ 2014-05-22 10:49 UTC (permalink / raw)
To: chen.fan.fnst@cn.fujitsu.com, qemu-devel@nongnu.org
Cc: Igor Mammedov, Eduardo Habkost, Marcel Apfelbaum
Hi,
Am 22.05.2014 04:33, schrieb chen.fan.fnst@cn.fujitsu.com:
> I think if we want to use 'device/device_add' to implement CPU,
> we must do some check before qemu_init_vcpu(). how can we to do that?
We ran into such problems before... If need be, we can change from the
old parent_realize scheme to the base class calling the derived realize
function in-order, or we can add new hooks to CPUClass as necessary.
Consider me a bit skeptical about MAX_CPUMASK_BITS in 1/3. This should
at least be tied to the maximum allowed for QEMUMachine/MachineClass
rather than hardcoded to 255, which people may forget to synchronize.
There was a recent attempt to increase the limits.
2/3 looks good apart from the subject; I could cherry-pick that, seeing
there is Reviewed-by, if you like.
3/3 is doing a bit much to digest at once for my taste.
Regards,
Andreas
> On Tue, 2014-05-13 at 18:08 +0800, Chen Fan wrote:
>> this patches tried to make cpu hotplug with device_add,
>> and made -device foo-x86_64-cpu available,also we can
>> set apic-id property with command line, if without setting
>> apic-id property, we added first unoccupied apic id as the
>> default new apic id. and hotplug cpu with device_add, we
>> must make check of APIC ID after cpu object initialization
>> that was different from 'cpu_add' command which check 'ids'
>> at the beginning.
>>
>> Chen Fan (3):
>> using CPUMASK bitmaps to calculate cpu index
>> cpu: introduce CpuTopoInfo structure for argument simplification
>> cpu: add device_add foo-x86_64-cpu support
>>
>> exec.c | 9 +++--
>> include/qom/cpu.h | 11 ++++++
>> include/sysemu/sysemu.h | 7 ----
>> qdev-monitor.c | 11 ++++++
>> target-i386/cpu.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++-
>> target-i386/topology.h | 51 ++++++++++++++++++---------
>> 6 files changed, 151 insertions(+), 29 deletions(-)
--
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [RFC 1/3] using CPUMASK bitmaps to calculate cpu index
2014-05-13 10:08 ` [Qemu-devel] [RFC 1/3] using CPUMASK bitmaps to calculate cpu index Chen Fan
@ 2014-05-22 13:26 ` Igor Mammedov
0 siblings, 0 replies; 10+ messages in thread
From: Igor Mammedov @ 2014-05-22 13:26 UTC (permalink / raw)
To: Chen Fan; +Cc: qemu-devel, Eduardo Habkost, Andreas Färber
On Tue, 13 May 2014 18:08:47 +0800
Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> instead of seeking the number of CPUs, using CPUMASK bitmaps to
> calculate the cpu index, also would be a gread benefit to remove
> cpu index.
How would it help to remove cpu_index?
What if there is only one CPU at start nad there is a need to add
CPU with cpu_index==10?
Bitmap hardly changes here anything, it's just another way of
doing:
cpu_index = 0;
CPU_FOREACH(some_cpu) {
cpu_index++;
}
What would help however is replacing cpu_index at read points with
CPUClass->get_arch_id()
Then targets that need sparse index could override default
get_arch_id() to suite their needs and use their own properties
to set arch_id value.
Caution: this change would cause migration breakage for target-i386,
so x86_cpu_get_arch_id() should take care about it when used with old
machine types.
>
> Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
> ---
> exec.c | 9 ++++-----
> include/qom/cpu.h | 9 +++++++++
> include/sysemu/sysemu.h | 7 -------
> 3 files changed, 13 insertions(+), 12 deletions(-)
>
> diff --git a/exec.c b/exec.c
> index cf12049..2948841 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -473,16 +473,15 @@ void cpu_exec_init(CPUArchState *env)
> {
> CPUState *cpu = ENV_GET_CPU(env);
> CPUClass *cc = CPU_GET_CLASS(cpu);
> - CPUState *some_cpu;
> int cpu_index;
>
> #if defined(CONFIG_USER_ONLY)
> cpu_list_lock();
> #endif
> - cpu_index = 0;
> - CPU_FOREACH(some_cpu) {
> - cpu_index++;
> - }
> + cpu_index = find_first_zero_bit(cc->cpu_present_mask,
> + MAX_CPUMASK_BITS);
> + set_bit(cpu_index, cc->cpu_present_mask);
> +
> cpu->cpu_index = cpu_index;
> cpu->numa_node = 0;
> QTAILQ_INIT(&cpu->breakpoints);
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index df977c8..b8f46b1 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -70,6 +70,13 @@ typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
>
> struct TranslationBlock;
>
> +/* The following shall be true for all CPUs:
> + * cpu->cpu_index < max_cpus <= MAX_CPUMASK_BITS
> + *
> + * Note that cpu->get_arch_id() may be larger than MAX_CPUMASK_BITS.
> + */
> +#define MAX_CPUMASK_BITS 255
> +
> /**
> * CPUClass:
> * @class_by_name: Callback to map -cpu command line model name to an
> @@ -142,6 +149,8 @@ typedef struct CPUClass {
> const struct VMStateDescription *vmsd;
> int gdb_num_core_regs;
> const char *gdb_core_xml_file;
> +
> + DECLARE_BITMAP(cpu_present_mask, MAX_CPUMASK_BITS);
> } CPUClass;
>
> #ifdef HOST_WORDS_BIGENDIAN
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index ba5c7f8..04edb8b 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -134,13 +134,6 @@ extern QEMUClockType rtc_clock;
>
> #define MAX_NODES 64
>
> -/* The following shall be true for all CPUs:
> - * cpu->cpu_index < max_cpus <= MAX_CPUMASK_BITS
> - *
> - * Note that cpu->get_arch_id() may be larger than MAX_CPUMASK_BITS.
> - */
> -#define MAX_CPUMASK_BITS 255
> -
> extern int nb_numa_nodes;
> extern uint64_t node_mem[MAX_NODES];
> extern unsigned long *node_cpumask[MAX_NODES];
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support
2014-05-22 2:33 ` [Qemu-devel] [RFC 0/3] " chen.fan.fnst
2014-05-22 10:49 ` Andreas Färber
@ 2014-05-22 13:33 ` Igor Mammedov
1 sibling, 0 replies; 10+ messages in thread
From: Igor Mammedov @ 2014-05-22 13:33 UTC (permalink / raw)
To: chen.fan.fnst@cn.fujitsu.com
Cc: qemu-devel@nongnu.org, Eduardo Habkost, Andreas Färber
On Thu, 22 May 2014 02:33:45 +0000
"chen.fan.fnst@cn.fujitsu.com" <chen.fan.fnst@cn.fujitsu.com> wrote:
> Hi,
> I think if we want to use 'device/device_add' to implement CPU,
> we must do some check before qemu_init_vcpu(). how can we to do that?
What check exactly would you like to perform?
For target-i38 you can look for kvm_check_features_against_host() in
x86_cpu_realizefn() doing check before qemu_init_vcpu().
>
> Thanks,
> Chen
>
> On Tue, 2014-05-13 at 18:08 +0800, Chen Fan wrote:
> > this patches tried to make cpu hotplug with device_add,
> > and made -device foo-x86_64-cpu available,also we can
> > set apic-id property with command line, if without setting
> > apic-id property, we added first unoccupied apic id as the
> > default new apic id. and hotplug cpu with device_add, we
> > must make check of APIC ID after cpu object initialization
> > that was different from 'cpu_add' command which check 'ids'
> > at the beginning.
> >
> > Chen Fan (3):
> > using CPUMASK bitmaps to calculate cpu index
> > cpu: introduce CpuTopoInfo structure for argument simplification
> > cpu: add device_add foo-x86_64-cpu support
> >
> > exec.c | 9 +++--
> > include/qom/cpu.h | 11 ++++++
> > include/sysemu/sysemu.h | 7 ----
> > qdev-monitor.c | 11 ++++++
> > target-i386/cpu.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++++-
> > target-i386/topology.h | 51 ++++++++++++++++++---------
> > 6 files changed, 151 insertions(+), 29 deletions(-)
> >
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [RFC 3/3] cpu: add device_add foo-x86_64-cpu support
2014-05-13 10:08 ` [Qemu-devel] [RFC 3/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
@ 2014-05-22 13:55 ` Igor Mammedov
0 siblings, 0 replies; 10+ messages in thread
From: Igor Mammedov @ 2014-05-22 13:55 UTC (permalink / raw)
To: Chen Fan; +Cc: qemu-devel, Eduardo Habkost, Andreas Färber
On Tue, 13 May 2014 18:08:49 +0800
Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> In order to implement adding cpu with device_add, we should make the
> check of APIC ID after object_init(), so add UserCreatable complete
> method for checking APIC ID availability, and introduce cpu_physid_mask
> for saving occupied APIC ID, then we could use -device foo-x86_64-cpu
> without setting apic-id property to add default APIC IDs.
Currently there is 2 places where APIC id could be checked:
x86_cpuid_set_apic_id() - property setter, currently checks for duplicate
x86_cpu_realizefn() ->
x86_cpu_apic_create() ->
qdev_prop_set_uint8(cpu->apic_state, "id", env->cpuid_apic_id);
It would be better to add necessary checks there instead of
adding yet another bitmap for APIC id to maintain.
And I didn't quite get why user_creatable interface was used here,
would you elaborate on it?
>
> Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
> ---
> include/qom/cpu.h | 2 ++
> qdev-monitor.c | 11 ++++++
> target-i386/cpu.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++-
> target-i386/topology.h | 18 ++++++++++
> 4 files changed, 121 insertions(+), 1 deletion(-)
>
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index b8f46b1..8ba9f7b 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -151,6 +151,7 @@ typedef struct CPUClass {
> const char *gdb_core_xml_file;
>
> DECLARE_BITMAP(cpu_present_mask, MAX_CPUMASK_BITS);
> + DECLARE_BITMAP(cpu_physid_mask, MAX_CPUMASK_BITS);
> } CPUClass;
>
> #ifdef HOST_WORDS_BIGENDIAN
> @@ -296,6 +297,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)
> diff --git a/qdev-monitor.c b/qdev-monitor.c
> index 02cbe43..36c200e 100644
> --- a/qdev-monitor.c
> +++ b/qdev-monitor.c
> @@ -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
> @@ -556,6 +557,16 @@ DeviceState *qdev_device_add(QemuOpts *opts)
> return NULL;
> }
>
> + user_creatable_complete(OBJECT(dev), &err);
> + if (err != NULL) {
> + qerror_report_err(err);
> + error_free(err);
> + object_unparent(OBJECT(dev));
> + object_unref(OBJECT(dev));
> + qerror_report(QERR_DEVICE_INIT_FAILED, driver);
> + return NULL;
> + }
> +
> dev->opts = opts;
> object_property_set_bool(OBJECT(dev), true, "realized", &err);
> if (err != NULL) {
> diff --git a/target-i386/cpu.c b/target-i386/cpu.c
> index 8f193a9..56cc3ad 100644
> --- a/target-i386/cpu.c
> +++ b/target-i386/cpu.c
> @@ -48,6 +48,7 @@
> #include "hw/i386/apic_internal.h"
> #endif
>
> +#include "qom/object_interfaces.h"
>
> /* Cache topology CPUID constants: */
>
> @@ -158,7 +159,7 @@
> #define L2_ITLB_4K_ASSOC 4
> #define L2_ITLB_4K_ENTRIES 512
>
> -
> +static int64_t cpu_2_physid[MAX_CPUMASK_BITS];
>
> static void x86_cpu_vendor_words2str(char *dst, uint32_t vendor1,
> uint32_t vendor2, uint32_t vendor3)
> @@ -1546,12 +1547,16 @@ static void x86_cpuid_get_apic_id(Object *obj, Visitor *v, void *opaque,
> static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
> const char *name, Error **errp)
> {
> + CPUState *cs = CPU(obj);
> + CPUClass *cc = CPU_GET_CLASS(obj);
> X86CPU *cpu = X86_CPU(obj);
> DeviceState *dev = DEVICE(obj);
> const int64_t min = 0;
> const int64_t max = UINT32_MAX;
> Error *error = NULL;
> int64_t value;
> + X86CPUTopoInfo topo;
> + int64_t phys_id;
>
> if (dev->realized) {
> error_setg(errp, "Attempt to set property '%s' on '%s' after "
> @@ -1571,10 +1576,28 @@ static void x86_cpuid_set_apic_id(Object *obj, Visitor *v, void *opaque,
> return;
> }
>
> + if (value > x86_cpu_apic_id_from_index(max_cpus - 1)) {
> + error_setg(errp, "CPU with APIC ID %" PRIi64
> + " is more than MAX APIC ID limits", value);
> + return;
> + }
> +
> + x86_topo_ids_from_apic_id(smp_cores, smp_threads, value, &topo);
> + if (topo.smt_id >= smp_threads || topo.core_id >= smp_cores) {
> + error_setg(errp, "CPU with APIC ID %" PRIi64 " does not match "
> + "topology configuration.", value);
> + return;
> + }
> +
> if ((value != cpu->env.cpuid_apic_id) && cpu_exists(value)) {
> error_setg(errp, "CPU with APIC ID %" PRIi64 " exists", value);
> return;
> }
> +
> + phys_id = (topo.smt_id + topo.core_id * smp_threads
> + + topo.pkg_id * smp_cores * smp_threads);
> + set_bit(phys_id, cc->cpu_physid_mask);
> + cpu_2_physid[cs->cpu_index] = phys_id;
> cpu->env.cpuid_apic_id = value;
> }
>
> @@ -1999,12 +2022,57 @@ out:
> return cpu;
> }
>
> +static void x86_cpu_cpudef_instance_init(Object *obj)
> +{
> + DeviceState *dev = DEVICE(obj);
> + X86CPU *cpu = X86_CPU(obj);
> + CPUX86State *env = &cpu->env;
> +
> + dev->hotplugged = true;
> +
> + env->cpuid_apic_id = ~0U;
> +}
> +
> +static void x86_cpu_cpudef_complete(UserCreatable *uc, Error **errp)
> +{
> + CPUState *cs = CPU(uc);
> + X86CPU *cpu = X86_CPU(uc);
> + CPUClass *cc = CPU_GET_CLASS(OBJECT(uc));
> + int64_t phys_id;
> +
> + if (cpu->env.cpuid_apic_id != ~0U) {
> + return;
> + }
> +
> + phys_id = find_first_zero_bit(cc->cpu_physid_mask, MAX_CPUMASK_BITS);
> + if (phys_id > max_cpus - 1) {
> + error_setg(errp, "Unable to add CPU %" PRIi64 " is larger than "
> + "max allowed: %d", phys_id, max_cpus - 1);
> + return;
> + }
> +
> + set_bit(phys_id, cc->cpu_physid_mask);
> + cpu_2_physid[cs->cpu_index] = phys_id;
> + cpu->env.cpuid_apic_id = x86_cpu_apic_id_from_index(phys_id);
> +}
> +
> static void x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
> {
> X86CPUDefinition *cpudef = data;
> X86CPUClass *xcc = X86_CPU_CLASS(oc);
> + DeviceClass *dc = DEVICE_CLASS(oc);
> + UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
> + int i;
>
> xcc->cpu_def = cpudef;
> +
> + ucc->complete = x86_cpu_cpudef_complete;
> +
> + dc->cannot_instantiate_with_device_add_yet = false;
> +
> + for (i = 0; i < MAX_CPUMASK_BITS; i++) {
> + cpu_2_physid[i] = -1;
> + }
> }
>
> static void x86_register_cpudef_type(X86CPUDefinition *def)
> @@ -2013,8 +2081,14 @@ static void x86_register_cpudef_type(X86CPUDefinition *def)
> TypeInfo ti = {
> .name = typename,
> .parent = TYPE_X86_CPU,
> + .instance_size = sizeof(X86CPU),
> + .instance_init = x86_cpu_cpudef_instance_init,
> .class_init = x86_cpu_cpudef_class_init,
> .class_data = def,
> + .interfaces = (InterfaceInfo[]) {
> + { TYPE_USER_CREATABLE },
> + { }
> + }
> };
>
> type_register(&ti);
> @@ -2738,6 +2812,20 @@ static void x86_cpu_initfn(Object *obj)
> }
> }
>
> +static void x86_cpu_finalizefn(Object *obj)
> +{
> + CPUState *cs = CPU(obj);
> + CPUClass *cc = CPU_GET_CLASS(obj);
> +
> + CPU_REMOVE(cs);
> +
> + clear_bit(cs->cpu_index, cc->cpu_present_mask);
> + if (cpu_2_physid[cs->cpu_index] != -1) {
> + clear_bit(cpu_2_physid[cs->cpu_index], cc->cpu_physid_mask);
> + cpu_2_physid[cs->cpu_index] = -1;
> + }
> +}
> +
> static int64_t x86_cpu_get_arch_id(CPUState *cs)
> {
> X86CPU *cpu = X86_CPU(cs);
> @@ -2837,6 +2925,7 @@ static const TypeInfo x86_cpu_type_info = {
> .parent = TYPE_CPU,
> .instance_size = sizeof(X86CPU),
> .instance_init = x86_cpu_initfn,
> + .instance_finalize = x86_cpu_finalizefn,
> .abstract = true,
> .class_size = sizeof(X86CPUClass),
> .class_init = x86_cpu_common_class_init,
> diff --git a/target-i386/topology.h b/target-i386/topology.h
> index e9ff89c..dcb4988 100644
> --- a/target-i386/topology.h
> +++ b/target-i386/topology.h
> @@ -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 */
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support
2014-05-22 10:49 ` Andreas Färber
@ 2014-05-22 14:52 ` Eduardo Habkost
0 siblings, 0 replies; 10+ messages in thread
From: Eduardo Habkost @ 2014-05-22 14:52 UTC (permalink / raw)
To: Andreas Färber
Cc: chen.fan.fnst@cn.fujitsu.com, Igor Mammedov,
qemu-devel@nongnu.org, Marcel Apfelbaum
On Thu, May 22, 2014 at 12:49:26PM +0200, Andreas Färber wrote:
> Hi,
>
> Am 22.05.2014 04:33, schrieb chen.fan.fnst@cn.fujitsu.com:
> > I think if we want to use 'device/device_add' to implement CPU,
> > we must do some check before qemu_init_vcpu(). how can we to do that?
>
> We ran into such problems before... If need be, we can change from the
> old parent_realize scheme to the base class calling the derived realize
> function in-order, or we can add new hooks to CPUClass as necessary.
>
> Consider me a bit skeptical about MAX_CPUMASK_BITS in 1/3. This should
> at least be tied to the maximum allowed for QEMUMachine/MachineClass
> rather than hardcoded to 255, which people may forget to synchronize.
> There was a recent attempt to increase the limits.
I agree that on new code we should avoid using static bitmap sizes and
use max_cpus instead.
MAX_CPUMASK_BITS only exists because there was existing code using
static limits to bitmaps. If we change all existing code to use max_cpus
to dynamically allocate bitmaps, we can drop it.
--
Eduardo
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2014-05-22 14:52 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-13 10:08 [Qemu-devel] [RFC 0/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
2014-05-13 10:08 ` [Qemu-devel] [RFC 1/3] using CPUMASK bitmaps to calculate cpu index Chen Fan
2014-05-22 13:26 ` Igor Mammedov
2014-05-13 10:08 ` [Qemu-devel] [RFC 2/3] cpu: introduce CpuTopoInfo structure for argument simplification Chen Fan
2014-05-13 10:08 ` [Qemu-devel] [RFC 3/3] cpu: add device_add foo-x86_64-cpu support Chen Fan
2014-05-22 13:55 ` Igor Mammedov
2014-05-22 2:33 ` [Qemu-devel] [RFC 0/3] " chen.fan.fnst
2014-05-22 10:49 ` Andreas Färber
2014-05-22 14:52 ` Eduardo Habkost
2014-05-22 13:33 ` 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).