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