]> git.proxmox.com Git - mirror_qemu.git/blob - hw/ppc/spapr_irq.c
spapr: add a 'reset' method to the sPAPR IRQ backend
[mirror_qemu.git] / hw / ppc / spapr_irq.c
1 /*
2 * QEMU PowerPC sPAPR IRQ interface
3 *
4 * Copyright (c) 2018, IBM Corporation.
5 *
6 * This code is licensed under the GPL version 2 or later. See the
7 * COPYING file in the top-level directory.
8 */
9
10 #include "qemu/osdep.h"
11 #include "qemu/log.h"
12 #include "qemu/error-report.h"
13 #include "qapi/error.h"
14 #include "hw/ppc/spapr.h"
15 #include "hw/ppc/spapr_xive.h"
16 #include "hw/ppc/xics.h"
17 #include "sysemu/kvm.h"
18
19 #include "trace.h"
20
21 void spapr_irq_msi_init(sPAPRMachineState *spapr, uint32_t nr_msis)
22 {
23 spapr->irq_map_nr = nr_msis;
24 spapr->irq_map = bitmap_new(spapr->irq_map_nr);
25 }
26
27 int spapr_irq_msi_alloc(sPAPRMachineState *spapr, uint32_t num, bool align,
28 Error **errp)
29 {
30 int irq;
31
32 /*
33 * The 'align_mask' parameter of bitmap_find_next_zero_area()
34 * should be one less than a power of 2; 0 means no
35 * alignment. Adapt the 'align' value of the former allocator
36 * to fit the requirements of bitmap_find_next_zero_area()
37 */
38 align -= 1;
39
40 irq = bitmap_find_next_zero_area(spapr->irq_map, spapr->irq_map_nr, 0, num,
41 align);
42 if (irq == spapr->irq_map_nr) {
43 error_setg(errp, "can't find a free %d-IRQ block", num);
44 return -1;
45 }
46
47 bitmap_set(spapr->irq_map, irq, num);
48
49 return irq + SPAPR_IRQ_MSI;
50 }
51
52 void spapr_irq_msi_free(sPAPRMachineState *spapr, int irq, uint32_t num)
53 {
54 bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
55 }
56
57 void spapr_irq_msi_reset(sPAPRMachineState *spapr)
58 {
59 bitmap_clear(spapr->irq_map, 0, spapr->irq_map_nr);
60 }
61
62
63 /*
64 * XICS IRQ backend.
65 */
66
67 static ICSState *spapr_ics_create(sPAPRMachineState *spapr,
68 const char *type_ics,
69 int nr_irqs, Error **errp)
70 {
71 Error *local_err = NULL;
72 Object *obj;
73
74 obj = object_new(type_ics);
75 object_property_add_child(OBJECT(spapr), "ics", obj, &error_abort);
76 object_property_add_const_link(obj, ICS_PROP_XICS, OBJECT(spapr),
77 &error_abort);
78 object_property_set_int(obj, nr_irqs, "nr-irqs", &local_err);
79 if (local_err) {
80 goto error;
81 }
82 object_property_set_bool(obj, true, "realized", &local_err);
83 if (local_err) {
84 goto error;
85 }
86
87 return ICS_BASE(obj);
88
89 error:
90 error_propagate(errp, local_err);
91 return NULL;
92 }
93
94 static void spapr_irq_init_xics(sPAPRMachineState *spapr, Error **errp)
95 {
96 MachineState *machine = MACHINE(spapr);
97 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
98 int nr_irqs = smc->irq->nr_irqs;
99 Error *local_err = NULL;
100
101 if (kvm_enabled()) {
102 if (machine_kernel_irqchip_allowed(machine) &&
103 !xics_kvm_init(spapr, &local_err)) {
104 spapr->icp_type = TYPE_KVM_ICP;
105 spapr->ics = spapr_ics_create(spapr, TYPE_ICS_KVM, nr_irqs,
106 &local_err);
107 }
108 if (machine_kernel_irqchip_required(machine) && !spapr->ics) {
109 error_prepend(&local_err,
110 "kernel_irqchip requested but unavailable: ");
111 goto error;
112 }
113 error_free(local_err);
114 local_err = NULL;
115 }
116
117 if (!spapr->ics) {
118 xics_spapr_init(spapr);
119 spapr->icp_type = TYPE_ICP;
120 spapr->ics = spapr_ics_create(spapr, TYPE_ICS_SIMPLE, nr_irqs,
121 &local_err);
122 }
123
124 error:
125 error_propagate(errp, local_err);
126 }
127
128 #define ICS_IRQ_FREE(ics, srcno) \
129 (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))
130
131 static int spapr_irq_claim_xics(sPAPRMachineState *spapr, int irq, bool lsi,
132 Error **errp)
133 {
134 ICSState *ics = spapr->ics;
135
136 assert(ics);
137
138 if (!ics_valid_irq(ics, irq)) {
139 error_setg(errp, "IRQ %d is invalid", irq);
140 return -1;
141 }
142
143 if (!ICS_IRQ_FREE(ics, irq - ics->offset)) {
144 error_setg(errp, "IRQ %d is not free", irq);
145 return -1;
146 }
147
148 ics_set_irq_type(ics, irq - ics->offset, lsi);
149 return 0;
150 }
151
152 static void spapr_irq_free_xics(sPAPRMachineState *spapr, int irq, int num)
153 {
154 ICSState *ics = spapr->ics;
155 uint32_t srcno = irq - ics->offset;
156 int i;
157
158 if (ics_valid_irq(ics, irq)) {
159 trace_spapr_irq_free(0, irq, num);
160 for (i = srcno; i < srcno + num; ++i) {
161 if (ICS_IRQ_FREE(ics, i)) {
162 trace_spapr_irq_free_warn(0, i);
163 }
164 memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
165 }
166 }
167 }
168
169 static qemu_irq spapr_qirq_xics(sPAPRMachineState *spapr, int irq)
170 {
171 ICSState *ics = spapr->ics;
172 uint32_t srcno = irq - ics->offset;
173
174 if (ics_valid_irq(ics, irq)) {
175 return ics->qirqs[srcno];
176 }
177
178 return NULL;
179 }
180
181 static void spapr_irq_print_info_xics(sPAPRMachineState *spapr, Monitor *mon)
182 {
183 CPUState *cs;
184
185 CPU_FOREACH(cs) {
186 PowerPCCPU *cpu = POWERPC_CPU(cs);
187
188 icp_pic_print_info(ICP(cpu->intc), mon);
189 }
190
191 ics_pic_print_info(spapr->ics, mon);
192 }
193
194 static Object *spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
195 Object *cpu, Error **errp)
196 {
197 return icp_create(cpu, spapr->icp_type, XICS_FABRIC(spapr), errp);
198 }
199
200 static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
201 {
202 if (!object_dynamic_cast(OBJECT(spapr->ics), TYPE_ICS_KVM)) {
203 CPUState *cs;
204 CPU_FOREACH(cs) {
205 PowerPCCPU *cpu = POWERPC_CPU(cs);
206 icp_resend(ICP(cpu->intc));
207 }
208 }
209 return 0;
210 }
211
212 #define SPAPR_IRQ_XICS_NR_IRQS 0x1000
213 #define SPAPR_IRQ_XICS_NR_MSIS \
214 (XICS_IRQ_BASE + SPAPR_IRQ_XICS_NR_IRQS - SPAPR_IRQ_MSI)
215
216 sPAPRIrq spapr_irq_xics = {
217 .nr_irqs = SPAPR_IRQ_XICS_NR_IRQS,
218 .nr_msis = SPAPR_IRQ_XICS_NR_MSIS,
219
220 .init = spapr_irq_init_xics,
221 .claim = spapr_irq_claim_xics,
222 .free = spapr_irq_free_xics,
223 .qirq = spapr_qirq_xics,
224 .print_info = spapr_irq_print_info_xics,
225 .dt_populate = spapr_dt_xics,
226 .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
227 .post_load = spapr_irq_post_load_xics,
228 };
229
230 /*
231 * XIVE IRQ backend.
232 */
233 static void spapr_irq_init_xive(sPAPRMachineState *spapr, Error **errp)
234 {
235 MachineState *machine = MACHINE(spapr);
236 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
237 uint32_t nr_servers = spapr_max_server_number(spapr);
238 DeviceState *dev;
239 int i;
240
241 /* KVM XIVE device not yet available */
242 if (kvm_enabled()) {
243 if (machine_kernel_irqchip_required(machine)) {
244 error_setg(errp, "kernel_irqchip requested. no KVM XIVE support");
245 return;
246 }
247 }
248
249 dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
250 qdev_prop_set_uint32(dev, "nr-irqs", smc->irq->nr_irqs);
251 /*
252 * 8 XIVE END structures per CPU. One for each available priority
253 */
254 qdev_prop_set_uint32(dev, "nr-ends", nr_servers << 3);
255 qdev_init_nofail(dev);
256
257 spapr->xive = SPAPR_XIVE(dev);
258
259 /* Enable the CPU IPIs */
260 for (i = 0; i < nr_servers; ++i) {
261 spapr_xive_irq_claim(spapr->xive, SPAPR_IRQ_IPI + i, false);
262 }
263
264 spapr_xive_hcall_init(spapr);
265 }
266
267 static int spapr_irq_claim_xive(sPAPRMachineState *spapr, int irq, bool lsi,
268 Error **errp)
269 {
270 if (!spapr_xive_irq_claim(spapr->xive, irq, lsi)) {
271 error_setg(errp, "IRQ %d is invalid", irq);
272 return -1;
273 }
274 return 0;
275 }
276
277 static void spapr_irq_free_xive(sPAPRMachineState *spapr, int irq, int num)
278 {
279 int i;
280
281 for (i = irq; i < irq + num; ++i) {
282 spapr_xive_irq_free(spapr->xive, i);
283 }
284 }
285
286 static qemu_irq spapr_qirq_xive(sPAPRMachineState *spapr, int irq)
287 {
288 return spapr_xive_qirq(spapr->xive, irq);
289 }
290
291 static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
292 Monitor *mon)
293 {
294 CPUState *cs;
295
296 CPU_FOREACH(cs) {
297 PowerPCCPU *cpu = POWERPC_CPU(cs);
298
299 xive_tctx_pic_print_info(XIVE_TCTX(cpu->intc), mon);
300 }
301
302 spapr_xive_pic_print_info(spapr->xive, mon);
303 }
304
305 static Object *spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
306 Object *cpu, Error **errp)
307 {
308 Object *obj = xive_tctx_create(cpu, XIVE_ROUTER(spapr->xive), errp);
309
310 /*
311 * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
312 * don't benificiate from the reset of the XIVE IRQ backend
313 */
314 spapr_xive_set_tctx_os_cam(XIVE_TCTX(obj));
315 return obj;
316 }
317
318 static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id)
319 {
320 return 0;
321 }
322
323 static void spapr_irq_reset_xive(sPAPRMachineState *spapr, Error **errp)
324 {
325 CPUState *cs;
326
327 CPU_FOREACH(cs) {
328 PowerPCCPU *cpu = POWERPC_CPU(cs);
329
330 /* (TCG) Set the OS CAM line of the thread interrupt context. */
331 spapr_xive_set_tctx_os_cam(XIVE_TCTX(cpu->intc));
332 }
333 }
334
335 /*
336 * XIVE uses the full IRQ number space. Set it to 8K to be compatible
337 * with XICS.
338 */
339
340 #define SPAPR_IRQ_XIVE_NR_IRQS 0x2000
341 #define SPAPR_IRQ_XIVE_NR_MSIS (SPAPR_IRQ_XIVE_NR_IRQS - SPAPR_IRQ_MSI)
342
343 sPAPRIrq spapr_irq_xive = {
344 .nr_irqs = SPAPR_IRQ_XIVE_NR_IRQS,
345 .nr_msis = SPAPR_IRQ_XIVE_NR_MSIS,
346
347 .init = spapr_irq_init_xive,
348 .claim = spapr_irq_claim_xive,
349 .free = spapr_irq_free_xive,
350 .qirq = spapr_qirq_xive,
351 .print_info = spapr_irq_print_info_xive,
352 .dt_populate = spapr_dt_xive,
353 .cpu_intc_create = spapr_irq_cpu_intc_create_xive,
354 .post_load = spapr_irq_post_load_xive,
355 .reset = spapr_irq_reset_xive,
356 };
357
358 /*
359 * sPAPR IRQ frontend routines for devices
360 */
361 void spapr_irq_init(sPAPRMachineState *spapr, Error **errp)
362 {
363 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
364
365 /* Initialize the MSI IRQ allocator. */
366 if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
367 spapr_irq_msi_init(spapr, smc->irq->nr_msis);
368 }
369
370 smc->irq->init(spapr, errp);
371 }
372
373 int spapr_irq_claim(sPAPRMachineState *spapr, int irq, bool lsi, Error **errp)
374 {
375 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
376
377 return smc->irq->claim(spapr, irq, lsi, errp);
378 }
379
380 void spapr_irq_free(sPAPRMachineState *spapr, int irq, int num)
381 {
382 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
383
384 smc->irq->free(spapr, irq, num);
385 }
386
387 qemu_irq spapr_qirq(sPAPRMachineState *spapr, int irq)
388 {
389 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
390
391 return smc->irq->qirq(spapr, irq);
392 }
393
394 int spapr_irq_post_load(sPAPRMachineState *spapr, int version_id)
395 {
396 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
397
398 return smc->irq->post_load(spapr, version_id);
399 }
400
401 void spapr_irq_reset(sPAPRMachineState *spapr, Error **errp)
402 {
403 sPAPRMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
404
405 if (smc->irq->reset) {
406 smc->irq->reset(spapr, errp);
407 }
408 }
409
410 /*
411 * XICS legacy routines - to deprecate one day
412 */
413
414 static int ics_find_free_block(ICSState *ics, int num, int alignnum)
415 {
416 int first, i;
417
418 for (first = 0; first < ics->nr_irqs; first += alignnum) {
419 if (num > (ics->nr_irqs - first)) {
420 return -1;
421 }
422 for (i = first; i < first + num; ++i) {
423 if (!ICS_IRQ_FREE(ics, i)) {
424 break;
425 }
426 }
427 if (i == (first + num)) {
428 return first;
429 }
430 }
431
432 return -1;
433 }
434
435 int spapr_irq_find(sPAPRMachineState *spapr, int num, bool align, Error **errp)
436 {
437 ICSState *ics = spapr->ics;
438 int first = -1;
439
440 assert(ics);
441
442 /*
443 * MSIMesage::data is used for storing VIRQ so
444 * it has to be aligned to num to support multiple
445 * MSI vectors. MSI-X is not affected by this.
446 * The hint is used for the first IRQ, the rest should
447 * be allocated continuously.
448 */
449 if (align) {
450 assert((num == 1) || (num == 2) || (num == 4) ||
451 (num == 8) || (num == 16) || (num == 32));
452 first = ics_find_free_block(ics, num, num);
453 } else {
454 first = ics_find_free_block(ics, num, 1);
455 }
456
457 if (first < 0) {
458 error_setg(errp, "can't find a free %d-IRQ block", num);
459 return -1;
460 }
461
462 return first + ics->offset;
463 }
464
465 #define SPAPR_IRQ_XICS_LEGACY_NR_IRQS 0x400
466
467 sPAPRIrq spapr_irq_xics_legacy = {
468 .nr_irqs = SPAPR_IRQ_XICS_LEGACY_NR_IRQS,
469 .nr_msis = SPAPR_IRQ_XICS_LEGACY_NR_IRQS,
470
471 .init = spapr_irq_init_xics,
472 .claim = spapr_irq_claim_xics,
473 .free = spapr_irq_free_xics,
474 .qirq = spapr_qirq_xics,
475 .print_info = spapr_irq_print_info_xics,
476 .dt_populate = spapr_dt_xics,
477 .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
478 .post_load = spapr_irq_post_load_xics,
479 };