xref: /openbmc/qemu/hw/intc/xics.c (revision 35a6ed4f)
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 void xics_set_nr_servers(XICSState *xics, uint32_t nr_servers,
187                          const char *typename, Error **errp)
188 {
189     int i;
190 
191     xics->nr_servers = nr_servers;
192 
193     xics->ss = g_malloc0(xics->nr_servers * sizeof(ICPState));
194     for (i = 0; i < xics->nr_servers; i++) {
195         char name[32];
196         ICPState *icp = &xics->ss[i];
197 
198         object_initialize(icp, sizeof(*icp), typename);
199         snprintf(name, sizeof(name), "icp[%d]", i);
200         object_property_add_child(OBJECT(xics), name, OBJECT(icp), errp);
201         icp->xics = xics;
202     }
203 }
204 
205 static void xics_prop_get_nr_servers(Object *obj, Visitor *v,
206                                      const char *name, void *opaque,
207                                      Error **errp)
208 {
209     XICSState *xics = XICS_COMMON(obj);
210     int64_t value = xics->nr_servers;
211 
212     visit_type_int(v, name, &value, errp);
213 }
214 
215 static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
216                                      const char *name, void *opaque,
217                                      Error **errp)
218 {
219     XICSState *xics = XICS_COMMON(obj);
220     XICSStateClass *xsc = XICS_COMMON_GET_CLASS(xics);
221     Error *error = NULL;
222     int64_t value;
223 
224     visit_type_int(v, name, &value, &error);
225     if (error) {
226         error_propagate(errp, error);
227         return;
228     }
229     if (xics->nr_servers) {
230         error_setg(errp, "Number of servers is already set to %u",
231                    xics->nr_servers);
232         return;
233     }
234 
235     assert(xsc->set_nr_servers);
236     xsc->set_nr_servers(xics, value, errp);
237 }
238 
239 static void xics_common_initfn(Object *obj)
240 {
241     XICSState *xics = XICS_COMMON(obj);
242 
243     QLIST_INIT(&xics->ics);
244     object_property_add(obj, "nr_irqs", "int",
245                         xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
246                         NULL, NULL, NULL);
247     object_property_add(obj, "nr_servers", "int",
248                         xics_prop_get_nr_servers, xics_prop_set_nr_servers,
249                         NULL, NULL, NULL);
250 }
251 
252 static void xics_common_class_init(ObjectClass *oc, void *data)
253 {
254     DeviceClass *dc = DEVICE_CLASS(oc);
255     InterruptStatsProviderClass *ic = INTERRUPT_STATS_PROVIDER_CLASS(oc);
256 
257     dc->reset = xics_common_reset;
258     ic->print_info = xics_common_pic_print_info;
259 }
260 
261 static const TypeInfo xics_common_info = {
262     .name          = TYPE_XICS_COMMON,
263     .parent        = TYPE_SYS_BUS_DEVICE,
264     .instance_size = sizeof(XICSState),
265     .class_size    = sizeof(XICSStateClass),
266     .instance_init = xics_common_initfn,
267     .class_init    = xics_common_class_init,
268     .interfaces = (InterfaceInfo[]) {
269         { TYPE_INTERRUPT_STATS_PROVIDER },
270         { }
271     },
272 };
273 
274 /*
275  * ICP: Presentation layer
276  */
277 
278 #define XISR_MASK  0x00ffffff
279 #define CPPR_MASK  0xff000000
280 
281 #define XISR(ss)   (((ss)->xirr) & XISR_MASK)
282 #define CPPR(ss)   (((ss)->xirr) >> 24)
283 
284 static void ics_reject(ICSState *ics, uint32_t nr)
285 {
286     ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
287 
288     if (k->reject) {
289         k->reject(ics, nr);
290     }
291 }
292 
293 static void ics_resend(ICSState *ics)
294 {
295     ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
296 
297     if (k->resend) {
298         k->resend(ics);
299     }
300 }
301 
302 static void ics_eoi(ICSState *ics, int nr)
303 {
304     ICSStateClass *k = ICS_BASE_GET_CLASS(ics);
305 
306     if (k->eoi) {
307         k->eoi(ics, nr);
308     }
309 }
310 
311 static void icp_check_ipi(ICPState *ss)
312 {
313     if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
314         return;
315     }
316 
317     trace_xics_icp_check_ipi(ss->cs->cpu_index, ss->mfrr);
318 
319     if (XISR(ss) && ss->xirr_owner) {
320         ics_reject(ss->xirr_owner, XISR(ss));
321     }
322 
323     ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
324     ss->pending_priority = ss->mfrr;
325     ss->xirr_owner = NULL;
326     qemu_irq_raise(ss->output);
327 }
328 
329 static void icp_resend(ICPState *ss)
330 {
331     ICSState *ics;
332 
333     if (ss->mfrr < CPPR(ss)) {
334         icp_check_ipi(ss);
335     }
336     QLIST_FOREACH(ics, &ss->xics->ics, list) {
337         ics_resend(ics);
338     }
339 }
340 
341 void icp_set_cppr(ICPState *ss, uint8_t cppr)
342 {
343     uint8_t old_cppr;
344     uint32_t old_xisr;
345 
346     old_cppr = CPPR(ss);
347     ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
348 
349     if (cppr < old_cppr) {
350         if (XISR(ss) && (cppr <= ss->pending_priority)) {
351             old_xisr = XISR(ss);
352             ss->xirr &= ~XISR_MASK; /* Clear XISR */
353             ss->pending_priority = 0xff;
354             qemu_irq_lower(ss->output);
355             if (ss->xirr_owner) {
356                 ics_reject(ss->xirr_owner, old_xisr);
357                 ss->xirr_owner = NULL;
358             }
359         }
360     } else {
361         if (!XISR(ss)) {
362             icp_resend(ss);
363         }
364     }
365 }
366 
367 void icp_set_mfrr(ICPState *ss, uint8_t mfrr)
368 {
369     ss->mfrr = mfrr;
370     if (mfrr < CPPR(ss)) {
371         icp_check_ipi(ss);
372     }
373 }
374 
375 uint32_t icp_accept(ICPState *ss)
376 {
377     uint32_t xirr = ss->xirr;
378 
379     qemu_irq_lower(ss->output);
380     ss->xirr = ss->pending_priority << 24;
381     ss->pending_priority = 0xff;
382     ss->xirr_owner = NULL;
383 
384     trace_xics_icp_accept(xirr, ss->xirr);
385 
386     return xirr;
387 }
388 
389 uint32_t icp_ipoll(ICPState *ss, uint32_t *mfrr)
390 {
391     if (mfrr) {
392         *mfrr = ss->mfrr;
393     }
394     return ss->xirr;
395 }
396 
397 void icp_eoi(ICPState *ss, uint32_t xirr)
398 {
399     ICSState *ics;
400     uint32_t irq;
401 
402     /* Send EOI -> ICS */
403     ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
404     trace_xics_icp_eoi(ss->cs->cpu_index, xirr, ss->xirr);
405     irq = xirr & XISR_MASK;
406     QLIST_FOREACH(ics, &ss->xics->ics, list) {
407         if (ics_valid_irq(ics, irq)) {
408             ics_eoi(ics, irq);
409         }
410     }
411     if (!XISR(ss)) {
412         icp_resend(ss);
413     }
414 }
415 
416 static void icp_irq(ICSState *ics, int server, int nr, uint8_t priority)
417 {
418     XICSState *xics = ics->xics;
419     ICPState *ss = xics->ss + server;
420 
421     trace_xics_icp_irq(server, nr, priority);
422 
423     if ((priority >= CPPR(ss))
424         || (XISR(ss) && (ss->pending_priority <= priority))) {
425         ics_reject(ics, nr);
426     } else {
427         if (XISR(ss) && ss->xirr_owner) {
428             ics_reject(ss->xirr_owner, XISR(ss));
429             ss->xirr_owner = NULL;
430         }
431         ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
432         ss->xirr_owner = ics;
433         ss->pending_priority = priority;
434         trace_xics_icp_raise(ss->xirr, ss->pending_priority);
435         qemu_irq_raise(ss->output);
436     }
437 }
438 
439 static void icp_dispatch_pre_save(void *opaque)
440 {
441     ICPState *ss = opaque;
442     ICPStateClass *info = ICP_GET_CLASS(ss);
443 
444     if (info->pre_save) {
445         info->pre_save(ss);
446     }
447 }
448 
449 static int icp_dispatch_post_load(void *opaque, int version_id)
450 {
451     ICPState *ss = opaque;
452     ICPStateClass *info = ICP_GET_CLASS(ss);
453 
454     if (info->post_load) {
455         return info->post_load(ss, version_id);
456     }
457 
458     return 0;
459 }
460 
461 static const VMStateDescription vmstate_icp_server = {
462     .name = "icp/server",
463     .version_id = 1,
464     .minimum_version_id = 1,
465     .pre_save = icp_dispatch_pre_save,
466     .post_load = icp_dispatch_post_load,
467     .fields = (VMStateField[]) {
468         /* Sanity check */
469         VMSTATE_UINT32(xirr, ICPState),
470         VMSTATE_UINT8(pending_priority, ICPState),
471         VMSTATE_UINT8(mfrr, ICPState),
472         VMSTATE_END_OF_LIST()
473     },
474 };
475 
476 static void icp_reset(DeviceState *dev)
477 {
478     ICPState *icp = ICP(dev);
479 
480     icp->xirr = 0;
481     icp->pending_priority = 0xff;
482     icp->mfrr = 0xff;
483 
484     /* Make all outputs are deasserted */
485     qemu_set_irq(icp->output, 0);
486 }
487 
488 static void icp_class_init(ObjectClass *klass, void *data)
489 {
490     DeviceClass *dc = DEVICE_CLASS(klass);
491 
492     dc->reset = icp_reset;
493     dc->vmsd = &vmstate_icp_server;
494 }
495 
496 static const TypeInfo icp_info = {
497     .name = TYPE_ICP,
498     .parent = TYPE_DEVICE,
499     .instance_size = sizeof(ICPState),
500     .class_init = icp_class_init,
501     .class_size = sizeof(ICPStateClass),
502 };
503 
504 /*
505  * ICS: Source layer
506  */
507 static void ics_simple_resend_msi(ICSState *ics, int srcno)
508 {
509     ICSIRQState *irq = ics->irqs + srcno;
510 
511     /* FIXME: filter by server#? */
512     if (irq->status & XICS_STATUS_REJECTED) {
513         irq->status &= ~XICS_STATUS_REJECTED;
514         if (irq->priority != 0xff) {
515             icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
516         }
517     }
518 }
519 
520 static void ics_simple_resend_lsi(ICSState *ics, int srcno)
521 {
522     ICSIRQState *irq = ics->irqs + srcno;
523 
524     if ((irq->priority != 0xff)
525         && (irq->status & XICS_STATUS_ASSERTED)
526         && !(irq->status & XICS_STATUS_SENT)) {
527         irq->status |= XICS_STATUS_SENT;
528         icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
529     }
530 }
531 
532 static void ics_simple_set_irq_msi(ICSState *ics, int srcno, int val)
533 {
534     ICSIRQState *irq = ics->irqs + srcno;
535 
536     trace_xics_ics_simple_set_irq_msi(srcno, srcno + ics->offset);
537 
538     if (val) {
539         if (irq->priority == 0xff) {
540             irq->status |= XICS_STATUS_MASKED_PENDING;
541             trace_xics_masked_pending();
542         } else  {
543             icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
544         }
545     }
546 }
547 
548 static void ics_simple_set_irq_lsi(ICSState *ics, int srcno, int val)
549 {
550     ICSIRQState *irq = ics->irqs + srcno;
551 
552     trace_xics_ics_simple_set_irq_lsi(srcno, srcno + ics->offset);
553     if (val) {
554         irq->status |= XICS_STATUS_ASSERTED;
555     } else {
556         irq->status &= ~XICS_STATUS_ASSERTED;
557     }
558     ics_simple_resend_lsi(ics, srcno);
559 }
560 
561 static void ics_simple_set_irq(void *opaque, int srcno, int val)
562 {
563     ICSState *ics = (ICSState *)opaque;
564 
565     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
566         ics_simple_set_irq_lsi(ics, srcno, val);
567     } else {
568         ics_simple_set_irq_msi(ics, srcno, val);
569     }
570 }
571 
572 static void ics_simple_write_xive_msi(ICSState *ics, int srcno)
573 {
574     ICSIRQState *irq = ics->irqs + srcno;
575 
576     if (!(irq->status & XICS_STATUS_MASKED_PENDING)
577         || (irq->priority == 0xff)) {
578         return;
579     }
580 
581     irq->status &= ~XICS_STATUS_MASKED_PENDING;
582     icp_irq(ics, irq->server, srcno + ics->offset, irq->priority);
583 }
584 
585 static void ics_simple_write_xive_lsi(ICSState *ics, int srcno)
586 {
587     ics_simple_resend_lsi(ics, srcno);
588 }
589 
590 void ics_simple_write_xive(ICSState *ics, int srcno, int server,
591                            uint8_t priority, uint8_t saved_priority)
592 {
593     ICSIRQState *irq = ics->irqs + srcno;
594 
595     irq->server = server;
596     irq->priority = priority;
597     irq->saved_priority = saved_priority;
598 
599     trace_xics_ics_simple_write_xive(ics->offset + srcno, srcno, server,
600                                      priority);
601 
602     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
603         ics_simple_write_xive_lsi(ics, srcno);
604     } else {
605         ics_simple_write_xive_msi(ics, srcno);
606     }
607 }
608 
609 static void ics_simple_reject(ICSState *ics, uint32_t nr)
610 {
611     ICSIRQState *irq = ics->irqs + nr - ics->offset;
612 
613     trace_xics_ics_simple_reject(nr, nr - ics->offset);
614     if (irq->flags & XICS_FLAGS_IRQ_MSI) {
615         irq->status |= XICS_STATUS_REJECTED;
616     } else if (irq->flags & XICS_FLAGS_IRQ_LSI) {
617         irq->status &= ~XICS_STATUS_SENT;
618     }
619 }
620 
621 static void ics_simple_resend(ICSState *ics)
622 {
623     int i;
624 
625     for (i = 0; i < ics->nr_irqs; i++) {
626         /* FIXME: filter by server#? */
627         if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
628             ics_simple_resend_lsi(ics, i);
629         } else {
630             ics_simple_resend_msi(ics, i);
631         }
632     }
633 }
634 
635 static void ics_simple_eoi(ICSState *ics, uint32_t nr)
636 {
637     int srcno = nr - ics->offset;
638     ICSIRQState *irq = ics->irqs + srcno;
639 
640     trace_xics_ics_simple_eoi(nr);
641 
642     if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
643         irq->status &= ~XICS_STATUS_SENT;
644     }
645 }
646 
647 static void ics_simple_reset(DeviceState *dev)
648 {
649     ICSState *ics = ICS_SIMPLE(dev);
650     int i;
651     uint8_t flags[ics->nr_irqs];
652 
653     for (i = 0; i < ics->nr_irqs; i++) {
654         flags[i] = ics->irqs[i].flags;
655     }
656 
657     memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
658 
659     for (i = 0; i < ics->nr_irqs; i++) {
660         ics->irqs[i].priority = 0xff;
661         ics->irqs[i].saved_priority = 0xff;
662         ics->irqs[i].flags = flags[i];
663     }
664 }
665 
666 static int ics_simple_post_load(ICSState *ics, int version_id)
667 {
668     int i;
669 
670     for (i = 0; i < ics->xics->nr_servers; i++) {
671         icp_resend(&ics->xics->ss[i]);
672     }
673 
674     return 0;
675 }
676 
677 static void ics_simple_dispatch_pre_save(void *opaque)
678 {
679     ICSState *ics = opaque;
680     ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
681 
682     if (info->pre_save) {
683         info->pre_save(ics);
684     }
685 }
686 
687 static int ics_simple_dispatch_post_load(void *opaque, int version_id)
688 {
689     ICSState *ics = opaque;
690     ICSStateClass *info = ICS_BASE_GET_CLASS(ics);
691 
692     if (info->post_load) {
693         return info->post_load(ics, version_id);
694     }
695 
696     return 0;
697 }
698 
699 static const VMStateDescription vmstate_ics_simple_irq = {
700     .name = "ics/irq",
701     .version_id = 2,
702     .minimum_version_id = 1,
703     .fields = (VMStateField[]) {
704         VMSTATE_UINT32(server, ICSIRQState),
705         VMSTATE_UINT8(priority, ICSIRQState),
706         VMSTATE_UINT8(saved_priority, ICSIRQState),
707         VMSTATE_UINT8(status, ICSIRQState),
708         VMSTATE_UINT8(flags, ICSIRQState),
709         VMSTATE_END_OF_LIST()
710     },
711 };
712 
713 static const VMStateDescription vmstate_ics_simple = {
714     .name = "ics",
715     .version_id = 1,
716     .minimum_version_id = 1,
717     .pre_save = ics_simple_dispatch_pre_save,
718     .post_load = ics_simple_dispatch_post_load,
719     .fields = (VMStateField[]) {
720         /* Sanity check */
721         VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
722 
723         VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
724                                              vmstate_ics_simple_irq,
725                                              ICSIRQState),
726         VMSTATE_END_OF_LIST()
727     },
728 };
729 
730 static void ics_simple_initfn(Object *obj)
731 {
732     ICSState *ics = ICS_SIMPLE(obj);
733 
734     ics->offset = XICS_IRQ_BASE;
735 }
736 
737 static void ics_simple_realize(DeviceState *dev, Error **errp)
738 {
739     ICSState *ics = ICS_SIMPLE(dev);
740 
741     if (!ics->nr_irqs) {
742         error_setg(errp, "Number of interrupts needs to be greater 0");
743         return;
744     }
745     ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
746     ics->qirqs = qemu_allocate_irqs(ics_simple_set_irq, ics, ics->nr_irqs);
747 }
748 
749 static void ics_simple_class_init(ObjectClass *klass, void *data)
750 {
751     DeviceClass *dc = DEVICE_CLASS(klass);
752     ICSStateClass *isc = ICS_BASE_CLASS(klass);
753 
754     dc->realize = ics_simple_realize;
755     dc->vmsd = &vmstate_ics_simple;
756     dc->reset = ics_simple_reset;
757     isc->post_load = ics_simple_post_load;
758     isc->reject = ics_simple_reject;
759     isc->resend = ics_simple_resend;
760     isc->eoi = ics_simple_eoi;
761 }
762 
763 static const TypeInfo ics_simple_info = {
764     .name = TYPE_ICS_SIMPLE,
765     .parent = TYPE_ICS_BASE,
766     .instance_size = sizeof(ICSState),
767     .class_init = ics_simple_class_init,
768     .class_size = sizeof(ICSStateClass),
769     .instance_init = ics_simple_initfn,
770 };
771 
772 static const TypeInfo ics_base_info = {
773     .name = TYPE_ICS_BASE,
774     .parent = TYPE_DEVICE,
775     .abstract = true,
776     .instance_size = sizeof(ICSState),
777     .class_size = sizeof(ICSStateClass),
778 };
779 
780 /*
781  * Exported functions
782  */
783 ICSState *xics_find_source(XICSState *xics, int irq)
784 {
785     ICSState *ics;
786 
787     QLIST_FOREACH(ics, &xics->ics, list) {
788         if (ics_valid_irq(ics, irq)) {
789             return ics;
790         }
791     }
792     return NULL;
793 }
794 
795 qemu_irq xics_get_qirq(XICSState *xics, int irq)
796 {
797     ICSState *ics = xics_find_source(xics, irq);
798 
799     if (ics) {
800         return ics->qirqs[irq - ics->offset];
801     }
802 
803     return NULL;
804 }
805 
806 void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
807 {
808     assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));
809 
810     ics->irqs[srcno].flags |=
811         lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
812 }
813 
814 static void xics_register_types(void)
815 {
816     type_register_static(&xics_common_info);
817     type_register_static(&ics_simple_info);
818     type_register_static(&ics_base_info);
819     type_register_static(&icp_info);
820 }
821 
822 type_init(xics_register_types)
823