add cpu-topology.h cpu-topology.c files for prebuilding cpu qom tree "/machine/node[X]/socket[Y]/core[Z]->link cpu"
Signed-off-by: Chen Fan <chen.fan.f...@cn.fujitsu.com> --- hw/i386/pc.c | 3 + target-i386/Makefile.objs | 2 +- target-i386/cpu-topology.c | 199 +++++++++++++++++++++++++++++++++++++++++++++ target-i386/cpu-topology.h | 71 ++++++++++++++++ target-i386/cpu.c | 22 +++++ target-i386/cpu.h | 3 + 6 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 target-i386/cpu-topology.c create mode 100644 target-i386/cpu-topology.h diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 84a017e..8a489f5 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -941,6 +941,7 @@ static X86CPU *pc_new_cpu(const char *cpu_model, X86CPUTopoInfo *topo, object_property_set_int(OBJECT(cpu), topo->apic_id, "apic-id", &local_err); object_property_set_bool(OBJECT(cpu), true, "realized", &local_err); + x86_topo_cpu_set_link(OBJECT(cpu), topo, &local_err); if (local_err) { error_propagate(errp, local_err); @@ -996,6 +997,8 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge) } current_cpu_model = cpu_model; + cpu_topo_init(); + for (i = 0; i < smp_cpus; i++) { X86CPUTopoInfo topo; x86_cpu_topo_ids_from_index(i, &topo); diff --git a/target-i386/Makefile.objs b/target-i386/Makefile.objs index 027b94e..239474d 100644 --- a/target-i386/Makefile.objs +++ b/target-i386/Makefile.objs @@ -1,4 +1,4 @@ -obj-y += translate.o helper.o cpu.o +obj-y += translate.o helper.o cpu.o cpu-topology.o obj-y += excp_helper.o fpu_helper.o cc_helper.o int_helper.o svm_helper.o obj-y += smm_helper.o misc_helper.o mem_helper.o seg_helper.o obj-y += gdbstub.o diff --git a/target-i386/cpu-topology.c b/target-i386/cpu-topology.c new file mode 100644 index 0000000..e611bae --- /dev/null +++ b/target-i386/cpu-topology.c @@ -0,0 +1,199 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2014 Fujitsu Ltd. + * Author: Chen Fan <chen.fan.f...@cn.fujitsu.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qom/object.h" +#include "qemu/module.h" +#include "hw/hw.h" +#include "sysemu/cpus.h" +#include "sysemu/sysemu.h" +#include "cpu-topology.h" + +static QTAILQ_HEAD(, SocketState) sockets = QTAILQ_HEAD_INITIALIZER(sockets); +static QTAILQ_HEAD(, NodeState) nodes = QTAILQ_HEAD_INITIALIZER(nodes); + +static NodeState *node_get(int node_id) +{ + NodeState *node; + + QTAILQ_FOREACH(node, &nodes, next) { + if (node->node_id == node_id) { + return node; + } + } + return NULL; +} + +static SocketState *cpu_socket_find(int pkg_id) +{ + SocketState *ss; + + QTAILQ_FOREACH(ss, &sockets, next) { + if (ss->socket_id == pkg_id) { + return ss; + } + } + return NULL; +} + +void cpu_topo_init(void) +{ + unsigned long *node_mask; + int i; + + node_mask = bitmap_new(MAX_NODES); + + for (i = 0; i < max_cpus; i++) { + NodeState *node; + SocketState *ss; + gchar *name; + int node_id = 0, socket_id; + int j; + + for (j = 0; j < nb_numa_nodes; j++) { + if (test_bit(i, node_cpumask[j])) { + node_id = j; + break; + } + } + + if (test_bit(node_id, node_mask)) { + node = node_get(node_id); + } else { + node = NODE(object_new(TYPE_NODE)); + node->node_id = node_id; + name = g_strdup_printf("node[%" PRIu32 "]", node_id); + object_property_add_child(qdev_get_machine(), name, + OBJECT(node), NULL); + set_bit(node_id, node_mask); + g_free(name); + QTAILQ_INSERT_TAIL(&nodes, node, next); + } + + socket_id = i / (smp_cores * smp_threads); + ss = cpu_socket_find(socket_id); + if (!ss) { + ss = SOCKET(object_new(TYPE_SOCKET)); + ss->socket_id = socket_id; + name = g_strdup_printf("socket[%" PRIu32 "]", socket_id); + object_property_add_child(OBJECT(node), name, + OBJECT(ss), NULL); + g_free(name); + QTAILQ_INSERT_TAIL(&sockets, ss, next); + } + } + + g_free(node_mask); +} + +CoreState *cpu_topo_object_core_find(X86CPUTopoInfo *topo) +{ + SocketState *ss; + CoreState *core; + + ss = cpu_socket_find(topo->pkg_id); + if (!ss) { + return NULL; + } + + QTAILQ_FOREACH(core, &ss->children, sibling) { + if (core->core_id == topo->core_id) { + return core; + } + } + return NULL; +} + +static void socket_initfn(Object *obj) +{ + SocketState *ss = SOCKET(obj); + int i; + + QTAILQ_INIT(&ss->children); + + for (i = 0; i < smp_cores; i++) { + gchar *name; + CoreState *core; + + core = CORE(object_new(TYPE_CORE)); + core->core_id = i; + QTAILQ_INSERT_TAIL(&ss->children, core, sibling); + + name = g_strdup_printf("core[%" PRIu32 "]", i); + object_property_add_child(obj, name, OBJECT(core), NULL); + g_free(name); + } +} + +static void core_initfn(Object *obj) +{ + CoreState *cs = CORE(obj); + gchar *name; + int i; + + cs->link_cpu = g_malloc0(sizeof(CPUState *) * smp_threads); + for (i = 0; i < smp_threads; i++) { + name = g_strdup_printf("cpu[%" PRIu32 "]", i); + object_property_add_link(obj, name, TYPE_CPU, + (Object **)&cs->link_cpu[i], NULL); + g_free(name); + } +} + +static void core_fini(Object *obj) +{ + CoreState *cs = CORE(obj); + + g_free(cs->link_cpu); +} + +static const TypeInfo core_type_info = { + .name = TYPE_CORE, + .parent = TYPE_OBJECT, + .instance_size = sizeof(CoreState), + .instance_init = core_initfn, + .instance_finalize = core_fini, +}; + +static const TypeInfo socket_type_info = { + .name = TYPE_SOCKET, + .parent = TYPE_OBJECT, + .instance_size = sizeof(SocketState), + .instance_init = socket_initfn, +}; + +static const TypeInfo node_type_info = { + .name = TYPE_NODE, + .parent = TYPE_OBJECT, + .instance_size = sizeof(NodeState), +}; + +static void node_register_types(void) +{ + type_register_static(&node_type_info); + type_register_static(&socket_type_info); + type_register_static(&core_type_info); +} + +type_init(node_register_types) diff --git a/target-i386/cpu-topology.h b/target-i386/cpu-topology.h new file mode 100644 index 0000000..6465d94 --- /dev/null +++ b/target-i386/cpu-topology.h @@ -0,0 +1,71 @@ +/* + * QEMU System Emulator + * + * Copyright (c) 2014 Fujitsu Ltd. + * Author: Chen Fan <chen.fan.f...@cn.fujitsu.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef TARGET_I386_CPU_TOPOLOGY_H +#define TARGET_I386_CPU_TOPOLOGY_H + +#include "hw/qdev-core.h" +#include "cpu.h" +#include "qom/cpu.h" + +#define TYPE_NODE "node" +#define TYPE_SOCKET "socket" +#define TYPE_CORE "core" + +#define NODE(obj) OBJECT_CHECK(NodeState, (obj), TYPE_NODE) + +#define SOCKET(obj) OBJECT_CHECK(SocketState, (obj), TYPE_SOCKET) + +#define CORE(obj) OBJECT_CHECK(CoreState, (obj), TYPE_CORE) + +typedef struct CoreState { + /*< private >*/ + Object parent_obj; + /*< public >*/ + int core_id; + QTAILQ_ENTRY(CoreState) sibling; + CPUState **link_cpu; +} CoreState; + +typedef struct SocketState { + /*< private >*/ + Object parent_obj; + /*< public >*/ + unsigned socket_id; + QTAILQ_HEAD(ChildHread, CoreState) children; + QTAILQ_ENTRY(SocketState) next; +} SocketState; + +typedef struct NodeState { + /*< private >*/ + Object parent_obj; + /*< public >*/ + int node_id; + QTAILQ_ENTRY(NodeState) next; +} NodeState; + +CoreState *cpu_topo_object_core_find(X86CPUTopoInfo *topo); +void cpu_topo_init(void); + +#endif /* TARGET_I386_CPU_TOPOLOGY_H */ diff --git a/target-i386/cpu.c b/target-i386/cpu.c index 6f2ba1c..9754ac2 100644 --- a/target-i386/cpu.c +++ b/target-i386/cpu.c @@ -2698,6 +2698,28 @@ static void x86_cpu_synchronize_from_tb(CPUState *cs, TranslationBlock *tb) cpu->env.eip = tb->pc - tb->cs_base; } +void x86_topo_cpu_set_link(Object *obj, X86CPUTopoInfo *topo, Error **errp) +{ + gchar *name; + CoreState *core; + Error *local_err = NULL; + + core = cpu_topo_object_core_find(topo); + if (!core) { + error_set(&local_err, QERR_DEVICE_NOT_FOUND, TYPE_CORE); + goto out; + } + + name = g_strdup_printf("cpu[%" PRIu32 "]", topo->smt_id); + object_property_set_link(OBJECT(core), obj, name, &local_err); + g_free(name); + +out: + if (local_err != NULL) { + error_propagate(errp, local_err); + } +} + static Property x86_cpu_properties[] = { DEFINE_PROP_BOOL("pmu", X86CPU, enable_pmu, false), { .name = "hv-spinlocks", .info = &qdev_prop_spinlocks }, diff --git a/target-i386/cpu.h b/target-i386/cpu.h index a410b16..42db0fd 100644 --- a/target-i386/cpu.h +++ b/target-i386/cpu.h @@ -24,6 +24,7 @@ #include "sysemu/cpus.h" #include "topology.h" +#include "cpu-topology.h" #ifdef TARGET_X86_64 #define TARGET_LONG_BITS 64 @@ -1293,6 +1294,8 @@ void x86_cpu_topo_ids_from_index(unsigned int cpu_index, X86CPUTopoInfo *topo); void enable_compat_apic_id_mode(void); +void x86_topo_cpu_set_link(Object *obj, X86CPUTopoInfo *topo, Error **errp); + #define APIC_DEFAULT_ADDRESS 0xfee00000 #define APIC_SPACE_SIZE 0x100000 -- 1.8.1.4