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