]> Git Repo - qemu.git/blame - hw/ppc/spapr_cpu_core.c
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.9-20170301' into staging
[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;
af81cf32
BR
66 CPUState *cs = CPU(cpu);
67 int i;
afd10a0f
BR
68
69 /* Set time-base frequency to 512 MHz */
70 cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
71
72 /* Enable PAPR mode in TCG or KVM */
b7b0b1f1 73 cpu_ppc_set_papr(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
afd10a0f
BR
74
75 if (cpu->max_compat) {
76 Error *local_err = NULL;
77
78 ppc_set_compat(cpu, cpu->max_compat, &local_err);
79 if (local_err) {
80 error_propagate(errp, local_err);
81 return;
82 }
83 }
84
af81cf32 85 /* Set NUMA node for the added CPUs */
6bea1ddf
IM
86 i = numa_get_node_for_cpu(cs->cpu_index);
87 if (i < nb_numa_nodes) {
af81cf32 88 cs->numa_node = i;
af81cf32
BR
89 }
90
b4f27d71 91 xics_cpu_setup(XICS_FABRIC(spapr), cpu);
afd10a0f
BR
92
93 qemu_register_reset(spapr_cpu_reset, cpu);
af81cf32 94 spapr_cpu_reset(cpu);
afd10a0f 95}
3b542549 96
94a94e4c
BR
97/*
98 * Return the sPAPR CPU core type for @model which essentially is the CPU
99 * model specified with -cpu cmdline option.
100 */
101char *spapr_get_cpu_core_type(const char *model)
102{
103 char *core_type;
104 gchar **model_pieces = g_strsplit(model, ",", 2);
105
106 core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE);
4babfaf0
TH
107
108 /* Check whether it exists or whether we have to look up an alias name */
109 if (!object_class_by_name(core_type)) {
110 const char *realmodel;
111
112 g_free(core_type);
e17a8779
GK
113 core_type = NULL;
114 realmodel = ppc_cpu_lookup_alias(model_pieces[0]);
4babfaf0 115 if (realmodel) {
e17a8779 116 core_type = spapr_get_cpu_core_type(realmodel);
4babfaf0 117 }
4babfaf0
TH
118 }
119
e17a8779 120 g_strfreev(model_pieces);
94a94e4c
BR
121 return core_type;
122}
123
f844616b 124static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
6f4b5c3e
BR
125{
126 sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
7ebaf795
BR
127 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
128 const char *typename = object_class_get_name(scc->cpu_class);
6f4b5c3e 129 size_t size = object_type_get_instance_size(typename);
6f4b5c3e 130 CPUCore *cc = CPU_CORE(dev);
6f4b5c3e
BR
131 int i;
132
133 for (i = 0; i < cc->nr_threads; i++) {
134 void *obj = sc->threads + i * size;
135 DeviceState *dev = DEVICE(obj);
136 CPUState *cs = CPU(dev);
137 PowerPCCPU *cpu = POWERPC_CPU(cs);
138
139 spapr_cpu_destroy(cpu);
140 cpu_remove_sync(cs);
141 object_unparent(obj);
142 }
8a1eb71b 143 g_free(sc->threads);
6f4b5c3e
BR
144}
145
7093645a 146static void spapr_cpu_core_realize_child(Object *child, Error **errp)
3b542549 147{
7093645a 148 Error *local_err = NULL;
3b542549
BR
149 sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
150 CPUState *cs = CPU(child);
151 PowerPCCPU *cpu = POWERPC_CPU(cs);
152
f11235b9
GK
153 object_property_set_bool(child, true, "realized", &local_err);
154 if (local_err) {
155 error_propagate(errp, local_err);
7093645a 156 return;
3b542549
BR
157 }
158
f11235b9
GK
159 spapr_cpu_init(spapr, cpu, &local_err);
160 if (local_err) {
161 error_propagate(errp, local_err);
7093645a 162 return;
3b542549 163 }
3b542549
BR
164}
165
166static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
167{
168 sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
7ebaf795 169 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
3b542549 170 CPUCore *cc = CPU_CORE(OBJECT(dev));
7ebaf795 171 const char *typename = object_class_get_name(scc->cpu_class);
3b542549
BR
172 size_t size = object_type_get_instance_size(typename);
173 Error *local_err = NULL;
7093645a
BR
174 void *obj;
175 int i, j;
3b542549
BR
176
177 sc->threads = g_malloc0(size * cc->nr_threads);
178 for (i = 0; i < cc->nr_threads; i++) {
179 char id[32];
b63578bd
IM
180 CPUState *cs;
181
7093645a 182 obj = sc->threads + i * size;
3b542549
BR
183
184 object_initialize(obj, size, typename);
b63578bd
IM
185 cs = CPU(obj);
186 cs->cpu_index = cc->core_id + i;
3b542549
BR
187 snprintf(id, sizeof(id), "thread[%d]", i);
188 object_property_add_child(OBJECT(sc), id, obj, &local_err);
189 if (local_err) {
190 goto err;
191 }
8e758dee 192 object_unref(obj);
3b542549 193 }
7093645a
BR
194
195 for (j = 0; j < cc->nr_threads; j++) {
196 obj = sc->threads + j * size;
197
198 spapr_cpu_core_realize_child(obj, &local_err);
199 if (local_err) {
200 goto err;
201 }
3b542549 202 }
7093645a 203 return;
3b542549
BR
204
205err:
dde35bc9 206 while (--i >= 0) {
3b542549
BR
207 obj = sc->threads + i * size;
208 object_unparent(obj);
3b542549
BR
209 }
210 g_free(sc->threads);
211 error_propagate(errp, local_err);
212}
213
7ebaf795 214static const char *spapr_core_models[] = {
4babfaf0 215 /* 970 */
7ebaf795 216 "970_v2.2",
ff461b8d 217
4babfaf0 218 /* 970MP variants */
7ebaf795
BR
219 "970MP_v1.0",
220 "970mp_v1.0",
221 "970MP_v1.1",
222 "970mp_v1.1",
470f2157 223
4babfaf0 224 /* POWER5+ */
7ebaf795 225 "POWER5+_v2.1",
ff461b8d 226
4babfaf0 227 /* POWER7 */
7ebaf795 228 "POWER7_v2.3",
3b542549 229
4babfaf0 230 /* POWER7+ */
7ebaf795 231 "POWER7+_v2.1",
3b542549 232
4babfaf0 233 /* POWER8 */
7ebaf795 234 "POWER8_v2.0",
3b542549 235
4babfaf0 236 /* POWER8E */
7ebaf795 237 "POWER8E_v2.1",
3b542549 238
4babfaf0 239 /* POWER8NVL */
7ebaf795 240 "POWER8NVL_v1.0",
3b542549
BR
241};
242
7ebaf795 243void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
3b542549 244{
7ebaf795
BR
245 DeviceClass *dc = DEVICE_CLASS(oc);
246 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
247
248 dc->realize = spapr_cpu_core_realize;
f844616b 249 dc->unrealize = spapr_cpu_core_unrealizefn;
7ebaf795
BR
250 scc->cpu_class = cpu_class_by_name(TYPE_POWERPC_CPU, data);
251 g_assert(scc->cpu_class);
3b542549
BR
252}
253
254static const TypeInfo spapr_cpu_core_type_info = {
255 .name = TYPE_SPAPR_CPU_CORE,
256 .parent = TYPE_CPU_CORE,
257 .abstract = true,
258 .instance_size = sizeof(sPAPRCPUCore),
7ebaf795 259 .class_size = sizeof(sPAPRCPUCoreClass),
3b542549
BR
260};
261
262static void spapr_cpu_core_register_types(void)
263{
7ebaf795 264 int i;
3b542549
BR
265
266 type_register_static(&spapr_cpu_core_type_info);
7ebaf795
BR
267
268 for (i = 0; i < ARRAY_SIZE(spapr_core_models); i++) {
269 TypeInfo type_info = {
270 .parent = TYPE_SPAPR_CPU_CORE,
271 .instance_size = sizeof(sPAPRCPUCore),
272 .class_init = spapr_cpu_core_class_init,
273 .class_data = (void *) spapr_core_models[i],
274 };
275
276 type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE,
277 spapr_core_models[i]);
278 type_register(&type_info);
279 g_free((void *)type_info.name);
3b542549
BR
280 }
281}
282
283type_init(spapr_cpu_core_register_types)
This page took 0.146621 seconds and 4 git commands to generate.