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