]> Git Repo - qemu.git/blame - hw/ppc/spapr_cpu_core.c
spapr: allocate the ICPState object from under sPAPRCPUCore
[qemu.git] / hw / ppc / spapr_cpu_core.c
CommitLineData
3b542549
BR
1/*
2 * sPAPR CPU core device, acts as container of CPU thread devices.
3 *
4 * Copyright (C) 2016 Bharata B Rao <[email protected]>
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"
fcf5ef2a 11#include "target/ppc/cpu.h"
3b542549
BR
12#include "hw/ppc/spapr.h"
13#include "hw/boards.h"
14#include "qapi/error.h"
a9c94277 15#include "sysemu/cpus.h"
e57ca75c 16#include "sysemu/kvm.h"
fcf5ef2a 17#include "target/ppc/kvm_ppc.h"
afd10a0f 18#include "hw/ppc/ppc.h"
fcf5ef2a 19#include "target/ppc/mmu-hash64.h"
a9c94277 20#include "sysemu/numa.h"
e57ca75c 21#include "qemu/error-report.h"
afd10a0f
BR
22
23static void spapr_cpu_reset(void *opaque)
24{
25 sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
26 PowerPCCPU *cpu = opaque;
27 CPUState *cs = CPU(cpu);
28 CPUPPCState *env = &cpu->env;
29
30 cpu_reset(cs);
31
32 /* All CPUs start halted. CPU0 is unhalted from the machine level
33 * reset code and the rest are explicitly started up by the guest
34 * using an RTAS call */
35 cs->halted = 1;
36
37 env->spr[SPR_HIOR] = 0;
38
e57ca75c
DG
39 /*
40 * This is a hack for the benefit of KVM PR - it abuses the SDR1
41 * slot in kvm_sregs to communicate the userspace address of the
42 * HPT
43 */
44 if (kvm_enabled()) {
45 env->spr[SPR_SDR1] = (target_ulong)(uintptr_t)spapr->htab
46 | (spapr->htab_shift - 18);
47 if (kvmppc_put_books_sregs(cpu) < 0) {
48 error_report("Unable to update SDR1 in KVM");
49 exit(1);
50 }
51 }
afd10a0f
BR
52}
53
6f4b5c3e
BR
54static void spapr_cpu_destroy(PowerPCCPU *cpu)
55{
56 sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
57
b4f27d71 58 xics_cpu_destroy(XICS_FABRIC(spapr), cpu);
6f4b5c3e
BR
59 qemu_unregister_reset(spapr_cpu_reset, cpu);
60}
61
0c86d0fd
DG
62static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
63 Error **errp)
afd10a0f
BR
64{
65 CPUPPCState *env = &cpu->env;
66
67 /* Set time-base frequency to 512 MHz */
68 cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
69
70 /* Enable PAPR mode in TCG or KVM */
b7b0b1f1 71 cpu_ppc_set_papr(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
afd10a0f
BR
72
73 if (cpu->max_compat) {
74 Error *local_err = NULL;
75
76 ppc_set_compat(cpu, cpu->max_compat, &local_err);
77 if (local_err) {
78 error_propagate(errp, local_err);
79 return;
80 }
81 }
82
afd10a0f 83 qemu_register_reset(spapr_cpu_reset, cpu);
af81cf32 84 spapr_cpu_reset(cpu);
afd10a0f 85}
3b542549 86
94a94e4c
BR
87/*
88 * Return the sPAPR CPU core type for @model which essentially is the CPU
89 * model specified with -cpu cmdline option.
90 */
91char *spapr_get_cpu_core_type(const char *model)
92{
93 char *core_type;
94 gchar **model_pieces = g_strsplit(model, ",", 2);
95
96 core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE);
4babfaf0
TH
97
98 /* Check whether it exists or whether we have to look up an alias name */
99 if (!object_class_by_name(core_type)) {
100 const char *realmodel;
101
102 g_free(core_type);
e17a8779
GK
103 core_type = NULL;
104 realmodel = ppc_cpu_lookup_alias(model_pieces[0]);
4babfaf0 105 if (realmodel) {
e17a8779 106 core_type = spapr_get_cpu_core_type(realmodel);
4babfaf0 107 }
4babfaf0
TH
108 }
109
e17a8779 110 g_strfreev(model_pieces);
94a94e4c
BR
111 return core_type;
112}
113
f844616b 114static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
6f4b5c3e
BR
115{
116 sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
7ebaf795
BR
117 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
118 const char *typename = object_class_get_name(scc->cpu_class);
6f4b5c3e 119 size_t size = object_type_get_instance_size(typename);
6f4b5c3e 120 CPUCore *cc = CPU_CORE(dev);
6f4b5c3e
BR
121 int i;
122
123 for (i = 0; i < cc->nr_threads; i++) {
124 void *obj = sc->threads + i * size;
125 DeviceState *dev = DEVICE(obj);
126 CPUState *cs = CPU(dev);
127 PowerPCCPU *cpu = POWERPC_CPU(cs);
128
129 spapr_cpu_destroy(cpu);
130 cpu_remove_sync(cs);
131 object_unparent(obj);
132 }
8a1eb71b 133 g_free(sc->threads);
6f4b5c3e
BR
134}
135
7093645a 136static void spapr_cpu_core_realize_child(Object *child, Error **errp)
3b542549 137{
7093645a 138 Error *local_err = NULL;
3b542549
BR
139 sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
140 CPUState *cs = CPU(child);
141 PowerPCCPU *cpu = POWERPC_CPU(cs);
5bc8d26d
CLG
142 Object *obj;
143
144 obj = object_new(spapr->icp_type);
145 object_property_add_child(OBJECT(cpu), "icp", obj, NULL);
146 object_property_add_const_link(obj, "xics", OBJECT(spapr), &error_abort);
147 object_property_set_bool(obj, true, "realized", &local_err);
148 if (local_err) {
149 error_propagate(errp, local_err);
150 return;
151 }
3b542549 152
f11235b9
GK
153 object_property_set_bool(child, true, "realized", &local_err);
154 if (local_err) {
5bc8d26d 155 object_unparent(obj);
f11235b9 156 error_propagate(errp, local_err);
7093645a 157 return;
3b542549
BR
158 }
159
f11235b9
GK
160 spapr_cpu_init(spapr, cpu, &local_err);
161 if (local_err) {
5bc8d26d 162 object_unparent(obj);
f11235b9 163 error_propagate(errp, local_err);
7093645a 164 return;
3b542549 165 }
5bc8d26d
CLG
166
167 xics_cpu_setup(XICS_FABRIC(spapr), cpu, ICP(obj));
3b542549
BR
168}
169
170static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
171{
172 sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
7ebaf795 173 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
3b542549 174 CPUCore *cc = CPU_CORE(OBJECT(dev));
7ebaf795 175 const char *typename = object_class_get_name(scc->cpu_class);
3b542549
BR
176 size_t size = object_type_get_instance_size(typename);
177 Error *local_err = NULL;
17b7c39e 178 int core_node_id = numa_get_node_for_cpu(cc->core_id);;
7093645a
BR
179 void *obj;
180 int i, j;
3b542549
BR
181
182 sc->threads = g_malloc0(size * cc->nr_threads);
183 for (i = 0; i < cc->nr_threads; i++) {
17b7c39e 184 int node_id;
3b542549 185 char id[32];
b63578bd
IM
186 CPUState *cs;
187
7093645a 188 obj = sc->threads + i * size;
3b542549
BR
189
190 object_initialize(obj, size, typename);
b63578bd
IM
191 cs = CPU(obj);
192 cs->cpu_index = cc->core_id + i;
17b7c39e
IM
193
194 /* Set NUMA node for the added CPUs */
195 node_id = numa_get_node_for_cpu(cs->cpu_index);
196 if (node_id != core_node_id) {
197 error_setg(&local_err, "Invalid node-id=%d of thread[cpu-index: %d]"
198 " on CPU[core-id: %d, node-id: %d], node-id must be the same",
199 node_id, cs->cpu_index, cc->core_id, core_node_id);
200 goto err;
201 }
202 if (node_id < nb_numa_nodes) {
203 cs->numa_node = node_id;
204 }
205
3b542549
BR
206 snprintf(id, sizeof(id), "thread[%d]", i);
207 object_property_add_child(OBJECT(sc), id, obj, &local_err);
208 if (local_err) {
209 goto err;
210 }
8e758dee 211 object_unref(obj);
3b542549 212 }
7093645a
BR
213
214 for (j = 0; j < cc->nr_threads; j++) {
215 obj = sc->threads + j * size;
216
217 spapr_cpu_core_realize_child(obj, &local_err);
218 if (local_err) {
219 goto err;
220 }
3b542549 221 }
7093645a 222 return;
3b542549
BR
223
224err:
dde35bc9 225 while (--i >= 0) {
3b542549
BR
226 obj = sc->threads + i * size;
227 object_unparent(obj);
3b542549
BR
228 }
229 g_free(sc->threads);
230 error_propagate(errp, local_err);
231}
232
7ebaf795 233static const char *spapr_core_models[] = {
4babfaf0 234 /* 970 */
7ebaf795 235 "970_v2.2",
ff461b8d 236
4babfaf0 237 /* 970MP variants */
7ebaf795
BR
238 "970MP_v1.0",
239 "970mp_v1.0",
240 "970MP_v1.1",
241 "970mp_v1.1",
470f2157 242
4babfaf0 243 /* POWER5+ */
7ebaf795 244 "POWER5+_v2.1",
ff461b8d 245
4babfaf0 246 /* POWER7 */
7ebaf795 247 "POWER7_v2.3",
3b542549 248
4babfaf0 249 /* POWER7+ */
7ebaf795 250 "POWER7+_v2.1",
3b542549 251
4babfaf0 252 /* POWER8 */
7ebaf795 253 "POWER8_v2.0",
3b542549 254
4babfaf0 255 /* POWER8E */
7ebaf795 256 "POWER8E_v2.1",
3b542549 257
4babfaf0 258 /* POWER8NVL */
7ebaf795 259 "POWER8NVL_v1.0",
24d8e565
SJS
260
261 /* POWER9 */
262 "POWER9_v1.0",
3b542549
BR
263};
264
7ebaf795 265void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
3b542549 266{
7ebaf795
BR
267 DeviceClass *dc = DEVICE_CLASS(oc);
268 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
269
270 dc->realize = spapr_cpu_core_realize;
f844616b 271 dc->unrealize = spapr_cpu_core_unrealizefn;
7ebaf795
BR
272 scc->cpu_class = cpu_class_by_name(TYPE_POWERPC_CPU, data);
273 g_assert(scc->cpu_class);
3b542549
BR
274}
275
276static const TypeInfo spapr_cpu_core_type_info = {
277 .name = TYPE_SPAPR_CPU_CORE,
278 .parent = TYPE_CPU_CORE,
279 .abstract = true,
280 .instance_size = sizeof(sPAPRCPUCore),
7ebaf795 281 .class_size = sizeof(sPAPRCPUCoreClass),
3b542549
BR
282};
283
284static void spapr_cpu_core_register_types(void)
285{
7ebaf795 286 int i;
3b542549
BR
287
288 type_register_static(&spapr_cpu_core_type_info);
7ebaf795
BR
289
290 for (i = 0; i < ARRAY_SIZE(spapr_core_models); i++) {
291 TypeInfo type_info = {
292 .parent = TYPE_SPAPR_CPU_CORE,
293 .instance_size = sizeof(sPAPRCPUCore),
294 .class_init = spapr_cpu_core_class_init,
295 .class_data = (void *) spapr_core_models[i],
296 };
297
298 type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE,
299 spapr_core_models[i]);
300 type_register(&type_info);
301 g_free((void *)type_info.name);
3b542549
BR
302 }
303}
304
305type_init(spapr_cpu_core_register_types)
This page took 0.111238 seconds and 4 git commands to generate.