xref: /qemu/hw/intc/xics.c (revision 59427871)
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 "hw/hw.h"
29 #include "trace.h"
30 #include "qemu/timer.h"
31 #include "hw/ppc/spapr.h"
32 #include "hw/ppc/xics.h"
33 #include "qemu/error-report.h"
34 #include "qapi/visitor.h"
35 
36 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
37 {
38     CPUState *cs = CPU(cpu);
39     CPUPPCState *env = &cpu->env;
40     ICPState *ss = &icp->ss[cs->cpu_index];
41     XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
42 
43     assert(cs->cpu_index < icp->nr_servers);
44 
45     if (info->cpu_setup) {
46         info->cpu_setup(icp, cpu);
47     }
48 
49     switch (PPC_INPUT(env)) {
50     case PPC_FLAGS_INPUT_POWER7:
51         ss->output = env->irq_inputs[POWER7_INPUT_INT];
52         break;
53 
54     case PPC_FLAGS_INPUT_970:
55         ss->output = env->irq_inputs[PPC970_INPUT_INT];
56         break;
57 
58     default:
59         error_report("XICS interrupt controller does not support this CPU "
60                      "bus model");
61         abort();
62     }
63 }
64 
65 /*
66  * XICS Common class - parent for emulated XICS and KVM-XICS
67  */
68 static void xics_common_reset(DeviceState *d)
69 {
70     XICSState *icp = XICS_COMMON(d);
71     int i;
72 
73     for (i = 0; i < icp->nr_servers; i++) {
74         device_reset(DEVICE(&icp->ss[i]));
75     }
76 
77     device_reset(DEVICE(icp->ics));
78 }
79 
80 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v,
81                                   void *opaque, const char *name, Error **errp)
82 {
83     XICSState *icp = XICS_COMMON(obj);
84     int64_t value = icp->nr_irqs;
85 
86     visit_type_int(v, &value, name, errp);
87 }
88 
89 static void xics_prop_set_nr_irqs(Object *obj, Visitor *v,
90                                   void *opaque, const char *name, Error **errp)
91 {
92     XICSState *icp = XICS_COMMON(obj);
93     XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
94     Error *error = NULL;
95     int64_t value;
96 
97     visit_type_int(v, &value, name, &error);
98     if (error) {
99         error_propagate(errp, error);
100         return;
101     }
102     if (icp->nr_irqs) {
103         error_setg(errp, "Number of interrupts is already set to %u",
104                    icp->nr_irqs);
105         return;
106     }
107 
108     assert(info->set_nr_irqs);
109     assert(icp->ics);
110     info->set_nr_irqs(icp, value, errp);
111 }
112 
113 static void xics_prop_get_nr_servers(Object *obj, Visitor *v,
114                                      void *opaque, const char *name,
115                                      Error **errp)
116 {
117     XICSState *icp = XICS_COMMON(obj);
118     int64_t value = icp->nr_servers;
119 
120     visit_type_int(v, &value, name, errp);
121 }
122 
123 static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
124                                      void *opaque, const char *name,
125                                      Error **errp)
126 {
127     XICSState *icp = XICS_COMMON(obj);
128     XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
129     Error *error = NULL;
130     int64_t value;
131 
132     visit_type_int(v, &value, name, &error);
133     if (error) {
134         error_propagate(errp, error);
135         return;
136     }
137     if (icp->nr_servers) {
138         error_setg(errp, "Number of servers is already set to %u",
139                    icp->nr_servers);
140         return;
141     }
142 
143     assert(info->set_nr_servers);
144     info->set_nr_servers(icp, value, errp);
145 }
146 
147 static void xics_common_initfn(Object *obj)
148 {
149     object_property_add(obj, "nr_irqs", "int",
150                         xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
151                         NULL, NULL, NULL);
152     object_property_add(obj, "nr_servers", "int",
153                         xics_prop_get_nr_servers, xics_prop_set_nr_servers,
154                         NULL, NULL, NULL);
155 }
156 
157 static void xics_common_class_init(ObjectClass *oc, void *data)
158 {
159     DeviceClass *dc = DEVICE_CLASS(oc);
160 
161     dc->reset = xics_common_reset;
162 }
163 
164 static const TypeInfo xics_common_info = {
165     .name          = TYPE_XICS_COMMON,
166     .parent        = TYPE_SYS_BUS_DEVICE,
167     .instance_size = sizeof(XICSState),
168     .class_size    = sizeof(XICSStateClass),
169     .instance_init = xics_common_initfn,
170     .class_init    = xics_common_class_init,
171 };
172 
173 /*
174  * ICP: Presentation layer
175  */
176 
177 #define XISR_MASK  0x00ffffff
178 #define CPPR_MASK  0xff000000
179 
180 #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
181 #define CPPR(ss)   (((ss)->xirr) >> 24)
182 
183 static void ics_reject(ICSState *ics, int nr);
184 static void ics_resend(ICSState *ics);
185 static void ics_eoi(ICSState *ics, int nr);
186 
187 static void icp_check_ipi(XICSState *icp, int server)
188 {
189     ICPState *ss = icp->ss + server;
190 
191     if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
192         return;
193     }
194 
195     trace_xics_icp_check_ipi(server, ss->mfrr);
196 
197     if (XISR(ss)) {
198         ics_reject(icp->ics, XISR(ss));
199     }
200 
201     ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
202     ss->pending_priority = ss->mfrr;
203     qemu_irq_raise(ss->output);
204 }
205 
206 static void icp_resend(XICSState *icp, int server)
207 {
208     ICPState *ss = icp->ss + server;
209 
210     if (ss->mfrr < CPPR(ss)) {
211         icp_check_ipi(icp, server);
212     }
213     ics_resend(icp->ics);
214 }
215 
216 static void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
217 {
218     ICPState *ss = icp->ss + server;
219     uint8_t old_cppr;
220     uint32_t old_xisr;
221 
222     old_cppr = CPPR(ss);
223     ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
224 
225     if (cppr < old_cppr) {
226         if (XISR(ss) && (cppr <= ss->pending_priority)) {
227             old_xisr = XISR(ss);
228             ss->xirr &= ~XISR_MASK; /* Clear XISR */
229             ss->pending_priority = 0xff;
230             qemu_irq_lower(ss->output);
231             ics_reject(icp->ics, old_xisr);
232         }
233     } else {
234         if (!XISR(ss)) {
235             icp_resend(icp, server);
236         }
237     }
238 }
239 
240 static void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
241 {
242     ICPState *ss = icp->ss + server;
243 
244     ss->mfrr = mfrr;
245     if (mfrr < CPPR(ss)) {
246         icp_check_ipi(icp, server);
247     }
248 }
249 
250 static uint32_t icp_accept(ICPState *ss)
251 {
252     uint32_t xirr = ss->xirr;
253 
254     qemu_irq_lower(ss->output);
255     ss->xirr = ss->pending_priority << 24;
256     ss->pending_priority = 0xff;
257 
258     trace_xics_icp_accept(xirr, ss->xirr);
259 
260     return xirr;
261 }
262 
263 static void icp_eoi(XICSState *icp, int server, uint32_t xirr)
264 {
265     ICPState *ss = icp->ss + server;
266 
267     /* Send EOI -> ICS */
268     ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
269     trace_xics_icp_eoi(server, xirr, ss->xirr);
270     ics_eoi(icp->ics, xirr & XISR_MASK);
271     if (!XISR(ss)) {
272         icp_resend(icp, server);
273     }
274 }
275 
276 static void icp_irq(XICSState *icp, int server, int nr, uint8_t priority)
277 {
278     ICPState *ss = icp->ss + server;
279 
280     trace_xics_icp_irq(server, nr, priority);
281 
282     if ((priority >= CPPR(ss))
283         || (XISR(ss) && (ss->pending_priority <= priority))) {
284         ics_reject(icp->ics, nr);
285     } else {
286         if (XISR(ss)) {
287             ics_reject(icp->ics, XISR(ss));
288         }
289         ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
290         ss->pending_priority = priority;
291         trace_xics_icp_raise(ss->xirr, ss->pending_priority);
292         qemu_irq_raise(ss->output);
293     }
294 }
295 
296 static void icp_dispatch_pre_save(void *opaque)
297 {
298     ICPState *ss = opaque;
299     ICPStateClass *info = ICP_GET_CLASS(ss);
300 
301     if (info->pre_save) {
302         info->pre_save(ss);
303     }
304 }
305 
306 static int icp_dispatch_post_load(void *opaque, int version_id)
307 {
308     ICPState *ss = opaque;
309     ICPStateClass *info = ICP_GET_CLASS(ss);
310 
311     if (info->post_load) {
312         return info->post_load(ss, version_id);
313     }
314 
315     return 0;
316 }
317 
318 static const VMStateDescription vmstate_icp_server = {
319     .name = "icp/server",
320     .version_id = 1,
321     .minimum_version_id = 1,
322     .minimum_version_id_old = 1,
323     .pre_save = icp_dispatch_pre_save,
324     .post_load = icp_dispatch_post_load,
325     .fields      = (VMStateField []) {
326         /* Sanity check */
327         VMSTATE_UINT32(xirr, ICPState),
328         VMSTATE_UINT8(pending_priority, ICPState),
329         VMSTATE_UINT8(mfrr, ICPState),
330         VMSTATE_END_OF_LIST()
331     },
332 };
333 
334 static void icp_reset(DeviceState *dev)
335 {
336     ICPState *icp = ICP(dev);
337 
338     icp->xirr = 0;
339     icp->pending_priority = 0xff;
340     icp->mfrr = 0xff;
341 
342     /* Make all outputs are deasserted */
343     qemu_set_irq(icp->output, 0);
344 }
345 
346 static void icp_class_init(ObjectClass *klass, void *data)
347 {
348     DeviceClass *dc = DEVICE_CLASS(klass);
349 
350     dc->reset = icp_reset;
351     dc->vmsd = &vmstate_icp_server;
352 }
353 
354 static const TypeInfo icp_info = {
355     .name = TYPE_ICP,
356     .parent = TYPE_DEVICE,
357     .instance_size = sizeof(ICPState),
358     .class_init = icp_class_init,
359     .class_size = sizeof(ICPStateClass),
360 };
361 
362 /*
363  * ICS: Source layer
364  */
365 static int ics_valid_irq(ICSState *ics, uint32_t nr)
366 {
367     return (nr >= ics->offset)
368         && (nr < (ics->offset + ics->nr_irqs));
369 }
370 
371 static void resend_msi(ICSState *ics, int srcno)
372 {
373     ICSIRQState *irq = ics->irqs + srcno;
374 
375     /* FIXME: filter by server#? */
376     if (irq->status & XICS_STATUS_REJECTED) {
377         irq->status &= ~XICS_STATUS_REJECTED;
378         if (irq->priority != 0xff) {
379             icp_irq(ics->icp, irq->server, srcno + ics->offset,
380                     irq->priority);
381         }
382     }
383 }
384 
385 static void resend_lsi(ICSState *ics, int srcno)
386 {
387     ICSIRQState *irq = ics->irqs + srcno;
388 
389     if ((irq->priority != 0xff)
390         && (irq->status & XICS_STATUS_ASSERTED)
391         && !(irq->status & XICS_STATUS_SENT)) {
392         irq->status |= XICS_STATUS_SENT;
393         icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
394     }
395 }
396 
397 static void set_irq_msi(ICSState *ics, int srcno, int val)
398 {
399     ICSIRQState *irq = ics->irqs + srcno;
400 
401     trace_xics_set_irq_msi(srcno, srcno + ics->offset);
402 
403     if (val) {
404         if (irq->priority == 0xff) {
405             irq->status |= XICS_STATUS_MASKED_PENDING;
406             trace_xics_masked_pending();
407         } else  {
408             icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
409         }
410     }
411 }
412 
413 static void set_irq_lsi(ICSState *ics, int srcno, int val)
414 {
415     ICSIRQState *irq = ics->irqs + srcno;
416 
417     trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
418     if (val) {
419         irq->status |= XICS_STATUS_ASSERTED;
420     } else {
421         irq->status &= ~XICS_STATUS_ASSERTED;
422     }
423     resend_lsi(ics, srcno);
424 }
425 
426 static void ics_set_irq(void *opaque, int srcno, int val)
427 {
428     ICSState *ics = (ICSState *)opaque;
429 
430     if (ics->islsi[srcno]) {
431         set_irq_lsi(ics, srcno, val);
432     } else {
433         set_irq_msi(ics, srcno, val);
434     }
435 }
436 
437 static void write_xive_msi(ICSState *ics, int srcno)
438 {
439     ICSIRQState *irq = ics->irqs + srcno;
440 
441     if (!(irq->status & XICS_STATUS_MASKED_PENDING)
442         || (irq->priority == 0xff)) {
443         return;
444     }
445 
446     irq->status &= ~XICS_STATUS_MASKED_PENDING;
447     icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
448 }
449 
450 static void write_xive_lsi(ICSState *ics, int srcno)
451 {
452     resend_lsi(ics, srcno);
453 }
454 
455 static void ics_write_xive(ICSState *ics, int nr, int server,
456                            uint8_t priority, uint8_t saved_priority)
457 {
458     int srcno = nr - ics->offset;
459     ICSIRQState *irq = ics->irqs + srcno;
460 
461     irq->server = server;
462     irq->priority = priority;
463     irq->saved_priority = saved_priority;
464 
465     trace_xics_ics_write_xive(nr, srcno, server, priority);
466 
467     if (ics->islsi[srcno]) {
468         write_xive_lsi(ics, srcno);
469     } else {
470         write_xive_msi(ics, srcno);
471     }
472 }
473 
474 static void ics_reject(ICSState *ics, int nr)
475 {
476     ICSIRQState *irq = ics->irqs + nr - ics->offset;
477 
478     trace_xics_ics_reject(nr, nr - ics->offset);
479     irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
480     irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
481 }
482 
483 static void ics_resend(ICSState *ics)
484 {
485     int i;
486 
487     for (i = 0; i < ics->nr_irqs; i++) {
488         /* FIXME: filter by server#? */
489         if (ics->islsi[i]) {
490             resend_lsi(ics, i);
491         } else {
492             resend_msi(ics, i);
493         }
494     }
495 }
496 
497 static void ics_eoi(ICSState *ics, int nr)
498 {
499     int srcno = nr - ics->offset;
500     ICSIRQState *irq = ics->irqs + srcno;
501 
502     trace_xics_ics_eoi(nr);
503 
504     if (ics->islsi[srcno]) {
505         irq->status &= ~XICS_STATUS_SENT;
506     }
507 }
508 
509 static void ics_reset(DeviceState *dev)
510 {
511     ICSState *ics = ICS(dev);
512     int i;
513 
514     memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
515     for (i = 0; i < ics->nr_irqs; i++) {
516         ics->irqs[i].priority = 0xff;
517         ics->irqs[i].saved_priority = 0xff;
518     }
519 }
520 
521 static int ics_post_load(ICSState *ics, int version_id)
522 {
523     int i;
524 
525     for (i = 0; i < ics->icp->nr_servers; i++) {
526         icp_resend(ics->icp, i);
527     }
528 
529     return 0;
530 }
531 
532 static void ics_dispatch_pre_save(void *opaque)
533 {
534     ICSState *ics = opaque;
535     ICSStateClass *info = ICS_GET_CLASS(ics);
536 
537     if (info->pre_save) {
538         info->pre_save(ics);
539     }
540 }
541 
542 static int ics_dispatch_post_load(void *opaque, int version_id)
543 {
544     ICSState *ics = opaque;
545     ICSStateClass *info = ICS_GET_CLASS(ics);
546 
547     if (info->post_load) {
548         return info->post_load(ics, version_id);
549     }
550 
551     return 0;
552 }
553 
554 static const VMStateDescription vmstate_ics_irq = {
555     .name = "ics/irq",
556     .version_id = 1,
557     .minimum_version_id = 1,
558     .minimum_version_id_old = 1,
559     .fields      = (VMStateField []) {
560         VMSTATE_UINT32(server, ICSIRQState),
561         VMSTATE_UINT8(priority, ICSIRQState),
562         VMSTATE_UINT8(saved_priority, ICSIRQState),
563         VMSTATE_UINT8(status, ICSIRQState),
564         VMSTATE_END_OF_LIST()
565     },
566 };
567 
568 static const VMStateDescription vmstate_ics = {
569     .name = "ics",
570     .version_id = 1,
571     .minimum_version_id = 1,
572     .minimum_version_id_old = 1,
573     .pre_save = ics_dispatch_pre_save,
574     .post_load = ics_dispatch_post_load,
575     .fields      = (VMStateField []) {
576         /* Sanity check */
577         VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
578 
579         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
580                                              vmstate_ics_irq, ICSIRQState),
581         VMSTATE_END_OF_LIST()
582     },
583 };
584 
585 static void ics_initfn(Object *obj)
586 {
587     ICSState *ics = ICS(obj);
588 
589     ics->offset = XICS_IRQ_BASE;
590 }
591 
592 static void ics_realize(DeviceState *dev, Error **errp)
593 {
594     ICSState *ics = ICS(dev);
595 
596     if (!ics->nr_irqs) {
597         error_setg(errp, "Number of interrupts needs to be greater 0");
598         return;
599     }
600     ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
601     ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
602     ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
603 }
604 
605 static void ics_class_init(ObjectClass *klass, void *data)
606 {
607     DeviceClass *dc = DEVICE_CLASS(klass);
608     ICSStateClass *isc = ICS_CLASS(klass);
609 
610     dc->realize = ics_realize;
611     dc->vmsd = &vmstate_ics;
612     dc->reset = ics_reset;
613     isc->post_load = ics_post_load;
614 }
615 
616 static const TypeInfo ics_info = {
617     .name = TYPE_ICS,
618     .parent = TYPE_DEVICE,
619     .instance_size = sizeof(ICSState),
620     .class_init = ics_class_init,
621     .class_size = sizeof(ICSStateClass),
622     .instance_init = ics_initfn,
623 };
624 
625 /*
626  * Exported functions
627  */
628 
629 qemu_irq xics_get_qirq(XICSState *icp, int irq)
630 {
631     if (!ics_valid_irq(icp->ics, irq)) {
632         return NULL;
633     }
634 
635     return icp->ics->qirqs[irq - icp->ics->offset];
636 }
637 
638 void xics_set_irq_type(XICSState *icp, int irq, bool lsi)
639 {
640     assert(ics_valid_irq(icp->ics, irq));
641 
642     icp->ics->islsi[irq - icp->ics->offset] = lsi;
643 }
644 
645 /*
646  * Guest interfaces
647  */
648 
649 static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
650                            target_ulong opcode, target_ulong *args)
651 {
652     CPUState *cs = CPU(cpu);
653     target_ulong cppr = args[0];
654 
655     icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
656     return H_SUCCESS;
657 }
658 
659 static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
660                           target_ulong opcode, target_ulong *args)
661 {
662     target_ulong server = args[0];
663     target_ulong mfrr = args[1];
664 
665     if (server >= spapr->icp->nr_servers) {
666         return H_PARAMETER;
667     }
668 
669     icp_set_mfrr(spapr->icp, server, mfrr);
670     return H_SUCCESS;
671 }
672 
673 static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
674                            target_ulong opcode, target_ulong *args)
675 {
676     CPUState *cs = CPU(cpu);
677     uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
678 
679     args[0] = xirr;
680     return H_SUCCESS;
681 }
682 
683 static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPREnvironment *spapr,
684                              target_ulong opcode, target_ulong *args)
685 {
686     CPUState *cs = CPU(cpu);
687     ICPState *ss = &spapr->icp->ss[cs->cpu_index];
688     uint32_t xirr = icp_accept(ss);
689 
690     args[0] = xirr;
691     args[1] = cpu_get_real_ticks();
692     return H_SUCCESS;
693 }
694 
695 static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
696                           target_ulong opcode, target_ulong *args)
697 {
698     CPUState *cs = CPU(cpu);
699     target_ulong xirr = args[0];
700 
701     icp_eoi(spapr->icp, cs->cpu_index, xirr);
702     return H_SUCCESS;
703 }
704 
705 static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPREnvironment *spapr,
706                             target_ulong opcode, target_ulong *args)
707 {
708     CPUState *cs = CPU(cpu);
709     ICPState *ss = &spapr->icp->ss[cs->cpu_index];
710 
711     args[0] = ss->xirr;
712     args[1] = ss->mfrr;
713 
714     return H_SUCCESS;
715 }
716 
717 static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
718                           uint32_t token,
719                           uint32_t nargs, target_ulong args,
720                           uint32_t nret, target_ulong rets)
721 {
722     ICSState *ics = spapr->icp->ics;
723     uint32_t nr, server, priority;
724 
725     if ((nargs != 3) || (nret != 1)) {
726         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
727         return;
728     }
729 
730     nr = rtas_ld(args, 0);
731     server = rtas_ld(args, 1);
732     priority = rtas_ld(args, 2);
733 
734     if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
735         || (priority > 0xff)) {
736         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
737         return;
738     }
739 
740     ics_write_xive(ics, nr, server, priority, priority);
741 
742     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
743 }
744 
745 static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
746                           uint32_t token,
747                           uint32_t nargs, target_ulong args,
748                           uint32_t nret, target_ulong rets)
749 {
750     ICSState *ics = spapr->icp->ics;
751     uint32_t nr;
752 
753     if ((nargs != 1) || (nret != 3)) {
754         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
755         return;
756     }
757 
758     nr = rtas_ld(args, 0);
759 
760     if (!ics_valid_irq(ics, nr)) {
761         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
762         return;
763     }
764 
765     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
766     rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
767     rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
768 }
769 
770 static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
771                          uint32_t token,
772                          uint32_t nargs, target_ulong args,
773                          uint32_t nret, target_ulong rets)
774 {
775     ICSState *ics = spapr->icp->ics;
776     uint32_t nr;
777 
778     if ((nargs != 1) || (nret != 1)) {
779         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
780         return;
781     }
782 
783     nr = rtas_ld(args, 0);
784 
785     if (!ics_valid_irq(ics, nr)) {
786         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
787         return;
788     }
789 
790     ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
791                    ics->irqs[nr - ics->offset].priority);
792 
793     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
794 }
795 
796 static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
797                         uint32_t token,
798                         uint32_t nargs, target_ulong args,
799                         uint32_t nret, target_ulong rets)
800 {
801     ICSState *ics = spapr->icp->ics;
802     uint32_t nr;
803 
804     if ((nargs != 1) || (nret != 1)) {
805         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
806         return;
807     }
808 
809     nr = rtas_ld(args, 0);
810 
811     if (!ics_valid_irq(ics, nr)) {
812         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
813         return;
814     }
815 
816     ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
817                    ics->irqs[nr - ics->offset].saved_priority,
818                    ics->irqs[nr - ics->offset].saved_priority);
819 
820     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
821 }
822 
823 /*
824  * XICS
825  */
826 
827 static void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
828 {
829     icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
830 }
831 
832 static void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers,
833                                 Error **errp)
834 {
835     int i;
836 
837     icp->nr_servers = nr_servers;
838 
839     icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
840     for (i = 0; i < icp->nr_servers; i++) {
841         char buffer[32];
842         object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
843         snprintf(buffer, sizeof(buffer), "icp[%d]", i);
844         object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
845                                   errp);
846     }
847 }
848 
849 static void xics_realize(DeviceState *dev, Error **errp)
850 {
851     XICSState *icp = XICS(dev);
852     Error *error = NULL;
853     int i;
854 
855     if (!icp->nr_servers) {
856         error_setg(errp, "Number of servers needs to be greater 0");
857         return;
858     }
859 
860     /* Registration of global state belongs into realize */
861     spapr_rtas_register("ibm,set-xive", rtas_set_xive);
862     spapr_rtas_register("ibm,get-xive", rtas_get_xive);
863     spapr_rtas_register("ibm,int-off", rtas_int_off);
864     spapr_rtas_register("ibm,int-on", rtas_int_on);
865 
866     spapr_register_hypercall(H_CPPR, h_cppr);
867     spapr_register_hypercall(H_IPI, h_ipi);
868     spapr_register_hypercall(H_XIRR, h_xirr);
869     spapr_register_hypercall(H_XIRR_X, h_xirr_x);
870     spapr_register_hypercall(H_EOI, h_eoi);
871     spapr_register_hypercall(H_IPOLL, h_ipoll);
872 
873     object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
874     if (error) {
875         error_propagate(errp, error);
876         return;
877     }
878 
879     for (i = 0; i < icp->nr_servers; i++) {
880         object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
881         if (error) {
882             error_propagate(errp, error);
883             return;
884         }
885     }
886 }
887 
888 static void xics_initfn(Object *obj)
889 {
890     XICSState *xics = XICS(obj);
891 
892     xics->ics = ICS(object_new(TYPE_ICS));
893     object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
894     xics->ics->icp = xics;
895 }
896 
897 static void xics_class_init(ObjectClass *oc, void *data)
898 {
899     DeviceClass *dc = DEVICE_CLASS(oc);
900     XICSStateClass *xsc = XICS_CLASS(oc);
901 
902     dc->realize = xics_realize;
903     xsc->set_nr_irqs = xics_set_nr_irqs;
904     xsc->set_nr_servers = xics_set_nr_servers;
905 }
906 
907 static const TypeInfo xics_info = {
908     .name          = TYPE_XICS,
909     .parent        = TYPE_XICS_COMMON,
910     .instance_size = sizeof(XICSState),
911     .class_size = sizeof(XICSStateClass),
912     .class_init    = xics_class_init,
913     .instance_init = xics_initfn,
914 };
915 
916 static void xics_register_types(void)
917 {
918     type_register_static(&xics_common_info);
919     type_register_static(&xics_info);
920     type_register_static(&ics_info);
921     type_register_static(&icp_info);
922 }
923 
924 type_init(xics_register_types)
925