]> Git Repo - qemu.git/blob - hw/ppc/spapr_cpu_core.c
spapr: cpu core: separate child threads destruction from machine state operations
[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 <[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"
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 #include "hw/ppc/ppc.h"
18 #include "target/ppc/mmu-hash64.h"
19 #include "sysemu/numa.h"
20
21 static void spapr_cpu_reset(void *opaque)
22 {
23     sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
24     PowerPCCPU *cpu = opaque;
25     CPUState *cs = CPU(cpu);
26     CPUPPCState *env = &cpu->env;
27
28     cpu_reset(cs);
29
30     /* All CPUs start halted.  CPU0 is unhalted from the machine level
31      * reset code and the rest are explicitly started up by the guest
32      * using an RTAS call */
33     cs->halted = 1;
34
35     env->spr[SPR_HIOR] = 0;
36
37     ppc_hash64_set_external_hpt(cpu, spapr->htab, spapr->htab_shift,
38                                 &error_fatal);
39 }
40
41 static void spapr_cpu_destroy(PowerPCCPU *cpu)
42 {
43     sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
44
45     xics_cpu_destroy(spapr->xics, cpu);
46     qemu_unregister_reset(spapr_cpu_reset, cpu);
47 }
48
49 static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
50                            Error **errp)
51 {
52     CPUPPCState *env = &cpu->env;
53     CPUState *cs = CPU(cpu);
54     int i;
55
56     /* Set time-base frequency to 512 MHz */
57     cpu_ppc_tb_init(env, SPAPR_TIMEBASE_FREQ);
58
59     /* Enable PAPR mode in TCG or KVM */
60     cpu_ppc_set_vhyp(cpu, PPC_VIRTUAL_HYPERVISOR(spapr));
61     cpu_ppc_set_papr(cpu);
62
63     if (cpu->max_compat) {
64         Error *local_err = NULL;
65
66         ppc_set_compat(cpu, cpu->max_compat, &local_err);
67         if (local_err) {
68             error_propagate(errp, local_err);
69             return;
70         }
71     }
72
73     /* Set NUMA node for the added CPUs  */
74     i = numa_get_node_for_cpu(cs->cpu_index);
75     if (i < nb_numa_nodes) {
76             cs->numa_node = i;
77     }
78
79     xics_cpu_setup(spapr->xics, cpu);
80
81     qemu_register_reset(spapr_cpu_reset, cpu);
82     spapr_cpu_reset(cpu);
83 }
84
85 /*
86  * Return the sPAPR CPU core type for @model which essentially is the CPU
87  * model specified with -cpu cmdline option.
88  */
89 char *spapr_get_cpu_core_type(const char *model)
90 {
91     char *core_type;
92     gchar **model_pieces = g_strsplit(model, ",", 2);
93
94     core_type = g_strdup_printf("%s-%s", model_pieces[0], TYPE_SPAPR_CPU_CORE);
95
96     /* Check whether it exists or whether we have to look up an alias name */
97     if (!object_class_by_name(core_type)) {
98         const char *realmodel;
99
100         g_free(core_type);
101         core_type = NULL;
102         realmodel = ppc_cpu_lookup_alias(model_pieces[0]);
103         if (realmodel) {
104             core_type = spapr_get_cpu_core_type(realmodel);
105         }
106     }
107
108     g_strfreev(model_pieces);
109     return core_type;
110 }
111
112 static void spapr_core_release(DeviceState *dev, void *opaque)
113 {
114     sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
115     CPUCore *cc = CPU_CORE(dev);
116
117     spapr->cores[cc->core_id / smp_threads] = NULL;
118     object_unparent(OBJECT(dev));
119 }
120
121 static void spapr_cpu_core_unrealizefn(DeviceState *dev, Error **errp)
122 {
123     sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
124     sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
125     const char *typename = object_class_get_name(scc->cpu_class);
126     size_t size = object_type_get_instance_size(typename);
127     CPUCore *cc = CPU_CORE(dev);
128     int i;
129
130     for (i = 0; i < cc->nr_threads; i++) {
131         void *obj = sc->threads + i * size;
132         DeviceState *dev = DEVICE(obj);
133         CPUState *cs = CPU(dev);
134         PowerPCCPU *cpu = POWERPC_CPU(cs);
135
136         spapr_cpu_destroy(cpu);
137         cpu_remove_sync(cs);
138         object_unparent(obj);
139     }
140     g_free(sc->threads);
141 }
142
143 void spapr_core_unplug(HotplugHandler *hotplug_dev, DeviceState *dev,
144                        Error **errp)
145 {
146     CPUCore *cc = CPU_CORE(dev);
147     int smt = kvmppc_smt_threads();
148     int index = cc->core_id / smp_threads;
149     sPAPRDRConnector *drc =
150         spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt);
151     sPAPRDRConnectorClass *drck;
152     Error *local_err = NULL;
153
154     if (index == 0) {
155         error_setg(errp, "Boot CPU core may not be unplugged");
156         return;
157     }
158
159     g_assert(drc);
160
161     drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
162     drck->detach(drc, dev, spapr_core_release, NULL, &local_err);
163     if (local_err) {
164         error_propagate(errp, local_err);
165         return;
166     }
167
168     spapr_hotplug_req_remove_by_index(drc);
169 }
170
171 void spapr_core_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
172                      Error **errp)
173 {
174     sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
175     MachineClass *mc = MACHINE_GET_CLASS(spapr);
176     sPAPRCPUCore *core = SPAPR_CPU_CORE(OBJECT(dev));
177     CPUCore *cc = CPU_CORE(dev);
178     CPUState *cs = CPU(core->threads);
179     sPAPRDRConnector *drc;
180     Error *local_err = NULL;
181     void *fdt = NULL;
182     int fdt_offset = 0;
183     int index = cc->core_id / smp_threads;
184     int smt = kvmppc_smt_threads();
185
186     drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_CPU, index * smt);
187     spapr->cores[index] = OBJECT(dev);
188
189     g_assert(drc || !mc->query_hotpluggable_cpus);
190
191     /*
192      * Setup CPU DT entries only for hotplugged CPUs. For boot time or
193      * coldplugged CPUs DT entries are setup in spapr_build_fdt().
194      */
195     if (dev->hotplugged) {
196         fdt = spapr_populate_hotplug_cpu_dt(cs, &fdt_offset, spapr);
197     }
198
199     if (drc) {
200         sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
201         drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, &local_err);
202         if (local_err) {
203             g_free(fdt);
204             spapr->cores[index] = NULL;
205             error_propagate(errp, local_err);
206             return;
207         }
208     }
209
210     if (dev->hotplugged) {
211         /*
212          * Send hotplug notification interrupt to the guest only in case
213          * of hotplugged CPUs.
214          */
215         spapr_hotplug_req_add_by_index(drc);
216     } else {
217         /*
218          * Set the right DRC states for cold plugged CPU.
219          */
220         if (drc) {
221             sPAPRDRConnectorClass *drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);
222             drck->set_allocation_state(drc, SPAPR_DR_ALLOCATION_STATE_USABLE);
223             drck->set_isolation_state(drc, SPAPR_DR_ISOLATION_STATE_UNISOLATED);
224         }
225     }
226 }
227
228 void spapr_core_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
229                          Error **errp)
230 {
231     MachineState *machine = MACHINE(OBJECT(hotplug_dev));
232     MachineClass *mc = MACHINE_GET_CLASS(hotplug_dev);
233     sPAPRMachineState *spapr = SPAPR_MACHINE(OBJECT(hotplug_dev));
234     int spapr_max_cores = max_cpus / smp_threads;
235     int index;
236     Error *local_err = NULL;
237     CPUCore *cc = CPU_CORE(dev);
238     char *base_core_type = spapr_get_cpu_core_type(machine->cpu_model);
239     const char *type = object_get_typename(OBJECT(dev));
240
241     if (dev->hotplugged && !mc->query_hotpluggable_cpus) {
242         error_setg(&local_err, "CPU hotplug not supported for this machine");
243         goto out;
244     }
245
246     if (strcmp(base_core_type, type)) {
247         error_setg(&local_err, "CPU core type should be %s", base_core_type);
248         goto out;
249     }
250
251     if (cc->core_id % smp_threads) {
252         error_setg(&local_err, "invalid core id %d", cc->core_id);
253         goto out;
254     }
255
256     index = cc->core_id / smp_threads;
257     if (index < 0 || index >= spapr_max_cores) {
258         error_setg(&local_err, "core id %d out of range", cc->core_id);
259         goto out;
260     }
261
262     if (spapr->cores[index]) {
263         error_setg(&local_err, "core %d already populated", cc->core_id);
264         goto out;
265     }
266
267 out:
268     g_free(base_core_type);
269     error_propagate(errp, local_err);
270 }
271
272 static void spapr_cpu_core_realize_child(Object *child, Error **errp)
273 {
274     Error *local_err = NULL;
275     sPAPRMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
276     CPUState *cs = CPU(child);
277     PowerPCCPU *cpu = POWERPC_CPU(cs);
278
279     object_property_set_bool(child, true, "realized", &local_err);
280     if (local_err) {
281         error_propagate(errp, local_err);
282         return;
283     }
284
285     spapr_cpu_init(spapr, cpu, &local_err);
286     if (local_err) {
287         error_propagate(errp, local_err);
288         return;
289     }
290 }
291
292 static void spapr_cpu_core_realize(DeviceState *dev, Error **errp)
293 {
294     sPAPRCPUCore *sc = SPAPR_CPU_CORE(OBJECT(dev));
295     sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_GET_CLASS(OBJECT(dev));
296     CPUCore *cc = CPU_CORE(OBJECT(dev));
297     const char *typename = object_class_get_name(scc->cpu_class);
298     size_t size = object_type_get_instance_size(typename);
299     Error *local_err = NULL;
300     void *obj;
301     int i, j;
302
303     sc->threads = g_malloc0(size * cc->nr_threads);
304     for (i = 0; i < cc->nr_threads; i++) {
305         char id[32];
306         CPUState *cs;
307
308         obj = sc->threads + i * size;
309
310         object_initialize(obj, size, typename);
311         cs = CPU(obj);
312         cs->cpu_index = cc->core_id + i;
313         snprintf(id, sizeof(id), "thread[%d]", i);
314         object_property_add_child(OBJECT(sc), id, obj, &local_err);
315         if (local_err) {
316             goto err;
317         }
318         object_unref(obj);
319     }
320
321     for (j = 0; j < cc->nr_threads; j++) {
322         obj = sc->threads + j * size;
323
324         spapr_cpu_core_realize_child(obj, &local_err);
325         if (local_err) {
326             goto err;
327         }
328     }
329     return;
330
331 err:
332     while (--i >= 0) {
333         obj = sc->threads + i * size;
334         object_unparent(obj);
335     }
336     g_free(sc->threads);
337     error_propagate(errp, local_err);
338 }
339
340 static const char *spapr_core_models[] = {
341     /* 970 */
342     "970_v2.2",
343
344     /* 970MP variants */
345     "970MP_v1.0",
346     "970mp_v1.0",
347     "970MP_v1.1",
348     "970mp_v1.1",
349
350     /* POWER5+ */
351     "POWER5+_v2.1",
352
353     /* POWER7 */
354     "POWER7_v2.3",
355
356     /* POWER7+ */
357     "POWER7+_v2.1",
358
359     /* POWER8 */
360     "POWER8_v2.0",
361
362     /* POWER8E */
363     "POWER8E_v2.1",
364
365     /* POWER8NVL */
366     "POWER8NVL_v1.0",
367 };
368
369 void spapr_cpu_core_class_init(ObjectClass *oc, void *data)
370 {
371     DeviceClass *dc = DEVICE_CLASS(oc);
372     sPAPRCPUCoreClass *scc = SPAPR_CPU_CORE_CLASS(oc);
373
374     dc->realize = spapr_cpu_core_realize;
375     dc->unrealize = spapr_cpu_core_unrealizefn;
376     scc->cpu_class = cpu_class_by_name(TYPE_POWERPC_CPU, data);
377     g_assert(scc->cpu_class);
378 }
379
380 static const TypeInfo spapr_cpu_core_type_info = {
381     .name = TYPE_SPAPR_CPU_CORE,
382     .parent = TYPE_CPU_CORE,
383     .abstract = true,
384     .instance_size = sizeof(sPAPRCPUCore),
385     .class_size = sizeof(sPAPRCPUCoreClass),
386 };
387
388 static void spapr_cpu_core_register_types(void)
389 {
390     int i;
391
392     type_register_static(&spapr_cpu_core_type_info);
393
394     for (i = 0; i < ARRAY_SIZE(spapr_core_models); i++) {
395         TypeInfo type_info = {
396             .parent = TYPE_SPAPR_CPU_CORE,
397             .instance_size = sizeof(sPAPRCPUCore),
398             .class_init = spapr_cpu_core_class_init,
399             .class_data = (void *) spapr_core_models[i],
400         };
401
402         type_info.name = g_strdup_printf("%s-" TYPE_SPAPR_CPU_CORE,
403                                          spapr_core_models[i]);
404         type_register(&type_info);
405         g_free((void *)type_info.name);
406     }
407 }
408
409 type_init(spapr_cpu_core_register_types)
This page took 0.047561 seconds and 4 git commands to generate.