]> git.proxmox.com Git - mirror_qemu.git/blob - hw/ppc/spapr_cpu_core.c
spapr: Abstract CPU core device and type specific core devices
[mirror_qemu.git] / hw / ppc / spapr_cpu_core.c
1 /*
2 * sPAPR CPU core device, acts as container of CPU thread devices.
3 *
4 * Copyright (C) 2016 Bharata B Rao <bharata@linux.vnet.ibm.com>
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
9 #include "hw/cpu/core.h"
10 #include "hw/ppc/spapr_cpu_core.h"
11 #include "target-ppc/cpu.h"
12 #include "hw/ppc/spapr.h"
13 #include "hw/boards.h"
14 #include "qapi/error.h"
15 #include <sysemu/cpus.h>
16 #include "target-ppc/kvm_ppc.h"
17
18 static int spapr_cpu_core_realize_child(Object *child, void *opaque)
19 {
20 Error **errp = opaque;
21 sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
22 CPUState *cs = CPU(child);
23 PowerPCCPU *cpu = POWERPC_CPU(cs);
24
25 object_property_set_bool(child, true, "realized", errp);
26 if (*errp) {
27 return 1;
28 }
29
30 spapr_cpu_init(spapr, cpu, errp);
31 if (*errp) {
32 return 1;
33 }
34 return 0;
35 }
36
37 static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
38 {
39 sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
40 CPUCore *cc = CPU_CORE(OBJECT(dev));
41 const char *typename = object_class_get_name(sc->cpu_class);
42 size_t size = object_type_get_instance_size(typename);
43 Error *local_err = NULL;
44 Object *obj;
45 int i;
46
47 sc->threads = g_malloc0(size * cc->nr_threads);
48 for (i = 0; i < cc->nr_threads; i++) {
49 char id[32];
50 void *obj = sc->threads + i * size;
51
52 object_initialize(obj, size, typename);
53 snprintf(id, sizeof(id), "thread[%d]", i);
54 object_property_add_child(OBJECT(sc), id, obj, &local_err);
55 if (local_err) {
56 goto err;
57 }
58 }
59 object_child_foreach(OBJECT(dev), spapr_cpu_core_realize_child, &local_err);
60 if (local_err) {
61 goto err;
62 } else {
63 return;
64 }
65
66 err:
67 while (i >= 0) {
68 obj = sc->threads + i * size;
69 object_unparent(obj);
70 i--;
71 }
72 g_free(sc->threads);
73 error_propagate(errp, local_err);
74 }
75
76 static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
77 {
78 DeviceClass *dc = DEVICE_CLASS(oc);
79 dc->realize = spapr_cpu_core_realize;
80 }
81
82 /*
83 * instance_init routines from different flavours of sPAPR CPU cores.
84 * TODO: Add support for 'host' core type.
85 */
86 #define SPAPR_CPU_CORE_INITFN(_type, _fname) \
87 static void glue(glue(spapr_cpu_core_, _fname), _initfn(Object *obj)) \
88 { \
89 sPAPRCPUCore *core = SPAPR_CPU_CORE(obj); \
90 char *name = g_strdup_printf("%s-" TYPE_POWERPC_CPU, stringify(_type)); \
91 ObjectClass *oc = object_class_by_name(name); \
92 g_assert(oc); \
93 g_free((void *)name); \
94 core->cpu_class = oc; \
95 }
96
97 SPAPR_CPU_CORE_INITFN(POWER7_v2.3, POWER7);
98 SPAPR_CPU_CORE_INITFN(POWER7+_v2.1, POWER7plus);
99 SPAPR_CPU_CORE_INITFN(POWER8_v2.0, POWER8);
100 SPAPR_CPU_CORE_INITFN(POWER8E_v2.1, POWER8E);
101
102 typedef struct SPAPRCoreInfo {
103 const char *name;
104 void (*initfn)(Object *obj);
105 } SPAPRCoreInfo;
106
107 static const SPAPRCoreInfo spapr_cores[] = {
108 /* POWER7 and aliases */
109 { .name = "POWER7_v2.3", .initfn = spapr_cpu_core_POWER7_initfn },
110 { .name = "POWER7", .initfn = spapr_cpu_core_POWER7_initfn },
111
112 /* POWER7+ and aliases */
113 { .name = "POWER7+_v2.1", .initfn = spapr_cpu_core_POWER7plus_initfn },
114 { .name = "POWER7+", .initfn = spapr_cpu_core_POWER7plus_initfn },
115
116 /* POWER8 and aliases */
117 { .name = "POWER8_v2.0", .initfn = spapr_cpu_core_POWER8_initfn },
118 { .name = "POWER8", .initfn = spapr_cpu_core_POWER8_initfn },
119 { .name = "power8", .initfn = spapr_cpu_core_POWER8_initfn },
120
121 /* POWER8E and aliases */
122 { .name = "POWER8E_v2.1", .initfn = spapr_cpu_core_POWER8E_initfn },
123 { .name = "POWER8E", .initfn = spapr_cpu_core_POWER8E_initfn },
124
125 { .name = NULL }
126 };
127
128 static void spapr_cpu_core_register(const SPAPRCoreInfo *info)
129 {
130 TypeInfo type_info = {
131 .parent = TYPE_SPAPR_CPU_CORE,
132 .instance_size = sizeof(sPAPRCPUCore),
133 .instance_init = info->initfn,
134 };
135
136 type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE, info->name);
137 type_register(&type_info);
138 g_free((void *)type_info.name);
139 }
140
141 static const TypeInfo spapr_cpu_core_type_info = {
142 .name = TYPE_SPAPR_CPU_CORE,
143 .parent = TYPE_CPU_CORE,
144 .abstract = true,
145 .instance_size = sizeof(sPAPRCPUCore),
146 .class_init = spapr_cpu_core_class_init,
147 };
148
149 static void spapr_cpu_core_register_types(void)
150 {
151 const SPAPRCoreInfo *info = spapr_cores;
152
153 type_register_static(&spapr_cpu_core_type_info);
154 while (info->name) {
155 spapr_cpu_core_register(info);
156 info++;
157 }
158 }
159
160 type_init(spapr_cpu_core_register_types)