]> git.proxmox.com Git - mirror_qemu.git/blame - hw/ppc/spapr_cpu_core.c
spapr: fix device tree properties when using compatibility mode
[mirror_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 <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 */
e9808d09 9#include "qemu/osdep.h"
3b542549
BR
10#include "hw/cpu/core.h"
11#include "hw/ppc/spapr_cpu_core.h"
fcf5ef2a 12#include "target/ppc/cpu.h"
3b542549
BR
13#include "hw/ppc/spapr.h"
14#include "hw/boards.h"
15#include "qapi/error.h"
a9c94277 16#include "sysemu/cpus.h"
e57ca75c 17#include "sysemu/kvm.h"
fcf5ef2a 18#include "target/ppc/kvm_ppc.h"
afd10a0f 19#include "hw/ppc/ppc.h"
fcf5ef2a 20#include "target/ppc/mmu-hash64.h"
a9c94277 21#include "sysemu/numa.h"
1ec26c75 22#include "sysemu/hw_accel.h"
e57ca75c 23#include "qemu/error-report.h"
afd10a0f
BR
24
25static void spapr_cpu_reset(void *opaque)
26{
afd10a0f
BR
27 PowerPCCPU *cpu = opaque;
28 CPUState *cs = CPU(cpu);
29 CPUPPCState *env = &cpu->env;
d6322252 30 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
afd10a0f
BR
31
32 cpu_reset(cs);
33
34 /* All CPUs start halted. CPU0 is unhalted from the machine level
35 * reset code and the rest are explicitly started up by the guest
36 * using an RTAS call */
37 cs->halted = 1;
38
39 env->spr[SPR_HIOR] = 0;
d6322252
CLG
40
41 /* Disable Power-saving mode Exit Cause exceptions for the CPU.
42 * This can cause issues when rebooting the guest if a secondary
43 * is awaken */
44 if (cs != first_cpu) {
45 env->spr[SPR_LPCR] &= ~pcc->lpcr_pm;
46 }
9012a53f
GK
47
48 /* Set compatibility mode to match the boot CPU, which was either set
49 * by the machine reset code or by CAS. This should never fail.
50 */
51 if (cs != first_cpu) {
52 ppc_set_compat(cpu, POWERPC_CPU(first_cpu)->compat_pvr, &error_abort);
53 }
afd10a0f
BR
54}
55
6f4b5c3e
BR
56static void spapr_cpu_destroy(PowerPCCPU *cpu)
57{
6f4b5c3e
BR
58 qemu_unregister_reset(spapr_cpu_reset, cpu);
59}
60
0c86d0fd
DG
61static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
62 Error **errp)
afd10a0f
BR
63{
64 CPUPPCState *env = &cpu->env;
65
66 /* Set time-base frequency to 512 MHz */
67 cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
68
69 /* Enable PAPR mode in TCG or KVM */
b7b0b1f1 70 cpu_ppc_set_papr(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
afd10a0f 71
afd10a0f 72 qemu_register_reset(spapr_cpu_reset, cpu);
af81cf32 73 spapr_cpu_reset(cpu);
afd10a0f 74}
3b542549 75
94a94e4c
BR
76/*
77 * Return the sPAPR CPU core type for @model which essentially is the CPU
78 * model specified with -cpu cmdline option.
79 */
2e9c10eb 80const char *spapr_get_cpu_core_type(const char *cpu_type)
94a94e4c 81{
2e9c10eb
IM
82 int len = strlen(cpu_type) - strlen(POWERPC_CPU_TYPE_SUFFIX);
83 char *core_type = g_strdup_printf(SPAPR_CPU_CORE_TYPE_NAME("%.*s"),
84 len, cpu_type);
85 ObjectClass *oc = object_class_by_name(core_type);
86
87 g_free(core_type);
88 if (!oc) {
89 return NULL;
4babfaf0
TH
90 }
91
2e9c10eb 92 return object_class_get_name(oc);
94a94e4c
BR
93}
94
f844616b 95static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
6f4b5c3e
BR
96{
97 sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
6f4b5c3e 98 CPUCore *cc = CPU_CORE(dev);
6f4b5c3e
BR
99 int i;
100
101 for (i = 0; i < cc->nr_threads; i++) {
94ad93bd 102 Object *obj = OBJECT(sc->threads[i]);
6f4b5c3e
BR
103 DeviceState *dev = DEVICE(obj);
104 CPUState *cs = CPU(dev);
105 PowerPCCPU *cpu = POWERPC_CPU(cs);
106
107 spapr_cpu_destroy(cpu);
8f37e54e 108 object_unparent(cpu->intc);
6f4b5c3e
BR
109 cpu_remove_sync(cs);
110 object_unparent(obj);
111 }
8a1eb71b 112 g_free(sc->threads);
6f4b5c3e
BR
113}
114
3b2fcedd
GK
115static void spapr_cpu_core_realize_child(Object *child,
116 sPAPRMachineState *spapr, Error **errp)
3b542549 117{
7093645a 118 Error *local_err = NULL;
3b542549
BR
119 CPUState *cs = CPU(child);
120 PowerPCCPU *cpu = POWERPC_CPU(cs);
5bc8d26d 121
9ed65663 122 object_property_set_bool(child, true, "realized", &local_err);
5bc8d26d 123 if (local_err) {
c8a98293 124 goto error;
5bc8d26d 125 }
3b542549 126
9ed65663 127 spapr_cpu_init(spapr, cpu, &local_err);
f11235b9 128 if (local_err) {
c8a98293 129 goto error;
3b542549
BR
130 }
131
ed0c37ee
CLG
132 cpu->intc = icp_create(child, spapr->icp_type, XICS_FABRIC(spapr),
133 &local_err);
f11235b9 134 if (local_err) {
4f7a47be 135 goto error;
3b542549 136 }
5bc8d26d 137
c8a98293
GK
138 return;
139
6595ab31 140error:
c8a98293 141 error_propagate(errp, local_err);
3b542549
BR
142}
143
144static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
145{
e7cca3e9
GK
146 /* We don't use SPAPR_MACHINE() in order to exit gracefully if the user
147 * tries to add a sPAPR CPU core to a non-pseries machine.
148 */
149 sPAPRMachineState *spapr =
150 (sPAPRMachineState *) object_dynamic_cast(qdev_get_machine(),
151 TYPE_SPAPR_MACHINE);
3b542549 152 sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
7ebaf795 153 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
3b542549 154 CPUCore *cc = CPU_CORE(OBJECT(dev));
3b542549 155 Error *local_err = NULL;
94ad93bd 156 Object *obj;
7093645a 157 int i, j;
3b542549 158
e7cca3e9
GK
159 if (!spapr) {
160 error_setg(errp, TYPE_SPAPR_CPU_CORE " needs a pseries machine");
2363d5ee
TH
161 return;
162 }
163
94ad93bd 164 sc->threads = g_new(PowerPCCPU *, cc->nr_threads);
3b542549
BR
165 for (i = 0; i < cc->nr_threads; i++) {
166 char id[32];
b63578bd 167 CPUState *cs;
15f8b142 168 PowerPCCPU *cpu;
b63578bd 169
94ad93bd 170 obj = object_new(scc->cpu_type);
3b542549 171
b63578bd 172 cs = CPU(obj);
94ad93bd 173 cpu = sc->threads[i] = POWERPC_CPU(obj);
b63578bd 174 cs->cpu_index = cc->core_id + i;
7cca3e46
SB
175 cpu->vcpu_id = (cc->core_id * spapr->vsmt / smp_threads) + i;
176 if (kvm_enabled() && !kvm_vcpu_id_is_valid(cpu->vcpu_id)) {
177 error_setg(&local_err, "Can't create CPU with id %d in KVM",
178 cpu->vcpu_id);
179 error_append_hint(&local_err, "Adjust the number of cpus to %d "
180 "or try to raise the number of threads per core\n",
181 cpu->vcpu_id * smp_threads / spapr->vsmt);
182 goto err;
183 }
184
17b7c39e 185
722387e7 186 /* Set NUMA node for the threads belonged to core */
15f8b142 187 cpu->node_id = sc->node_id;
17b7c39e 188
3b542549
BR
189 snprintf(id, sizeof(id), "thread[%d]", i);
190 object_property_add_child(OBJECT(sc), id, obj, &local_err);
191 if (local_err) {
192 goto err;
193 }
8e758dee 194 object_unref(obj);
3b542549 195 }
7093645a
BR
196
197 for (j = 0; j < cc->nr_threads; j++) {
94ad93bd 198 obj = OBJECT(sc->threads[j]);
7093645a 199
3b2fcedd 200 spapr_cpu_core_realize_child(obj, spapr, &local_err);
7093645a
BR
201 if (local_err) {
202 goto err;
203 }
3b542549 204 }
7093645a 205 return;
3b542549
BR
206
207err:
dde35bc9 208 while (--i >= 0) {
94ad93bd 209 obj = OBJECT(sc->threads[i]);
3b542549 210 object_unparent(obj);
3b542549
BR
211 }
212 g_free(sc->threads);
213 error_propagate(errp, local_err);
214}
215
0b8497f0
IM
216static Property spapr_cpu_core_properties[] = {
217 DEFINE_PROP_INT32("node-id", sPAPRCPUCore, node_id, CPU_UNSET_NUMA_NODE_ID),
218 DEFINE_PROP_END_OF_LIST()
219};
220
5bbb2641 221static void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
3b542549 222{
7ebaf795
BR
223 DeviceClass *dc = DEVICE_CLASS(oc);
224 sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
225
226 dc->realize = spapr_cpu_core_realize;
f844616b 227 dc->unrealize = spapr_cpu_core_unrealizefn;
0b8497f0 228 dc->props = spapr_cpu_core_properties;
b51d3c88 229 scc->cpu_type = data;
3b542549
BR
230}
231
44cd95e3
IM
232#define DEFINE_SPAPR_CPU_CORE_TYPE(cpu_model) \
233 { \
234 .parent = TYPE_SPAPR_CPU_CORE, \
b51d3c88 235 .class_data = (void *) POWERPC_CPU_TYPE_NAME(cpu_model), \
44cd95e3
IM
236 .class_init = spapr_cpu_core_class_init, \
237 .name = SPAPR_CPU_CORE_TYPE_NAME(cpu_model), \
3b542549 238 }
3b542549 239
44cd95e3
IM
240static const TypeInfo spapr_cpu_core_type_infos[] = {
241 {
242 .name = TYPE_SPAPR_CPU_CORE,
243 .parent = TYPE_CPU_CORE,
244 .abstract = true,
245 .instance_size = sizeof(sPAPRCPUCore),
246 .class_size = sizeof(sPAPRCPUCoreClass),
247 },
248 DEFINE_SPAPR_CPU_CORE_TYPE("970_v2.2"),
249 DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.0"),
250 DEFINE_SPAPR_CPU_CORE_TYPE("970mp_v1.1"),
251 DEFINE_SPAPR_CPU_CORE_TYPE("power5+_v2.1"),
252 DEFINE_SPAPR_CPU_CORE_TYPE("power7_v2.3"),
253 DEFINE_SPAPR_CPU_CORE_TYPE("power7+_v2.1"),
254 DEFINE_SPAPR_CPU_CORE_TYPE("power8_v2.0"),
255 DEFINE_SPAPR_CPU_CORE_TYPE("power8e_v2.1"),
256 DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
257 DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
258 DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
5bbb2641
IM
259#ifdef CONFIG_KVM
260 DEFINE_SPAPR_CPU_CORE_TYPE("host"),
261#endif
44cd95e3
IM
262};
263
264DEFINE_TYPES(spapr_cpu_core_type_infos)