* [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
* 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
* [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 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-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 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
* 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
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).