xics: Implement H_IPOLL
[qemu/kevin.git] / hw / intc / xics.c
blobeb932762b3f1dec15a027ac4b6aa68bb1a7d38f9
1 /*
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
24 * THE SOFTWARE.
28 #include "hw/hw.h"
29 #include "trace.h"
30 #include "hw/ppc/spapr.h"
31 #include "hw/ppc/xics.h"
32 #include "qemu/error-report.h"
33 #include "qapi/visitor.h"
35 void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu)
37 CPUState *cs = CPU(cpu);
38 CPUPPCState *env = &cpu->env;
39 ICPState *ss = &icp->ss[cs->cpu_index];
40 XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
42 assert(cs->cpu_index < icp->nr_servers);
44 if (info->cpu_setup) {
45 info->cpu_setup(icp, cpu);
48 switch (PPC_INPUT(env)) {
49 case PPC_FLAGS_INPUT_POWER7:
50 ss->output = env->irq_inputs[POWER7_INPUT_INT];
51 break;
53 case PPC_FLAGS_INPUT_970:
54 ss->output = env->irq_inputs[PPC970_INPUT_INT];
55 break;
57 default:
58 error_report("XICS interrupt controller does not support this CPU "
59 "bus model");
60 abort();
65 * XICS Common class - parent for emulated XICS and KVM-XICS
67 static void xics_common_reset(DeviceState *d)
69 XICSState *icp = XICS_COMMON(d);
70 int i;
72 for (i = 0; i < icp->nr_servers; i++) {
73 device_reset(DEVICE(&icp->ss[i]));
76 device_reset(DEVICE(icp->ics));
79 static void xics_prop_get_nr_irqs(Object *obj, Visitor *v,
80 void *opaque, const char *name, Error **errp)
82 XICSState *icp = XICS_COMMON(obj);
83 int64_t value = icp->nr_irqs;
85 visit_type_int(v, &value, name, errp);
88 static void xics_prop_set_nr_irqs(Object *obj, Visitor *v,
89 void *opaque, const char *name, Error **errp)
91 XICSState *icp = XICS_COMMON(obj);
92 XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
93 Error *error = NULL;
94 int64_t value;
96 visit_type_int(v, &value, name, &error);
97 if (error) {
98 error_propagate(errp, error);
99 return;
101 if (icp->nr_irqs) {
102 error_setg(errp, "Number of interrupts is already set to %u",
103 icp->nr_irqs);
104 return;
107 assert(info->set_nr_irqs);
108 assert(icp->ics);
109 info->set_nr_irqs(icp, value, errp);
112 static void xics_prop_get_nr_servers(Object *obj, Visitor *v,
113 void *opaque, const char *name,
114 Error **errp)
116 XICSState *icp = XICS_COMMON(obj);
117 int64_t value = icp->nr_servers;
119 visit_type_int(v, &value, name, errp);
122 static void xics_prop_set_nr_servers(Object *obj, Visitor *v,
123 void *opaque, const char *name,
124 Error **errp)
126 XICSState *icp = XICS_COMMON(obj);
127 XICSStateClass *info = XICS_COMMON_GET_CLASS(icp);
128 Error *error = NULL;
129 int64_t value;
131 visit_type_int(v, &value, name, &error);
132 if (error) {
133 error_propagate(errp, error);
134 return;
136 if (icp->nr_servers) {
137 error_setg(errp, "Number of servers is already set to %u",
138 icp->nr_servers);
139 return;
142 assert(info->set_nr_servers);
143 info->set_nr_servers(icp, value, errp);
146 static void xics_common_initfn(Object *obj)
148 object_property_add(obj, "nr_irqs", "int",
149 xics_prop_get_nr_irqs, xics_prop_set_nr_irqs,
150 NULL, NULL, NULL);
151 object_property_add(obj, "nr_servers", "int",
152 xics_prop_get_nr_servers, xics_prop_set_nr_servers,
153 NULL, NULL, NULL);
156 static void xics_common_class_init(ObjectClass *oc, void *data)
158 DeviceClass *dc = DEVICE_CLASS(oc);
160 dc->reset = xics_common_reset;
163 static const TypeInfo xics_common_info = {
164 .name = TYPE_XICS_COMMON,
165 .parent = TYPE_SYS_BUS_DEVICE,
166 .instance_size = sizeof(XICSState),
167 .class_size = sizeof(XICSStateClass),
168 .instance_init = xics_common_initfn,
169 .class_init = xics_common_class_init,
173 * ICP: Presentation layer
176 #define XISR_MASK 0x00ffffff
177 #define CPPR_MASK 0xff000000
179 #define XISR(ss) (((ss)->xirr) & XISR_MASK)
180 #define CPPR(ss) (((ss)->xirr) >> 24)
182 static void ics_reject(ICSState *ics, int nr);
183 static void ics_resend(ICSState *ics);
184 static void ics_eoi(ICSState *ics, int nr);
186 static void icp_check_ipi(XICSState *icp, int server)
188 ICPState *ss = icp->ss + server;
190 if (XISR(ss) && (ss->pending_priority <= ss->mfrr)) {
191 return;
194 trace_xics_icp_check_ipi(server, ss->mfrr);
196 if (XISR(ss)) {
197 ics_reject(icp->ics, XISR(ss));
200 ss->xirr = (ss->xirr & ~XISR_MASK) | XICS_IPI;
201 ss->pending_priority = ss->mfrr;
202 qemu_irq_raise(ss->output);
205 static void icp_resend(XICSState *icp, int server)
207 ICPState *ss = icp->ss + server;
209 if (ss->mfrr < CPPR(ss)) {
210 icp_check_ipi(icp, server);
212 ics_resend(icp->ics);
215 static void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
217 ICPState *ss = icp->ss + server;
218 uint8_t old_cppr;
219 uint32_t old_xisr;
221 old_cppr = CPPR(ss);
222 ss->xirr = (ss->xirr & ~CPPR_MASK) | (cppr << 24);
224 if (cppr < old_cppr) {
225 if (XISR(ss) && (cppr <= ss->pending_priority)) {
226 old_xisr = XISR(ss);
227 ss->xirr &= ~XISR_MASK; /* Clear XISR */
228 ss->pending_priority = 0xff;
229 qemu_irq_lower(ss->output);
230 ics_reject(icp->ics, old_xisr);
232 } else {
233 if (!XISR(ss)) {
234 icp_resend(icp, server);
239 static void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
241 ICPState *ss = icp->ss + server;
243 ss->mfrr = mfrr;
244 if (mfrr < CPPR(ss)) {
245 icp_check_ipi(icp, server);
249 static uint32_t icp_accept(ICPState *ss)
251 uint32_t xirr = ss->xirr;
253 qemu_irq_lower(ss->output);
254 ss->xirr = ss->pending_priority << 24;
255 ss->pending_priority = 0xff;
257 trace_xics_icp_accept(xirr, ss->xirr);
259 return xirr;
262 static void icp_eoi(XICSState *icp, int server, uint32_t xirr)
264 ICPState *ss = icp->ss + server;
266 /* Send EOI -> ICS */
267 ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
268 trace_xics_icp_eoi(server, xirr, ss->xirr);
269 ics_eoi(icp->ics, xirr & XISR_MASK);
270 if (!XISR(ss)) {
271 icp_resend(icp, server);
275 static void icp_irq(XICSState *icp, int server, int nr, uint8_t priority)
277 ICPState *ss = icp->ss + server;
279 trace_xics_icp_irq(server, nr, priority);
281 if ((priority >= CPPR(ss))
282 || (XISR(ss) && (ss->pending_priority <= priority))) {
283 ics_reject(icp->ics, nr);
284 } else {
285 if (XISR(ss)) {
286 ics_reject(icp->ics, XISR(ss));
288 ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
289 ss->pending_priority = priority;
290 trace_xics_icp_raise(ss->xirr, ss->pending_priority);
291 qemu_irq_raise(ss->output);
295 static void icp_dispatch_pre_save(void *opaque)
297 ICPState *ss = opaque;
298 ICPStateClass *info = ICP_GET_CLASS(ss);
300 if (info->pre_save) {
301 info->pre_save(ss);
305 static int icp_dispatch_post_load(void *opaque, int version_id)
307 ICPState *ss = opaque;
308 ICPStateClass *info = ICP_GET_CLASS(ss);
310 if (info->post_load) {
311 return info->post_load(ss, version_id);
314 return 0;
317 static const VMStateDescription vmstate_icp_server = {
318 .name = "icp/server",
319 .version_id = 1,
320 .minimum_version_id = 1,
321 .minimum_version_id_old = 1,
322 .pre_save = icp_dispatch_pre_save,
323 .post_load = icp_dispatch_post_load,
324 .fields = (VMStateField []) {
325 /* Sanity check */
326 VMSTATE_UINT32(xirr, ICPState),
327 VMSTATE_UINT8(pending_priority, ICPState),
328 VMSTATE_UINT8(mfrr, ICPState),
329 VMSTATE_END_OF_LIST()
333 static void icp_reset(DeviceState *dev)
335 ICPState *icp = ICP(dev);
337 icp->xirr = 0;
338 icp->pending_priority = 0xff;
339 icp->mfrr = 0xff;
341 /* Make all outputs are deasserted */
342 qemu_set_irq(icp->output, 0);
345 static void icp_class_init(ObjectClass *klass, void *data)
347 DeviceClass *dc = DEVICE_CLASS(klass);
349 dc->reset = icp_reset;
350 dc->vmsd = &vmstate_icp_server;
353 static const TypeInfo icp_info = {
354 .name = TYPE_ICP,
355 .parent = TYPE_DEVICE,
356 .instance_size = sizeof(ICPState),
357 .class_init = icp_class_init,
358 .class_size = sizeof(ICPStateClass),
362 * ICS: Source layer
364 static int ics_valid_irq(ICSState *ics, uint32_t nr)
366 return (nr >= ics->offset)
367 && (nr < (ics->offset + ics->nr_irqs));
370 static void resend_msi(ICSState *ics, int srcno)
372 ICSIRQState *irq = ics->irqs + srcno;
374 /* FIXME: filter by server#? */
375 if (irq->status & XICS_STATUS_REJECTED) {
376 irq->status &= ~XICS_STATUS_REJECTED;
377 if (irq->priority != 0xff) {
378 icp_irq(ics->icp, irq->server, srcno + ics->offset,
379 irq->priority);
384 static void resend_lsi(ICSState *ics, int srcno)
386 ICSIRQState *irq = ics->irqs + srcno;
388 if ((irq->priority != 0xff)
389 && (irq->status & XICS_STATUS_ASSERTED)
390 && !(irq->status & XICS_STATUS_SENT)) {
391 irq->status |= XICS_STATUS_SENT;
392 icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
396 static void set_irq_msi(ICSState *ics, int srcno, int val)
398 ICSIRQState *irq = ics->irqs + srcno;
400 trace_xics_set_irq_msi(srcno, srcno + ics->offset);
402 if (val) {
403 if (irq->priority == 0xff) {
404 irq->status |= XICS_STATUS_MASKED_PENDING;
405 trace_xics_masked_pending();
406 } else {
407 icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
412 static void set_irq_lsi(ICSState *ics, int srcno, int val)
414 ICSIRQState *irq = ics->irqs + srcno;
416 trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
417 if (val) {
418 irq->status |= XICS_STATUS_ASSERTED;
419 } else {
420 irq->status &= ~XICS_STATUS_ASSERTED;
422 resend_lsi(ics, srcno);
425 static void ics_set_irq(void *opaque, int srcno, int val)
427 ICSState *ics = (ICSState *)opaque;
429 if (ics->islsi[srcno]) {
430 set_irq_lsi(ics, srcno, val);
431 } else {
432 set_irq_msi(ics, srcno, val);
436 static void write_xive_msi(ICSState *ics, int srcno)
438 ICSIRQState *irq = ics->irqs + srcno;
440 if (!(irq->status & XICS_STATUS_MASKED_PENDING)
441 || (irq->priority == 0xff)) {
442 return;
445 irq->status &= ~XICS_STATUS_MASKED_PENDING;
446 icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
449 static void write_xive_lsi(ICSState *ics, int srcno)
451 resend_lsi(ics, srcno);
454 static void ics_write_xive(ICSState *ics, int nr, int server,
455 uint8_t priority, uint8_t saved_priority)
457 int srcno = nr - ics->offset;
458 ICSIRQState *irq = ics->irqs + srcno;
460 irq->server = server;
461 irq->priority = priority;
462 irq->saved_priority = saved_priority;
464 trace_xics_ics_write_xive(nr, srcno, server, priority);
466 if (ics->islsi[srcno]) {
467 write_xive_lsi(ics, srcno);
468 } else {
469 write_xive_msi(ics, srcno);
473 static void ics_reject(ICSState *ics, int nr)
475 ICSIRQState *irq = ics->irqs + nr - ics->offset;
477 trace_xics_ics_reject(nr, nr - ics->offset);
478 irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
479 irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
482 static void ics_resend(ICSState *ics)
484 int i;
486 for (i = 0; i < ics->nr_irqs; i++) {
487 /* FIXME: filter by server#? */
488 if (ics->islsi[i]) {
489 resend_lsi(ics, i);
490 } else {
491 resend_msi(ics, i);
496 static void ics_eoi(ICSState *ics, int nr)
498 int srcno = nr - ics->offset;
499 ICSIRQState *irq = ics->irqs + srcno;
501 trace_xics_ics_eoi(nr);
503 if (ics->islsi[srcno]) {
504 irq->status &= ~XICS_STATUS_SENT;
508 static void ics_reset(DeviceState *dev)
510 ICSState *ics = ICS(dev);
511 int i;
513 memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);
514 for (i = 0; i < ics->nr_irqs; i++) {
515 ics->irqs[i].priority = 0xff;
516 ics->irqs[i].saved_priority = 0xff;
520 static int ics_post_load(ICSState *ics, int version_id)
522 int i;
524 for (i = 0; i < ics->icp->nr_servers; i++) {
525 icp_resend(ics->icp, i);
528 return 0;
531 static void ics_dispatch_pre_save(void *opaque)
533 ICSState *ics = opaque;
534 ICSStateClass *info = ICS_GET_CLASS(ics);
536 if (info->pre_save) {
537 info->pre_save(ics);
541 static int ics_dispatch_post_load(void *opaque, int version_id)
543 ICSState *ics = opaque;
544 ICSStateClass *info = ICS_GET_CLASS(ics);
546 if (info->post_load) {
547 return info->post_load(ics, version_id);
550 return 0;
553 static const VMStateDescription vmstate_ics_irq = {
554 .name = "ics/irq",
555 .version_id = 1,
556 .minimum_version_id = 1,
557 .minimum_version_id_old = 1,
558 .fields = (VMStateField []) {
559 VMSTATE_UINT32(server, ICSIRQState),
560 VMSTATE_UINT8(priority, ICSIRQState),
561 VMSTATE_UINT8(saved_priority, ICSIRQState),
562 VMSTATE_UINT8(status, ICSIRQState),
563 VMSTATE_END_OF_LIST()
567 static const VMStateDescription vmstate_ics = {
568 .name = "ics",
569 .version_id = 1,
570 .minimum_version_id = 1,
571 .minimum_version_id_old = 1,
572 .pre_save = ics_dispatch_pre_save,
573 .post_load = ics_dispatch_post_load,
574 .fields = (VMStateField []) {
575 /* Sanity check */
576 VMSTATE_UINT32_EQUAL(nr_irqs, ICSState),
578 VMSTATE_STRUCT_VARRAY_POINTER_UINT32(irqs, ICSState, nr_irqs,
579 vmstate_ics_irq, ICSIRQState),
580 VMSTATE_END_OF_LIST()
584 static void ics_initfn(Object *obj)
586 ICSState *ics = ICS(obj);
588 ics->offset = XICS_IRQ_BASE;
591 static void ics_realize(DeviceState *dev, Error **errp)
593 ICSState *ics = ICS(dev);
595 if (!ics->nr_irqs) {
596 error_setg(errp, "Number of interrupts needs to be greater 0");
597 return;
599 ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
600 ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
601 ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
604 static void ics_class_init(ObjectClass *klass, void *data)
606 DeviceClass *dc = DEVICE_CLASS(klass);
607 ICSStateClass *isc = ICS_CLASS(klass);
609 dc->realize = ics_realize;
610 dc->vmsd = &vmstate_ics;
611 dc->reset = ics_reset;
612 isc->post_load = ics_post_load;
615 static const TypeInfo ics_info = {
616 .name = TYPE_ICS,
617 .parent = TYPE_DEVICE,
618 .instance_size = sizeof(ICSState),
619 .class_init = ics_class_init,
620 .class_size = sizeof(ICSStateClass),
621 .instance_init = ics_initfn,
625 * Exported functions
628 qemu_irq xics_get_qirq(XICSState *icp, int irq)
630 if (!ics_valid_irq(icp->ics, irq)) {
631 return NULL;
634 return icp->ics->qirqs[irq - icp->ics->offset];
637 void xics_set_irq_type(XICSState *icp, int irq, bool lsi)
639 assert(ics_valid_irq(icp->ics, irq));
641 icp->ics->islsi[irq - icp->ics->offset] = lsi;
645 * Guest interfaces
648 static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
649 target_ulong opcode, target_ulong *args)
651 CPUState *cs = CPU(cpu);
652 target_ulong cppr = args[0];
654 icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
655 return H_SUCCESS;
658 static target_ulong h_ipi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
659 target_ulong opcode, target_ulong *args)
661 target_ulong server = args[0];
662 target_ulong mfrr = args[1];
664 if (server >= spapr->icp->nr_servers) {
665 return H_PARAMETER;
668 icp_set_mfrr(spapr->icp, server, mfrr);
669 return H_SUCCESS;
672 static target_ulong h_xirr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
673 target_ulong opcode, target_ulong *args)
675 CPUState *cs = CPU(cpu);
676 uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
678 args[0] = xirr;
679 return H_SUCCESS;
682 static target_ulong h_eoi(PowerPCCPU *cpu, sPAPREnvironment *spapr,
683 target_ulong opcode, target_ulong *args)
685 CPUState *cs = CPU(cpu);
686 target_ulong xirr = args[0];
688 icp_eoi(spapr->icp, cs->cpu_index, xirr);
689 return H_SUCCESS;
692 static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPREnvironment *spapr,
693 target_ulong opcode, target_ulong *args)
695 CPUState *cs = CPU(cpu);
696 ICPState *ss = &spapr->icp->ss[cs->cpu_index];
698 args[0] = ss->xirr;
699 args[1] = ss->mfrr;
701 return H_SUCCESS;
704 static void rtas_set_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
705 uint32_t token,
706 uint32_t nargs, target_ulong args,
707 uint32_t nret, target_ulong rets)
709 ICSState *ics = spapr->icp->ics;
710 uint32_t nr, server, priority;
712 if ((nargs != 3) || (nret != 1)) {
713 rtas_st(rets, 0, -3);
714 return;
717 nr = rtas_ld(args, 0);
718 server = rtas_ld(args, 1);
719 priority = rtas_ld(args, 2);
721 if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
722 || (priority > 0xff)) {
723 rtas_st(rets, 0, -3);
724 return;
727 ics_write_xive(ics, nr, server, priority, priority);
729 rtas_st(rets, 0, 0); /* Success */
732 static void rtas_get_xive(PowerPCCPU *cpu, sPAPREnvironment *spapr,
733 uint32_t token,
734 uint32_t nargs, target_ulong args,
735 uint32_t nret, target_ulong rets)
737 ICSState *ics = spapr->icp->ics;
738 uint32_t nr;
740 if ((nargs != 1) || (nret != 3)) {
741 rtas_st(rets, 0, -3);
742 return;
745 nr = rtas_ld(args, 0);
747 if (!ics_valid_irq(ics, nr)) {
748 rtas_st(rets, 0, -3);
749 return;
752 rtas_st(rets, 0, 0); /* Success */
753 rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
754 rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
757 static void rtas_int_off(PowerPCCPU *cpu, sPAPREnvironment *spapr,
758 uint32_t token,
759 uint32_t nargs, target_ulong args,
760 uint32_t nret, target_ulong rets)
762 ICSState *ics = spapr->icp->ics;
763 uint32_t nr;
765 if ((nargs != 1) || (nret != 1)) {
766 rtas_st(rets, 0, -3);
767 return;
770 nr = rtas_ld(args, 0);
772 if (!ics_valid_irq(ics, nr)) {
773 rtas_st(rets, 0, -3);
774 return;
777 ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
778 ics->irqs[nr - ics->offset].priority);
780 rtas_st(rets, 0, 0); /* Success */
783 static void rtas_int_on(PowerPCCPU *cpu, sPAPREnvironment *spapr,
784 uint32_t token,
785 uint32_t nargs, target_ulong args,
786 uint32_t nret, target_ulong rets)
788 ICSState *ics = spapr->icp->ics;
789 uint32_t nr;
791 if ((nargs != 1) || (nret != 1)) {
792 rtas_st(rets, 0, -3);
793 return;
796 nr = rtas_ld(args, 0);
798 if (!ics_valid_irq(ics, nr)) {
799 rtas_st(rets, 0, -3);
800 return;
803 ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
804 ics->irqs[nr - ics->offset].saved_priority,
805 ics->irqs[nr - ics->offset].saved_priority);
807 rtas_st(rets, 0, 0); /* Success */
811 * XICS
814 static void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
816 icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
819 static void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers,
820 Error **errp)
822 int i;
824 icp->nr_servers = nr_servers;
826 icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
827 for (i = 0; i < icp->nr_servers; i++) {
828 char buffer[32];
829 object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
830 snprintf(buffer, sizeof(buffer), "icp[%d]", i);
831 object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
832 errp);
836 static void xics_realize(DeviceState *dev, Error **errp)
838 XICSState *icp = XICS(dev);
839 Error *error = NULL;
840 int i;
842 if (!icp->nr_servers) {
843 error_setg(errp, "Number of servers needs to be greater 0");
844 return;
847 /* Registration of global state belongs into realize */
848 spapr_rtas_register("ibm,set-xive", rtas_set_xive);
849 spapr_rtas_register("ibm,get-xive", rtas_get_xive);
850 spapr_rtas_register("ibm,int-off", rtas_int_off);
851 spapr_rtas_register("ibm,int-on", rtas_int_on);
853 spapr_register_hypercall(H_CPPR, h_cppr);
854 spapr_register_hypercall(H_IPI, h_ipi);
855 spapr_register_hypercall(H_XIRR, h_xirr);
856 spapr_register_hypercall(H_EOI, h_eoi);
857 spapr_register_hypercall(H_IPOLL, h_ipoll);
859 object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
860 if (error) {
861 error_propagate(errp, error);
862 return;
865 for (i = 0; i < icp->nr_servers; i++) {
866 object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
867 if (error) {
868 error_propagate(errp, error);
869 return;
874 static void xics_initfn(Object *obj)
876 XICSState *xics = XICS(obj);
878 xics->ics = ICS(object_new(TYPE_ICS));
879 object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
880 xics->ics->icp = xics;
883 static void xics_class_init(ObjectClass *oc, void *data)
885 DeviceClass *dc = DEVICE_CLASS(oc);
886 XICSStateClass *xsc = XICS_CLASS(oc);
888 dc->realize = xics_realize;
889 xsc->set_nr_irqs = xics_set_nr_irqs;
890 xsc->set_nr_servers = xics_set_nr_servers;
893 static const TypeInfo xics_info = {
894 .name = TYPE_XICS,
895 .parent = TYPE_XICS_COMMON,
896 .instance_size = sizeof(XICSState),
897 .class_size = sizeof(XICSStateClass),
898 .class_init = xics_class_init,
899 .instance_init = xics_initfn,
902 static void xics_register_types(void)
904 type_register_static(&xics_common_info);
905 type_register_static(&xics_info);
906 type_register_static(&ics_info);
907 type_register_static(&icp_info);
910 type_init(xics_register_types)