xref: /qemu/hw/intc/xics.c (revision 603476c2)
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 "qapi/error.h"
30 #include "qemu-common.h"
31 #include "cpu.h"
32 #include "hw/hw.h"
33 #include "trace.h"
34 #include "qemu/timer.h"
35 #include "hw/ppc/xics.h"
36 #include "qemu/error-report.h"
37 #include "qapi/visitor.h"
38 
39 int xics_get_cpu_index_by_dt_id(int cpu_dt_id)
40 {
41     PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id);
42 
43     if (cpu) {
44         return cpu->parent_obj.cpu_index;
45     }
46 
47     return -1;
48 }
49 
50 void xics_cpu_destroy(XICSState *xics, PowerPCCPU *cpu)
51 {
52     CPUState *cs = CPU(cpu);
53     ICPState *ss = &xics->ss[cs->cpu_index];
54 
55     assert(cs->cpu_index < xics->nr_servers);
56     assert(cs == ss->cs);
57 
58     ss->output = NULL;
59     ss->cs = NULL;
60 }
61 
62 void xics_cpu_setup(XICSState *xics, PowerPCCPU *cpu)
63 {
64     CPUState *cs = CPU(cpu);
65     CPUPPCState *env = &cpu->env;
66     ICPState *ss = &xics->ss[cs->cpu_index];
67     XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
68 
69     assert(cs->cpu_index < xics->nr_servers);
70 
71     ss->cs = cs;
72 
73     if (info->cpu_setup) {
74         info->cpu_setup(xics, cpu);
75     }
76 
77     switch (PPC_INPUT(env)) {
78     case PPC_FLAGS_INPUT_POWER7:
79         ss->output = env->irq_inputs[POWER7_INPUT_INT];
80         break;
81 
82     case PPC_FLAGS_INPUT_970:
83         ss->output = env->irq_inputs[PPC970_INPUT_INT];
84         break;
85 
86     default:
87         error_report("XICS interrupt controller does not support this CPU "
88                      "bus model");
89         abort();
90     }
91 }
92 
93 /*
94  * XICS Common class - parent for emulated XICS and KVM-XICS
95  */
96 static void xics_common_reset(DeviceState *d)
97 {
98     XICSState *xics = XICS_COMMON(d);
99     ICSState *ics;
100     int i;
101 
102     for (i = 0; i < xics->nr_servers; i++) {
103         device_reset(DEVICE(&xics->ss[i]));
104     }
105 
106     QLIST_FOREACH(ics, &xics->ics, list) {
107         device_reset(DEVICE(ics));
108     }
109 }
110 
111 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v, const char *name,
112                                   void *opaque, Error **errp)
113 {
114     XICSState *xics = XICS_COMMON(obj);
115     int64_t value = xics->nr_irqs;
116 
117     visit_type_int(v, name, &value, errp);
118 }
119 
120 static void xics_prop_set_nr_irqs(Object *obj, Visitor *v, const char *name,
121                                   void *opaque, Error **errp)
122 {
123     XICSState *xics = XICS_COMMON(obj);
124     XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
125     Error *error = NULL;
126     int64_t value;
127 
128     visit_type_int(v, name, &value, &error);
129     if (error) {
130         error_propagate(errp, error);
131         return;
132     }
133     if (xics->nr_irqs) {
134         error_setg(errp, "Number of interrupts is already set to %u",
135                    xics->nr_irqs);
136         return;
137     }
138 
139     assert(info->set_nr_irqs);
140     info->set_nr_irqs(xics, value, errp);
141 }
142 
143 static void xics_prop_get_nr_servers(Object *obj, Visitor *v,
144                                      const char *name, void *opaque,
145                                      Error **errp)
146 {
147     XICSState *xics = XICS_COMMON(obj);
148     int64_t value = xics->nr_servers;
149 
150     visit_type_int(v, name, &value, errp);
151 }
152 
153 static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
154                                      const char *name, void *opaque,
155                                      Error **errp)
156 {
157     XICSState *xics = XICS_COMMON(obj);
158     XICSStateClass *info = XICS_COMMON_GET_CLASS(xics);
159     Error *error = NULL;
160     int64_t value;
161 
162     visit_type_int(v, name, &value, &error);
163     if (error) {
164         error_propagate(errp, error);
165         return;
166     }
167     if (xics->nr_servers) {
168         error_setg(errp, "Number of servers is already set to %u",
169                    xics->nr_servers);
170         return;
171     }
172 
173     assert(info->set_nr_servers);
174     info->set_nr_servers(xics, value, errp);
175 }
176 
177 static void xics_common_initfn(Object *obj)
178 {
179     XICSState *xics = XICS_COMMON(obj);
180 
181     QLIST_INIT(&xics->ics);
182     object_property_add(obj, "nr_irqs", "int",
183                         xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
184                         NULL, NULL, NULL);
185     object_property_add(obj, "nr_servers", "int",
186                         xics_prop_get_nr_servers, xics_prop_set_nr_servers,
187                         NULL, NULL, NULL);
188 }
189 
190 static void xics_common_class_init(ObjectClass *oc, void *data)
191 {
192     DeviceClass *dc = DEVICE_CLASS(oc);
193 
194     dc->reset = xics_common_reset;
195 }
196 
197 static const TypeInfo xics_common_info = {
198     .name          = TYPE_XICS_COMMON,
199     .parent        = TYPE_SYS_BUS_DEVICE,
200     .instance_size = sizeof(XICSState),
201     .class_size    = sizeof(XICSStateClass),
202     .instance_init = xics_common_initfn,
203     .class_init    = xics_common_class_init,
204 };
205 
206 /*
207  * ICP: Presentation layer
208  */
209 
210 #define XISR_MASK  0x00ffffff
211 #define CPPR_MASK  0xff000000
212 
213 #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
214 #define CPPR(ss)   (((ss)->xirr) >> 24)
215 
216 static void ics_reject(ICSState *ics, uint32_t nr)
217 {
218     ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
219 
220     if (k->reject) {
221         k->reject(ics, nr);
222     }
223 }
224 
225 static void ics_resend(ICSState *ics)
226 {
227     ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
228 
229     if (k->resend) {
230         k->resend(ics);
231     }
232 }
233 
234 static void ics_eoi(ICSState *ics, int nr)
235 {
236     ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
237 
238     if (k->eoi) {
239         k->eoi(ics, nr);
240     }
241 }
242 
243 static void icp_check_ipi(ICPState *ss)
244 {
245     if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
246         return;
247     }
248 
249     trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);
250 
251     if (XISR(ss) && ss->xirr_owner) {
252         ics_reject(ss->xirr_owner, XISR(ss));
253     }
254 
255     ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
256     ss->pending_priority = ss->mfrr;
257     ss->xirr_owner = NULL;
258     qemu_irq_raise(ss->output);
259 }
260 
261 static void icp_resend(XICSState *xics, int server)
262 {
263     ICPState *ss = xics->ss + server;
264     ICSState *ics;
265 
266     if (ss->mfrr < CPPR(ss)) {
267         icp_check_ipi(ss);
268     }
269     QLIST_FOREACH(ics, &xics->ics, list) {
270         ics_resend(ics);
271     }
272 }
273 
274 void icp_set_cppr(XICSState *xics, int server, uint8_t cppr)
275 {
276     ICPState *ss = xics->ss + server;
277     uint8_t old_cppr;
278     uint32_t old_xisr;
279 
280     old_cppr = CPPR(ss);
281     ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
282 
283     if (cppr < old_cppr) {
284         if (XISR(ss) && (cppr <= ss->pending_priority)) {
285             old_xisr = XISR(ss);
286             ss->xirr &= ~XISR_MASK; /* Clear XISR */
287             ss->pending_priority = 0xff;
288             qemu_irq_lower(ss->output);
289             if (ss->xirr_owner) {
290                 ics_reject(ss->xirr_owner, old_xisr);
291                 ss->xirr_owner = NULL;
292             }
293         }
294     } else {
295         if (!XISR(ss)) {
296             icp_resend(xics, server);
297         }
298     }
299 }
300 
301 void icp_set_mfrr(XICSState *xics, int server, uint8_t mfrr)
302 {
303     ICPState *ss = xics->ss + server;
304 
305     ss->mfrr = mfrr;
306     if (mfrr < CPPR(ss)) {
307         icp_check_ipi(ss);
308     }
309 }
310 
311 uint32_t icp_accept(ICPState *ss)
312 {
313     uint32_t xirr = ss->xirr;
314 
315     qemu_irq_lower(ss->output);
316     ss->xirr = ss->pending_priority << 24;
317     ss->pending_priority = 0xff;
318     ss->xirr_owner = NULL;
319 
320     trace_xics_icp_accept(xirr, ss->xirr);
321 
322     return xirr;
323 }
324 
325 uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
326 {
327     if (mfrr) {
328         *mfrr = ss->mfrr;
329     }
330     return ss->xirr;
331 }
332 
333 void icp_eoi(XICSState *xics, int server, uint32_t xirr)
334 {
335     ICPState *ss = xics->ss + server;
336     ICSState *ics;
337     uint32_t irq;
338 
339     /* Send EOI -> ICS */
340     ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
341     trace_xics_icp_eoi(server, xirr, ss->xirr);
342     irq = xirr & XISR_MASK;
343     QLIST_FOREACH(ics, &xics->ics, list) {
344         if (ics_valid_irq(ics, irq)) {
345             ics_eoi(ics, irq);
346         }
347     }
348     if (!XISR(ss)) {
349         icp_resend(xics, server);
350     }
351 }
352 
353 static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
354 {
355     XICSState *xics = ics->xics;
356     ICPState *ss = xics->ss + server;
357 
358     trace_xics_icp_irq(server, nr, priority);
359 
360     if ((priority >= CPPR(ss))
361         || (XISR(ss) && (ss->pending_priority <= priority))) {
362         ics_reject(ics, nr);
363     } else {
364         if (XISR(ss) && ss->xirr_owner) {
365             ics_reject(ss->xirr_owner, XISR(ss));
366             ss->xirr_owner = NULL;
367         }
368         ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
369         ss->xirr_owner = ics;
370         ss->pending_priority = priority;
371         trace_xics_icp_raise(ss->xirr, ss->pending_priority);
372         qemu_irq_raise(ss->output);
373     }
374 }
375 
376 static void icp_dispatch_pre_save(void *opaque)
377 {
378     ICPState *ss = opaque;
379     ICPStateClass *info = ICP_GET_CLASS(ss);
380 
381     if (info->pre_save) {
382         info->pre_save(ss);
383     }
384 }
385 
386 static int icp_dispatch_post_load(void *opaque, int version_id)
387 {
388     ICPState *ss = opaque;
389     ICPStateClass *info = ICP_GET_CLASS(ss);
390 
391     if (info->post_load) {
392         return info->post_load(ss, version_id);
393     }
394 
395     return 0;
396 }
397 
398 static const VMStateDescription vmstate_icp_server = {
399     .name = "icp/server",
400     .version_id = 1,
401     .minimum_version_id = 1,
402     .pre_save = icp_dispatch_pre_save,
403     .post_load = icp_dispatch_post_load,
404     .fields = (VMStateField[]) {
405         /* Sanity check */
406         VMSTATE_UINT32(xirr, ICPState),
407         VMSTATE_UINT8(pending_priority, ICPState),
408         VMSTATE_UINT8(mfrr, ICPState),
409         VMSTATE_END_OF_LIST()
410     },
411 };
412 
413 static void icp_reset(DeviceState *dev)
414 {
415     ICPState *icp = ICP(dev);
416 
417     icp->xirr = 0;
418     icp->pending_priority = 0xff;
419     icp->mfrr = 0xff;
420 
421     /* Make all outputs are deasserted */
422     qemu_set_irq(icp->output, 0);
423 }
424 
425 static void icp_class_init(ObjectClass *klass, void *data)
426 {
427     DeviceClass *dc = DEVICE_CLASS(klass);
428 
429     dc->reset = icp_reset;
430     dc->vmsd = &vmstate_icp_server;
431 }
432 
433 static const TypeInfo icp_info = {
434     .name = TYPE_ICP,
435     .parent = TYPE_DEVICE,
436     .instance_size = sizeof(ICPState),
437     .class_init = icp_class_init,
438     .class_size = sizeof(ICPStateClass),
439 };
440 
441 /*
442  * ICS: Source layer
443  */
444 static void ics_simple_resend_msi(ICSState *ics, int srcno)
445 {
446     ICSIRQState *irq = ics->irqs + srcno;
447 
448     /* FIXME: filter by server#? */
449     if (irq->status & XICS_STATUS_REJECTED) {
450         irq->status &= ~XICS_STATUS_REJECTED;
451         if (irq->priority != 0xff) {
452             icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
453         }
454     }
455 }
456 
457 static void ics_simple_resend_lsi(ICSState *ics, int srcno)
458 {
459     ICSIRQState *irq = ics->irqs + srcno;
460 
461     if ((irq->priority != 0xff)
462         && (irq->status & XICS_STATUS_ASSERTED)
463         && !(irq->status & XICS_STATUS_SENT)) {
464         irq->status |= XICS_STATUS_SENT;
465         icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
466     }
467 }
468 
469 static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
470 {
471     ICSIRQState *irq = ics->irqs + srcno;
472 
473     trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
474 
475     if (val) {
476         if (irq->priority == 0xff) {
477             irq->status |= XICS_STATUS_MASKED_PENDING;
478             trace_xics_masked_pending();
479         } else  {
480             icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
481         }
482     }
483 }
484 
485 static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
486 {
487     ICSIRQState *irq = ics->irqs + srcno;
488 
489     trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
490     if (val) {
491         irq->status |= XICS_STATUS_ASSERTED;
492     } else {
493         irq->status &= ~XICS_STATUS_ASSERTED;
494     }
495     ics_simple_resend_lsi(ics, srcno);
496 }
497 
498 static void ics_simple_set_irq(void *opaque, int srcno, int val)
499 {
500     ICSState *ics = (ICSState *)opaque;
501 
502     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
503         ics_simple_set_irq_lsi(ics, srcno, val);
504     } else {
505         ics_simple_set_irq_msi(ics, srcno, val);
506     }
507 }
508 
509 static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
510 {
511     ICSIRQState *irq = ics->irqs + srcno;
512 
513     if (!(irq->status & XICS_STATUS_MASKED_PENDING)
514         || (irq->priority == 0xff)) {
515         return;
516     }
517 
518     irq->status &= ~XICS_STATUS_MASKED_PENDING;
519     icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
520 }
521 
522 static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
523 {
524     ics_simple_resend_lsi(ics, srcno);
525 }
526 
527 void ics_simple_write_xive(ICSState *ics, int srcno, int server,
528                            uint8_t priority, uint8_t saved_priority)
529 {
530     ICSIRQState *irq = ics->irqs + srcno;
531 
532     irq->server = server;
533     irq->priority = priority;
534     irq->saved_priority = saved_priority;
535 
536     trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
537                                      priority);
538 
539     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
540         ics_simple_write_xive_lsi(ics, srcno);
541     } else {
542         ics_simple_write_xive_msi(ics, srcno);
543     }
544 }
545 
546 static void ics_simple_reject(ICSState *ics, uint32_t nr)
547 {
548     ICSIRQState *irq = ics->irqs + nr - ics->offset;
549 
550     trace_xics_ics_simple_reject(nr, nr - ics->offset);
551     if (irq->flags & XICS_FLAGS_IRQ_MSI) {
552         irq->status |= XICS_STATUS_REJECTED;
553     } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
554         irq->status &= ~XICS_STATUS_SENT;
555     }
556 }
557 
558 static void ics_simple_resend(ICSState *ics)
559 {
560     int i;
561 
562     for (i = 0; i < ics->nr_irqs; i++) {
563         /* FIXME: filter by server#? */
564         if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
565             ics_simple_resend_lsi(ics, i);
566         } else {
567             ics_simple_resend_msi(ics, i);
568         }
569     }
570 }
571 
572 static void ics_simple_eoi(ICSState *ics, uint32_t nr)
573 {
574     int srcno = nr - ics->offset;
575     ICSIRQState *irq = ics->irqs + srcno;
576 
577     trace_xics_ics_simple_eoi(nr);
578 
579     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
580         irq->status &= ~XICS_STATUS_SENT;
581     }
582 }
583 
584 static void ics_simple_reset(DeviceState *dev)
585 {
586     ICSState *ics = ICS_SIMPLE(dev);
587     int i;
588     uint8_t flags[ics->nr_irqs];
589 
590     for (i = 0; i < ics->nr_irqs; i++) {
591         flags[i] = ics->irqs[i].flags;
592     }
593 
594     memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
595 
596     for (i = 0; i < ics->nr_irqs; i++) {
597         ics->irqs[i].priority = 0xff;
598         ics->irqs[i].saved_priority = 0xff;
599         ics->irqs[i].flags = flags[i];
600     }
601 }
602 
603 static int ics_simple_post_load(ICSState *ics, int version_id)
604 {
605     int i;
606 
607     for (i = 0; i < ics->xics->nr_servers; i++) {
608         icp_resend(ics->xics, i);
609     }
610 
611     return 0;
612 }
613 
614 static void ics_simple_dispatch_pre_save(void *opaque)
615 {
616     ICSState *ics = opaque;
617     ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
618 
619     if (info->pre_save) {
620         info->pre_save(ics);
621     }
622 }
623 
624 static int ics_simple_dispatch_post_load(void *opaque, int version_id)
625 {
626     ICSState *ics = opaque;
627     ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
628 
629     if (info->post_load) {
630         return info->post_load(ics, version_id);
631     }
632 
633     return 0;
634 }
635 
636 static const VMStateDescription vmstate_ics_simple_irq = {
637     .name = "ics/irq",
638     .version_id = 2,
639     .minimum_version_id = 1,
640     .fields = (VMStateField[]) {
641         VMSTATE_UINT32(server, ICSIRQState),
642         VMSTATE_UINT8(priority, ICSIRQState),
643         VMSTATE_UINT8(saved_priority, ICSIRQState),
644         VMSTATE_UINT8(status, ICSIRQState),
645         VMSTATE_UINT8(flags, ICSIRQState),
646         VMSTATE_END_OF_LIST()
647     },
648 };
649 
650 static const VMStateDescription vmstate_ics_simple = {
651     .name = "ics",
652     .version_id = 1,
653     .minimum_version_id = 1,
654     .pre_save = ics_simple_dispatch_pre_save,
655     .post_load = ics_simple_dispatch_post_load,
656     .fields = (VMStateField[]) {
657         /* Sanity check */
658         VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
659 
660         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
661                                              vmstate_ics_simple_irq,
662                                              ICSIRQState),
663         VMSTATE_END_OF_LIST()
664     },
665 };
666 
667 static void ics_simple_initfn(Object *obj)
668 {
669     ICSState *ics = ICS_SIMPLE(obj);
670 
671     ics->offset = XICS_IRQ_BASE;
672 }
673 
674 static void ics_simple_realize(DeviceState *dev, Error **errp)
675 {
676     ICSState *ics = ICS_SIMPLE(dev);
677 
678     if (!ics->nr_irqs) {
679         error_setg(errp, "Number of interrupts needs to be greater 0");
680         return;
681     }
682     ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
683     ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
684 }
685 
686 static void ics_simple_class_init(ObjectClass *klass, void *data)
687 {
688     DeviceClass *dc = DEVICE_CLASS(klass);
689     ICSStateClass *isc = ICS_BASE_CLASS(klass);
690 
691     dc->realize = ics_simple_realize;
692     dc->vmsd = &vmstate_ics_simple;
693     dc->reset = ics_simple_reset;
694     isc->post_load = ics_simple_post_load;
695     isc->reject = ics_simple_reject;
696     isc->resend = ics_simple_resend;
697     isc->eoi = ics_simple_eoi;
698 }
699 
700 static const TypeInfo ics_simple_info = {
701     .name = TYPE_ICS_SIMPLE,
702     .parent = TYPE_ICS_BASE,
703     .instance_size = sizeof(ICSState),
704     .class_init = ics_simple_class_init,
705     .class_size = sizeof(ICSStateClass),
706     .instance_init = ics_simple_initfn,
707 };
708 
709 static const TypeInfo ics_base_info = {
710     .name = TYPE_ICS_BASE,
711     .parent = TYPE_DEVICE,
712     .abstract = true,
713     .instance_size = sizeof(ICSState),
714     .class_size = sizeof(ICSStateClass),
715 };
716 
717 /*
718  * Exported functions
719  */
720 ICSState *xics_find_source(XICSState *xics, int irq)
721 {
722     ICSState *ics;
723 
724     QLIST_FOREACH(ics, &xics->ics, list) {
725         if (ics_valid_irq(ics, irq)) {
726             return ics;
727         }
728     }
729     return NULL;
730 }
731 
732 qemu_irq xics_get_qirq(XICSState *xics, int irq)
733 {
734     ICSState *ics = xics_find_source(xics, irq);
735 
736     if (ics) {
737         return ics->qirqs[irq - ics->offset];
738     }
739 
740     return NULL;
741 }
742 
743 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
744 {
745     assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));
746 
747     ics->irqs[srcno].flags |=
748         lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
749 }
750 
751 static void xics_register_types(void)
752 {
753     type_register_static(&xics_common_info);
754     type_register_static(&ics_simple_info);
755     type_register_static(&ics_base_info);
756     type_register_static(&icp_info);
757 }
758 
759 type_init(xics_register_types)
760