2 * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
4 * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
6 * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
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:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
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
28 #include "qemu/osdep.h"
29 #include "qapi/error.h"
30 #include "qemu-common.h"
34 #include "qemu/timer.h"
35 #include "hw/ppc/xics.h"
36 #include "qemu/error-report.h"
37 #include "qapi/visitor.h"
39 int xics_get_cpu_index_by_dt_id(int cpu_dt_id
)
41 PowerPCCPU
*cpu
= ppc_get_vcpu_by_dt_id(cpu_dt_id
);
44 return cpu
->parent_obj
.cpu_index
;
50 void xics_cpu_destroy(XICSState
*xics
, PowerPCCPU
*cpu
)
52 CPUState
*cs
= CPU(cpu
);
53 ICPState
*ss
= &xics
->ss
[cs
->cpu_index
];
55 assert(cs
->cpu_index
< xics
->nr_servers
);
62 void xics_cpu_setup(XICSState
*xics
, PowerPCCPU
*cpu
)
64 CPUState
*cs
= CPU(cpu
);
65 CPUPPCState
*env
= &cpu
->env
;
66 ICPState
*ss
= &xics
->ss
[cs
->cpu_index
];
67 XICSStateClass
*info
= XICS_COMMON_GET_CLASS(xics
);
69 assert(cs
->cpu_index
< xics
->nr_servers
);
73 if (info
->cpu_setup
) {
74 info
->cpu_setup(xics
, cpu
);
77 switch (PPC_INPUT(env
)) {
78 case PPC_FLAGS_INPUT_POWER7
:
79 ss
->output
= env
->irq_inputs
[POWER7_INPUT_INT
];
82 case PPC_FLAGS_INPUT_970
:
83 ss
->output
= env
->irq_inputs
[PPC970_INPUT_INT
];
87 error_report("XICS interrupt controller does not support this CPU "
94 * XICS Common class - parent for emulated XICS and KVM-XICS
96 static void xics_common_reset(DeviceState
*d
)
98 XICSState
*xics
= XICS_COMMON(d
);
101 for (i
= 0; i
< xics
->nr_servers
; i
++) {
102 device_reset(DEVICE(&xics
->ss
[i
]));
105 device_reset(DEVICE(xics
->ics
));
108 static void xics_prop_get_nr_irqs(Object
*obj
, Visitor
*v
, const char *name
,
109 void *opaque
, Error
**errp
)
111 XICSState
*xics
= XICS_COMMON(obj
);
112 int64_t value
= xics
->nr_irqs
;
114 visit_type_int(v
, name
, &value
, errp
);
117 static void xics_prop_set_nr_irqs(Object
*obj
, Visitor
*v
, const char *name
,
118 void *opaque
, Error
**errp
)
120 XICSState
*xics
= XICS_COMMON(obj
);
121 XICSStateClass
*info
= XICS_COMMON_GET_CLASS(xics
);
125 visit_type_int(v
, name
, &value
, &error
);
127 error_propagate(errp
, error
);
131 error_setg(errp
, "Number of interrupts is already set to %u",
136 assert(info
->set_nr_irqs
);
138 info
->set_nr_irqs(xics
, value
, errp
);
141 static void xics_prop_get_nr_servers(Object
*obj
, Visitor
*v
,
142 const char *name
, void *opaque
,
145 XICSState
*xics
= XICS_COMMON(obj
);
146 int64_t value
= xics
->nr_servers
;
148 visit_type_int(v
, name
, &value
, errp
);
151 static void xics_prop_set_nr_servers(Object
*obj
, Visitor
*v
,
152 const char *name
, void *opaque
,
155 XICSState
*xics
= XICS_COMMON(obj
);
156 XICSStateClass
*info
= XICS_COMMON_GET_CLASS(xics
);
160 visit_type_int(v
, name
, &value
, &error
);
162 error_propagate(errp
, error
);
165 if (xics
->nr_servers
) {
166 error_setg(errp
, "Number of servers is already set to %u",
171 assert(info
->set_nr_servers
);
172 info
->set_nr_servers(xics
, value
, errp
);
175 static void xics_common_initfn(Object
*obj
)
177 object_property_add(obj
, "nr_irqs", "int",
178 xics_prop_get_nr_irqs
, xics_prop_set_nr_irqs
,
180 object_property_add(obj
, "nr_servers", "int",
181 xics_prop_get_nr_servers
, xics_prop_set_nr_servers
,
185 static void xics_common_class_init(ObjectClass
*oc
, void *data
)
187 DeviceClass
*dc
= DEVICE_CLASS(oc
);
189 dc
->reset
= xics_common_reset
;
192 static const TypeInfo xics_common_info
= {
193 .name
= TYPE_XICS_COMMON
,
194 .parent
= TYPE_SYS_BUS_DEVICE
,
195 .instance_size
= sizeof(XICSState
),
196 .class_size
= sizeof(XICSStateClass
),
197 .instance_init
= xics_common_initfn
,
198 .class_init
= xics_common_class_init
,
202 * ICP: Presentation layer
205 #define XISR_MASK 0x00ffffff
206 #define CPPR_MASK 0xff000000
208 #define XISR(ss) (((ss)->xirr) & XISR_MASK)
209 #define CPPR(ss) (((ss)->xirr) >> 24)
211 static void ics_reject(ICSState
*ics
, int nr
);
212 static void ics_resend(ICSState
*ics
);
213 static void ics_eoi(ICSState
*ics
, int nr
);
215 static void icp_check_ipi(XICSState
*xics
, int server
)
217 ICPState
*ss
= xics
->ss
+ server
;
219 if (XISR(ss
) && (ss
->pending_priority
<= ss
->mfrr
)) {
223 trace_xics_icp_check_ipi(server
, ss
->mfrr
);
226 ics_reject(xics
->ics
, XISR(ss
));
229 ss
->xirr
= (ss
->xirr
& ~XISR_MASK
) | XICS_IPI
;
230 ss
->pending_priority
= ss
->mfrr
;
231 qemu_irq_raise(ss
->output
);
234 static void icp_resend(XICSState
*xics
, int server
)
236 ICPState
*ss
= xics
->ss
+ server
;
238 if (ss
->mfrr
< CPPR(ss
)) {
239 icp_check_ipi(xics
, server
);
241 ics_resend(xics
->ics
);
244 void icp_set_cppr(XICSState
*xics
, int server
, uint8_t cppr
)
246 ICPState
*ss
= xics
->ss
+ server
;
251 ss
->xirr
= (ss
->xirr
& ~CPPR_MASK
) | (cppr
<< 24);
253 if (cppr
< old_cppr
) {
254 if (XISR(ss
) && (cppr
<= ss
->pending_priority
)) {
256 ss
->xirr
&= ~XISR_MASK
; /* Clear XISR */
257 ss
->pending_priority
= 0xff;
258 qemu_irq_lower(ss
->output
);
259 ics_reject(xics
->ics
, old_xisr
);
263 icp_resend(xics
, server
);
268 void icp_set_mfrr(XICSState
*xics
, int server
, uint8_t mfrr
)
270 ICPState
*ss
= xics
->ss
+ server
;
273 if (mfrr
< CPPR(ss
)) {
274 icp_check_ipi(xics
, server
);
278 uint32_t icp_accept(ICPState
*ss
)
280 uint32_t xirr
= ss
->xirr
;
282 qemu_irq_lower(ss
->output
);
283 ss
->xirr
= ss
->pending_priority
<< 24;
284 ss
->pending_priority
= 0xff;
286 trace_xics_icp_accept(xirr
, ss
->xirr
);
291 uint32_t icp_ipoll(ICPState
*ss
, uint32_t *mfrr
)
299 void icp_eoi(XICSState
*xics
, int server
, uint32_t xirr
)
301 ICPState
*ss
= xics
->ss
+ server
;
303 /* Send EOI -> ICS */
304 ss
->xirr
= (ss
->xirr
& ~CPPR_MASK
) | (xirr
& CPPR_MASK
);
305 trace_xics_icp_eoi(server
, xirr
, ss
->xirr
);
306 ics_eoi(xics
->ics
, xirr
& XISR_MASK
);
308 icp_resend(xics
, server
);
312 static void icp_irq(XICSState
*xics
, int server
, int nr
, uint8_t priority
)
314 ICPState
*ss
= xics
->ss
+ server
;
316 trace_xics_icp_irq(server
, nr
, priority
);
318 if ((priority
>= CPPR(ss
))
319 || (XISR(ss
) && (ss
->pending_priority
<= priority
))) {
320 ics_reject(xics
->ics
, nr
);
323 ics_reject(xics
->ics
, XISR(ss
));
325 ss
->xirr
= (ss
->xirr
& ~XISR_MASK
) | (nr
& XISR_MASK
);
326 ss
->pending_priority
= priority
;
327 trace_xics_icp_raise(ss
->xirr
, ss
->pending_priority
);
328 qemu_irq_raise(ss
->output
);
332 static void icp_dispatch_pre_save(void *opaque
)
334 ICPState
*ss
= opaque
;
335 ICPStateClass
*info
= ICP_GET_CLASS(ss
);
337 if (info
->pre_save
) {
342 static int icp_dispatch_post_load(void *opaque
, int version_id
)
344 ICPState
*ss
= opaque
;
345 ICPStateClass
*info
= ICP_GET_CLASS(ss
);
347 if (info
->post_load
) {
348 return info
->post_load(ss
, version_id
);
354 static const VMStateDescription vmstate_icp_server
= {
355 .name
= "icp/server",
357 .minimum_version_id
= 1,
358 .pre_save
= icp_dispatch_pre_save
,
359 .post_load
= icp_dispatch_post_load
,
360 .fields
= (VMStateField
[]) {
362 VMSTATE_UINT32(xirr
, ICPState
),
363 VMSTATE_UINT8(pending_priority
, ICPState
),
364 VMSTATE_UINT8(mfrr
, ICPState
),
365 VMSTATE_END_OF_LIST()
369 static void icp_reset(DeviceState
*dev
)
371 ICPState
*icp
= ICP(dev
);
374 icp
->pending_priority
= 0xff;
377 /* Make all outputs are deasserted */
378 qemu_set_irq(icp
->output
, 0);
381 static void icp_class_init(ObjectClass
*klass
, void *data
)
383 DeviceClass
*dc
= DEVICE_CLASS(klass
);
385 dc
->reset
= icp_reset
;
386 dc
->vmsd
= &vmstate_icp_server
;
389 static const TypeInfo icp_info
= {
391 .parent
= TYPE_DEVICE
,
392 .instance_size
= sizeof(ICPState
),
393 .class_init
= icp_class_init
,
394 .class_size
= sizeof(ICPStateClass
),
400 static void resend_msi(ICSState
*ics
, int srcno
)
402 ICSIRQState
*irq
= ics
->irqs
+ srcno
;
404 /* FIXME: filter by server#? */
405 if (irq
->status
& XICS_STATUS_REJECTED
) {
406 irq
->status
&= ~XICS_STATUS_REJECTED
;
407 if (irq
->priority
!= 0xff) {
408 icp_irq(ics
->xics
, irq
->server
, srcno
+ ics
->offset
,
414 static void resend_lsi(ICSState
*ics
, int srcno
)
416 ICSIRQState
*irq
= ics
->irqs
+ srcno
;
418 if ((irq
->priority
!= 0xff)
419 && (irq
->status
& XICS_STATUS_ASSERTED
)
420 && !(irq
->status
& XICS_STATUS_SENT
)) {
421 irq
->status
|= XICS_STATUS_SENT
;
422 icp_irq(ics
->xics
, irq
->server
, srcno
+ ics
->offset
, irq
->priority
);
426 static void set_irq_msi(ICSState
*ics
, int srcno
, int val
)
428 ICSIRQState
*irq
= ics
->irqs
+ srcno
;
430 trace_xics_set_irq_msi(srcno
, srcno
+ ics
->offset
);
433 if (irq
->priority
== 0xff) {
434 irq
->status
|= XICS_STATUS_MASKED_PENDING
;
435 trace_xics_masked_pending();
437 icp_irq(ics
->xics
, irq
->server
, srcno
+ ics
->offset
, irq
->priority
);
442 static void set_irq_lsi(ICSState
*ics
, int srcno
, int val
)
444 ICSIRQState
*irq
= ics
->irqs
+ srcno
;
446 trace_xics_set_irq_lsi(srcno
, srcno
+ ics
->offset
);
448 irq
->status
|= XICS_STATUS_ASSERTED
;
450 irq
->status
&= ~XICS_STATUS_ASSERTED
;
452 resend_lsi(ics
, srcno
);
455 static void ics_set_irq(void *opaque
, int srcno
, int val
)
457 ICSState
*ics
= (ICSState
*)opaque
;
459 if (ics
->irqs
[srcno
].flags
& XICS_FLAGS_IRQ_LSI
) {
460 set_irq_lsi(ics
, srcno
, val
);
462 set_irq_msi(ics
, srcno
, val
);
466 static void write_xive_msi(ICSState
*ics
, int srcno
)
468 ICSIRQState
*irq
= ics
->irqs
+ srcno
;
470 if (!(irq
->status
& XICS_STATUS_MASKED_PENDING
)
471 || (irq
->priority
== 0xff)) {
475 irq
->status
&= ~XICS_STATUS_MASKED_PENDING
;
476 icp_irq(ics
->xics
, irq
->server
, srcno
+ ics
->offset
, irq
->priority
);
479 static void write_xive_lsi(ICSState
*ics
, int srcno
)
481 resend_lsi(ics
, srcno
);
484 void ics_write_xive(ICSState
*ics
, int nr
, int server
,
485 uint8_t priority
, uint8_t saved_priority
)
487 int srcno
= nr
- ics
->offset
;
488 ICSIRQState
*irq
= ics
->irqs
+ srcno
;
490 irq
->server
= server
;
491 irq
->priority
= priority
;
492 irq
->saved_priority
= saved_priority
;
494 trace_xics_ics_write_xive(nr
, srcno
, server
, priority
);
496 if (ics
->irqs
[srcno
].flags
& XICS_FLAGS_IRQ_LSI
) {
497 write_xive_lsi(ics
, srcno
);
499 write_xive_msi(ics
, srcno
);
503 static void ics_reject(ICSState
*ics
, int nr
)
505 ICSIRQState
*irq
= ics
->irqs
+ nr
- ics
->offset
;
507 trace_xics_ics_reject(nr
, nr
- ics
->offset
);
508 if (irq
->flags
& XICS_FLAGS_IRQ_MSI
) {
509 irq
->status
|= XICS_STATUS_REJECTED
;
510 } else if (irq
->flags
& XICS_FLAGS_IRQ_LSI
) {
511 irq
->status
&= ~XICS_STATUS_SENT
;
515 static void ics_resend(ICSState
*ics
)
519 for (i
= 0; i
< ics
->nr_irqs
; i
++) {
520 /* FIXME: filter by server#? */
521 if (ics
->irqs
[i
].flags
& XICS_FLAGS_IRQ_LSI
) {
529 static void ics_eoi(ICSState
*ics
, int nr
)
531 int srcno
= nr
- ics
->offset
;
532 ICSIRQState
*irq
= ics
->irqs
+ srcno
;
534 trace_xics_ics_eoi(nr
);
536 if (ics
->irqs
[srcno
].flags
& XICS_FLAGS_IRQ_LSI
) {
537 irq
->status
&= ~XICS_STATUS_SENT
;
541 static void ics_reset(DeviceState
*dev
)
543 ICSState
*ics
= ICS(dev
);
545 uint8_t flags
[ics
->nr_irqs
];
547 for (i
= 0; i
< ics
->nr_irqs
; i
++) {
548 flags
[i
] = ics
->irqs
[i
].flags
;
551 memset(ics
->irqs
, 0, sizeof(ICSIRQState
) * ics
->nr_irqs
);
553 for (i
= 0; i
< ics
->nr_irqs
; i
++) {
554 ics
->irqs
[i
].priority
= 0xff;
555 ics
->irqs
[i
].saved_priority
= 0xff;
556 ics
->irqs
[i
].flags
= flags
[i
];
560 static int ics_post_load(ICSState
*ics
, int version_id
)
564 for (i
= 0; i
< ics
->xics
->nr_servers
; i
++) {
565 icp_resend(ics
->xics
, i
);
571 static void ics_dispatch_pre_save(void *opaque
)
573 ICSState
*ics
= opaque
;
574 ICSStateClass
*info
= ICS_GET_CLASS(ics
);
576 if (info
->pre_save
) {
581 static int ics_dispatch_post_load(void *opaque
, int version_id
)
583 ICSState
*ics
= opaque
;
584 ICSStateClass
*info
= ICS_GET_CLASS(ics
);
586 if (info
->post_load
) {
587 return info
->post_load(ics
, version_id
);
593 static const VMStateDescription vmstate_ics_irq
= {
596 .minimum_version_id
= 1,
597 .fields
= (VMStateField
[]) {
598 VMSTATE_UINT32(server
, ICSIRQState
),
599 VMSTATE_UINT8(priority
, ICSIRQState
),
600 VMSTATE_UINT8(saved_priority
, ICSIRQState
),
601 VMSTATE_UINT8(status
, ICSIRQState
),
602 VMSTATE_UINT8(flags
, ICSIRQState
),
603 VMSTATE_END_OF_LIST()
607 static const VMStateDescription vmstate_ics
= {
610 .minimum_version_id
= 1,
611 .pre_save
= ics_dispatch_pre_save
,
612 .post_load
= ics_dispatch_post_load
,
613 .fields
= (VMStateField
[]) {
615 VMSTATE_UINT32_EQUAL(nr_irqs
, ICSState
),
617 VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs
, ICSState
, nr_irqs
,
618 vmstate_ics_irq
, ICSIRQState
),
619 VMSTATE_END_OF_LIST()
623 static void ics_initfn(Object
*obj
)
625 ICSState
*ics
= ICS(obj
);
627 ics
->offset
= XICS_IRQ_BASE
;
630 static void ics_realize(DeviceState
*dev
, Error
**errp
)
632 ICSState
*ics
= ICS(dev
);
635 error_setg(errp
, "Number of interrupts needs to be greater 0");
638 ics
->irqs
= g_malloc0(ics
->nr_irqs
* sizeof(ICSIRQState
));
639 ics
->qirqs
= qemu_allocate_irqs(ics_set_irq
, ics
, ics
->nr_irqs
);
642 static void ics_class_init(ObjectClass
*klass
, void *data
)
644 DeviceClass
*dc
= DEVICE_CLASS(klass
);
645 ICSStateClass
*isc
= ICS_CLASS(klass
);
647 dc
->realize
= ics_realize
;
648 dc
->vmsd
= &vmstate_ics
;
649 dc
->reset
= ics_reset
;
650 isc
->post_load
= ics_post_load
;
653 static const TypeInfo ics_info
= {
655 .parent
= TYPE_DEVICE
,
656 .instance_size
= sizeof(ICSState
),
657 .class_init
= ics_class_init
,
658 .class_size
= sizeof(ICSStateClass
),
659 .instance_init
= ics_initfn
,
665 int xics_find_source(XICSState
*xics
, int irq
)
670 /* FIXME: implement multiple sources */
671 for (src
= 0; src
< sources
; ++src
) {
672 ICSState
*ics
= &xics
->ics
[src
];
673 if (ics_valid_irq(ics
, irq
)) {
681 qemu_irq
xics_get_qirq(XICSState
*xics
, int irq
)
683 int src
= xics_find_source(xics
, irq
);
686 ICSState
*ics
= &xics
->ics
[src
];
687 return ics
->qirqs
[irq
- ics
->offset
];
693 void ics_set_irq_type(ICSState
*ics
, int srcno
, bool lsi
)
695 assert(!(ics
->irqs
[srcno
].flags
& XICS_FLAGS_IRQ_MASK
));
697 ics
->irqs
[srcno
].flags
|=
698 lsi
? XICS_FLAGS_IRQ_LSI
: XICS_FLAGS_IRQ_MSI
;
701 static void xics_register_types(void)
703 type_register_static(&xics_common_info
);
704 type_register_static(&ics_info
);
705 type_register_static(&icp_info
);
708 type_init(xics_register_types
)