xref: /qemu/hw/intc/xics_spapr.c (revision 5242494c056f19be05335e8a190e7a40f72e6a22)
1 /*
2  * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
3  *
4  * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
5  *
6  * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  *
26  */
27 
28 #include "qemu/osdep.h"
29 #include "trace.h"
30 #include "qemu/timer.h"
31 #include "hw/ppc/spapr.h"
32 #include "hw/ppc/spapr_cpu_core.h"
33 #include "hw/ppc/xics.h"
34 #include "hw/ppc/xics_spapr.h"
35 #include "hw/ppc/fdt.h"
36 #include "qapi/visitor.h"
37 #include "qapi/type-helpers.h"
38 #include "monitor/monitor.h"
39 
40 /*
41  * Guest interfaces
42  */
43 
44 static bool check_emulated_xics(SpaprMachineState *spapr, const char *func)
45 {
46     if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ||
47         kvm_irqchip_in_kernel()) {
48         error_report("pseries: %s must only be called for emulated XICS",
49                      func);
50         return false;
51     }
52 
53     return true;
54 }
55 
56 #define CHECK_EMULATED_XICS_HCALL(spapr)               \
57     do {                                               \
58         if (!check_emulated_xics((spapr), __func__)) { \
59             return H_HARDWARE;                         \
60         }                                              \
61     } while (0)
62 
63 static target_ulong h_cppr(PowerPCCPU *cpu, SpaprMachineState *spapr,
64                            target_ulong opcode, target_ulong *args)
65 {
66     target_ulong cppr = args[0];
67 
68     CHECK_EMULATED_XICS_HCALL(spapr);
69 
70     icp_set_cppr(spapr_cpu_state(cpu)->icp, cppr);
71     return H_SUCCESS;
72 }
73 
74 static target_ulong h_ipi(PowerPCCPU *cpu, SpaprMachineState *spapr,
75                           target_ulong opcode, target_ulong *args)
76 {
77     target_ulong mfrr = args[1];
78     ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]);
79 
80     CHECK_EMULATED_XICS_HCALL(spapr);
81 
82     if (!icp) {
83         return H_PARAMETER;
84     }
85 
86     icp_set_mfrr(icp, mfrr);
87     return H_SUCCESS;
88 }
89 
90 static target_ulong h_xirr(PowerPCCPU *cpu, SpaprMachineState *spapr,
91                            target_ulong opcode, target_ulong *args)
92 {
93     uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
94 
95     CHECK_EMULATED_XICS_HCALL(spapr);
96 
97     args[0] = xirr;
98     return H_SUCCESS;
99 }
100 
101 static target_ulong h_xirr_x(PowerPCCPU *cpu, SpaprMachineState *spapr,
102                              target_ulong opcode, target_ulong *args)
103 {
104     uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
105 
106     CHECK_EMULATED_XICS_HCALL(spapr);
107 
108     args[0] = xirr;
109     args[1] = cpu_get_host_ticks();
110     return H_SUCCESS;
111 }
112 
113 static target_ulong h_eoi(PowerPCCPU *cpu, SpaprMachineState *spapr,
114                           target_ulong opcode, target_ulong *args)
115 {
116     target_ulong xirr = args[0];
117 
118     CHECK_EMULATED_XICS_HCALL(spapr);
119 
120     icp_eoi(spapr_cpu_state(cpu)->icp, xirr);
121     return H_SUCCESS;
122 }
123 
124 static target_ulong h_ipoll(PowerPCCPU *cpu, SpaprMachineState *spapr,
125                             target_ulong opcode, target_ulong *args)
126 {
127     ICPState *icp = xics_icp_get(XICS_FABRIC(spapr), args[0]);
128     uint32_t mfrr;
129     uint32_t xirr;
130 
131     CHECK_EMULATED_XICS_HCALL(spapr);
132 
133     if (!icp) {
134         return H_PARAMETER;
135     }
136 
137     xirr = icp_ipoll(icp, &mfrr);
138 
139     args[0] = xirr;
140     args[1] = mfrr;
141 
142     return H_SUCCESS;
143 }
144 
145 #define CHECK_EMULATED_XICS_RTAS(spapr, rets)          \
146     do {                                               \
147         if (!check_emulated_xics((spapr), __func__)) { \
148             rtas_st((rets), 0, RTAS_OUT_HW_ERROR);     \
149             return;                                    \
150         }                                              \
151     } while (0)
152 
153 static void rtas_set_xive(PowerPCCPU *cpu, SpaprMachineState *spapr,
154                           uint32_t token,
155                           uint32_t nargs, target_ulong args,
156                           uint32_t nret, target_ulong rets)
157 {
158     ICSState *ics = spapr->ics;
159     uint32_t nr, srcno, server, priority;
160 
161     CHECK_EMULATED_XICS_RTAS(spapr, rets);
162 
163     if ((nargs != 3) || (nret != 1)) {
164         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
165         return;
166     }
167     if (!ics) {
168         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
169         return;
170     }
171 
172     nr = rtas_ld(args, 0);
173     server = rtas_ld(args, 1);
174     priority = rtas_ld(args, 2);
175 
176     if (!ics_valid_irq(ics, nr) || !xics_icp_get(XICS_FABRIC(spapr), server)
177         || (priority > 0xff)) {
178         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
179         return;
180     }
181 
182     srcno = nr - ics->offset;
183     ics_write_xive(ics, srcno, server, priority, priority);
184 
185     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
186 }
187 
188 static void rtas_get_xive(PowerPCCPU *cpu, SpaprMachineState *spapr,
189                           uint32_t token,
190                           uint32_t nargs, target_ulong args,
191                           uint32_t nret, target_ulong rets)
192 {
193     ICSState *ics = spapr->ics;
194     uint32_t nr, srcno;
195 
196     CHECK_EMULATED_XICS_RTAS(spapr, rets);
197 
198     if ((nargs != 1) || (nret != 3)) {
199         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
200         return;
201     }
202     if (!ics) {
203         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
204         return;
205     }
206 
207     nr = rtas_ld(args, 0);
208 
209     if (!ics_valid_irq(ics, nr)) {
210         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
211         return;
212     }
213 
214     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
215     srcno = nr - ics->offset;
216     rtas_st(rets, 1, ics->irqs[srcno].server);
217     rtas_st(rets, 2, ics->irqs[srcno].priority);
218 }
219 
220 static void rtas_int_off(PowerPCCPU *cpu, SpaprMachineState *spapr,
221                          uint32_t token,
222                          uint32_t nargs, target_ulong args,
223                          uint32_t nret, target_ulong rets)
224 {
225     ICSState *ics = spapr->ics;
226     uint32_t nr, srcno;
227 
228     CHECK_EMULATED_XICS_RTAS(spapr, rets);
229 
230     if ((nargs != 1) || (nret != 1)) {
231         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
232         return;
233     }
234     if (!ics) {
235         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
236         return;
237     }
238 
239     nr = rtas_ld(args, 0);
240 
241     if (!ics_valid_irq(ics, nr)) {
242         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
243         return;
244     }
245 
246     srcno = nr - ics->offset;
247     ics_write_xive(ics, srcno, ics->irqs[srcno].server, 0xff,
248                    ics->irqs[srcno].priority);
249 
250     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
251 }
252 
253 static void rtas_int_on(PowerPCCPU *cpu, SpaprMachineState *spapr,
254                         uint32_t token,
255                         uint32_t nargs, target_ulong args,
256                         uint32_t nret, target_ulong rets)
257 {
258     ICSState *ics = spapr->ics;
259     uint32_t nr, srcno;
260 
261     CHECK_EMULATED_XICS_RTAS(spapr, rets);
262 
263     if ((nargs != 1) || (nret != 1)) {
264         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
265         return;
266     }
267     if (!ics) {
268         rtas_st(rets, 0, RTAS_OUT_HW_ERROR);
269         return;
270     }
271 
272     nr = rtas_ld(args, 0);
273 
274     if (!ics_valid_irq(ics, nr)) {
275         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
276         return;
277     }
278 
279     srcno = nr - ics->offset;
280     ics_write_xive(ics, srcno, ics->irqs[srcno].server,
281                    ics->irqs[srcno].saved_priority,
282                    ics->irqs[srcno].saved_priority);
283 
284     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
285 }
286 
287 static void ics_spapr_realize(DeviceState *dev, Error **errp)
288 {
289     ICSState *ics = ICS_SPAPR(dev);
290     ICSStateClass *icsc = ICS_GET_CLASS(ics);
291     Error *local_err = NULL;
292 
293     icsc->parent_realize(dev, &local_err);
294     if (local_err) {
295         error_propagate(errp, local_err);
296         return;
297     }
298 
299     spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
300     spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive);
301     spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off);
302     spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_int_on);
303 
304     spapr_register_hypercall(H_CPPR, h_cppr);
305     spapr_register_hypercall(H_IPI, h_ipi);
306     spapr_register_hypercall(H_XIRR, h_xirr);
307     spapr_register_hypercall(H_XIRR_X, h_xirr_x);
308     spapr_register_hypercall(H_EOI, h_eoi);
309     spapr_register_hypercall(H_IPOLL, h_ipoll);
310 }
311 
312 static void xics_spapr_dt(SpaprInterruptController *intc, uint32_t nr_servers,
313                           void *fdt, uint32_t phandle)
314 {
315     uint32_t interrupt_server_ranges_prop[] = {
316         0, cpu_to_be32(nr_servers),
317     };
318     int node;
319 
320     _FDT(node = fdt_add_subnode(fdt, 0, "interrupt-controller"));
321 
322     _FDT(fdt_setprop_string(fdt, node, "device_type",
323                             "PowerPC-External-Interrupt-Presentation"));
324     _FDT(fdt_setprop_string(fdt, node, "compatible", "IBM,ppc-xicp"));
325     _FDT(fdt_setprop(fdt, node, "interrupt-controller", NULL, 0));
326     _FDT(fdt_setprop(fdt, node, "ibm,interrupt-server-ranges",
327                      interrupt_server_ranges_prop,
328                      sizeof(interrupt_server_ranges_prop)));
329     _FDT(fdt_setprop_cell(fdt, node, "#interrupt-cells", 2));
330     _FDT(fdt_setprop_cell(fdt, node, "linux,phandle", phandle));
331     _FDT(fdt_setprop_cell(fdt, node, "phandle", phandle));
332 }
333 
334 static int xics_spapr_cpu_intc_create(SpaprInterruptController *intc,
335                                        PowerPCCPU *cpu, Error **errp)
336 {
337     ICSState *ics = ICS_SPAPR(intc);
338     Object *obj;
339     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
340 
341     obj = icp_create(OBJECT(cpu), TYPE_ICP, ics->xics, errp);
342     if (!obj) {
343         return -1;
344     }
345 
346     spapr_cpu->icp = ICP(obj);
347     return 0;
348 }
349 
350 static void xics_spapr_cpu_intc_reset(SpaprInterruptController *intc,
351                                      PowerPCCPU *cpu)
352 {
353     icp_reset(spapr_cpu_state(cpu)->icp);
354 }
355 
356 static void xics_spapr_cpu_intc_destroy(SpaprInterruptController *intc,
357                                         PowerPCCPU *cpu)
358 {
359     SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
360 
361     icp_destroy(spapr_cpu->icp);
362     spapr_cpu->icp = NULL;
363 }
364 
365 static int xics_spapr_claim_irq(SpaprInterruptController *intc, int irq,
366                                 bool lsi, Error **errp)
367 {
368     ICSState *ics = ICS_SPAPR(intc);
369 
370     assert(ics);
371     assert(ics_valid_irq(ics, irq));
372 
373     if (!ics_irq_free(ics, irq - ics->offset)) {
374         error_setg(errp, "IRQ %d is not free", irq);
375         return -EBUSY;
376     }
377 
378     ics_set_irq_type(ics, irq - ics->offset, lsi);
379     return 0;
380 }
381 
382 static void xics_spapr_free_irq(SpaprInterruptController *intc, int irq)
383 {
384     ICSState *ics = ICS_SPAPR(intc);
385     uint32_t srcno = irq - ics->offset;
386 
387     assert(ics_valid_irq(ics, irq));
388 
389     memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
390 }
391 
392 static void xics_spapr_set_irq(SpaprInterruptController *intc, int irq, int val)
393 {
394     ICSState *ics = ICS_SPAPR(intc);
395     uint32_t srcno = irq - ics->offset;
396 
397     ics_set_irq(ics, srcno, val);
398 }
399 
400 static void xics_spapr_print_info(SpaprInterruptController *intc, Monitor *mon)
401 {
402     ICSState *ics = ICS_SPAPR(intc);
403     CPUState *cs;
404     g_autoptr(GString) buf = g_string_new("");
405     g_autoptr(HumanReadableText) info = NULL;
406 
407     CPU_FOREACH(cs) {
408         PowerPCCPU *cpu = POWERPC_CPU(cs);
409 
410         icp_pic_print_info(spapr_cpu_state(cpu)->icp, buf);
411     }
412     info = human_readable_text_from_str(buf);
413     monitor_puts(mon, info->human_readable_text);
414 
415     ics_pic_print_info(ics, mon);
416 }
417 
418 static int xics_spapr_post_load(SpaprInterruptController *intc, int version_id)
419 {
420     if (!kvm_irqchip_in_kernel()) {
421         CPUState *cs;
422         CPU_FOREACH(cs) {
423             PowerPCCPU *cpu = POWERPC_CPU(cs);
424             icp_resend(spapr_cpu_state(cpu)->icp);
425         }
426     }
427     return 0;
428 }
429 
430 static int xics_spapr_activate(SpaprInterruptController *intc,
431                                uint32_t nr_servers, Error **errp)
432 {
433     if (kvm_enabled()) {
434         return spapr_irq_init_kvm(xics_kvm_connect, intc, nr_servers, errp);
435     }
436     return 0;
437 }
438 
439 static void xics_spapr_deactivate(SpaprInterruptController *intc)
440 {
441     if (kvm_irqchip_in_kernel()) {
442         xics_kvm_disconnect(intc);
443     }
444 }
445 
446 static void ics_spapr_class_init(ObjectClass *klass, void *data)
447 {
448     DeviceClass *dc = DEVICE_CLASS(klass);
449     ICSStateClass *isc = ICS_CLASS(klass);
450     SpaprInterruptControllerClass *sicc = SPAPR_INTC_CLASS(klass);
451 
452     device_class_set_parent_realize(dc, ics_spapr_realize,
453                                     &isc->parent_realize);
454     sicc->activate = xics_spapr_activate;
455     sicc->deactivate = xics_spapr_deactivate;
456     sicc->cpu_intc_create = xics_spapr_cpu_intc_create;
457     sicc->cpu_intc_reset = xics_spapr_cpu_intc_reset;
458     sicc->cpu_intc_destroy = xics_spapr_cpu_intc_destroy;
459     sicc->claim_irq = xics_spapr_claim_irq;
460     sicc->free_irq = xics_spapr_free_irq;
461     sicc->set_irq = xics_spapr_set_irq;
462     sicc->print_info = xics_spapr_print_info;
463     sicc->dt = xics_spapr_dt;
464     sicc->post_load = xics_spapr_post_load;
465 }
466 
467 static const TypeInfo ics_spapr_info = {
468     .name = TYPE_ICS_SPAPR,
469     .parent = TYPE_ICS,
470     .class_init = ics_spapr_class_init,
471     .interfaces = (InterfaceInfo[]) {
472         { TYPE_SPAPR_INTC },
473         { }
474     },
475 };
476 
477 static void xics_spapr_register_types(void)
478 {
479     type_register_static(&ics_spapr_info);
480 }
481 
482 type_init(xics_spapr_register_types)
483