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