summaryrefslogtreecommitdiffstats
path: root/hw/ppc/spapr_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'hw/ppc/spapr_irq.c')
-rw-r--r--hw/ppc/spapr_irq.c611
1 files changed, 216 insertions, 395 deletions
diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c
index 457eabe24c..b941608b69 100644
--- a/hw/ppc/spapr_irq.c
+++ b/hw/ppc/spapr_irq.c
@@ -23,9 +23,20 @@
#include "trace.h"
-void spapr_irq_msi_init(SpaprMachineState *spapr, uint32_t nr_msis)
+static const TypeInfo spapr_intc_info = {
+ .name = TYPE_SPAPR_INTC,
+ .parent = TYPE_INTERFACE,
+ .class_size = sizeof(SpaprInterruptControllerClass),
+};
+
+static void spapr_irq_msi_init(SpaprMachineState *spapr)
{
- spapr->irq_map_nr = nr_msis;
+ if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
+ /* Legacy mode doesn't use this allocator */
+ return;
+ }
+
+ spapr->irq_map_nr = spapr_irq_nr_msis(spapr);
spapr->irq_map = bitmap_new(spapr->irq_map_nr);
}
@@ -59,262 +70,53 @@ void spapr_irq_msi_free(SpaprMachineState *spapr, int irq, uint32_t num)
bitmap_clear(spapr->irq_map, irq - SPAPR_IRQ_MSI, num);
}
-static void spapr_irq_init_kvm(SpaprMachineState *spapr,
- SpaprIrq *irq, Error **errp)
+int spapr_irq_init_kvm(int (*fn)(SpaprInterruptController *, Error **),
+ SpaprInterruptController *intc,
+ Error **errp)
{
- MachineState *machine = MACHINE(spapr);
+ MachineState *machine = MACHINE(qdev_get_machine());
Error *local_err = NULL;
if (kvm_enabled() && machine_kernel_irqchip_allowed(machine)) {
- irq->init_kvm(spapr, &local_err);
- if (local_err && machine_kernel_irqchip_required(machine)) {
- error_prepend(&local_err,
- "kernel_irqchip requested but unavailable: ");
- error_propagate(errp, local_err);
- return;
- }
+ if (fn(intc, &local_err) < 0) {
+ if (machine_kernel_irqchip_required(machine)) {
+ error_prepend(&local_err,
+ "kernel_irqchip requested but unavailable: ");
+ error_propagate(errp, local_err);
+ return -1;
+ }
- if (!local_err) {
- return;
+ /*
+ * We failed to initialize the KVM device, fallback to
+ * emulated mode
+ */
+ error_prepend(&local_err,
+ "kernel_irqchip allowed but unavailable: ");
+ error_append_hint(&local_err,
+ "Falling back to kernel-irqchip=off\n");
+ warn_report_err(local_err);
}
-
- /*
- * We failed to initialize the KVM device, fallback to
- * emulated mode
- */
- error_prepend(&local_err, "kernel_irqchip allowed but unavailable: ");
- error_append_hint(&local_err, "Falling back to kernel-irqchip=off\n");
- warn_report_err(local_err);
}
+
+ return 0;
}
/*
* XICS IRQ backend.
*/
-static int spapr_irq_claim_xics(SpaprMachineState *spapr, int irq, bool lsi,
- Error **errp)
-{
- ICSState *ics = spapr->ics;
-
- assert(ics);
- assert(ics_valid_irq(ics, irq));
-
- if (!ics_irq_free(ics, irq - ics->offset)) {
- error_setg(errp, "IRQ %d is not free", irq);
- return -1;
- }
-
- ics_set_irq_type(ics, irq - ics->offset, lsi);
- return 0;
-}
-
-static void spapr_irq_free_xics(SpaprMachineState *spapr, int irq)
-{
- ICSState *ics = spapr->ics;
- uint32_t srcno = irq - ics->offset;
-
- assert(ics_valid_irq(ics, irq));
-
- memset(&ics->irqs[srcno], 0, sizeof(ICSIRQState));
-}
-
-static void spapr_irq_print_info_xics(SpaprMachineState *spapr, Monitor *mon)
-{
- CPUState *cs;
-
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
- }
-
- ics_pic_print_info(spapr->ics, mon);
-}
-
-static void spapr_irq_cpu_intc_create_xics(SpaprMachineState *spapr,
- PowerPCCPU *cpu, Error **errp)
-{
- Error *local_err = NULL;
- Object *obj;
- SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
- obj = icp_create(OBJECT(cpu), TYPE_ICP, XICS_FABRIC(spapr),
- &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_cpu->icp = ICP(obj);
-}
-
-static int spapr_irq_post_load_xics(SpaprMachineState *spapr, int version_id)
-{
- if (!kvm_irqchip_in_kernel()) {
- CPUState *cs;
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
- icp_resend(spapr_cpu_state(cpu)->icp);
- }
- }
- return 0;
-}
-
-static void spapr_irq_set_irq_xics(void *opaque, int irq, int val)
-{
- SpaprMachineState *spapr = opaque;
- uint32_t srcno = irq - spapr->ics->offset;
-
- ics_set_irq(spapr->ics, srcno, val);
-}
-
-static void spapr_irq_reset_xics(SpaprMachineState *spapr, Error **errp)
-{
- Error *local_err = NULL;
-
- spapr_irq_init_kvm(spapr, &spapr_irq_xics, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-}
-
-static void spapr_irq_init_kvm_xics(SpaprMachineState *spapr, Error **errp)
-{
- if (kvm_enabled()) {
- xics_kvm_connect(spapr, errp);
- }
-}
-
SpaprIrq spapr_irq_xics = {
- .nr_xirqs = SPAPR_NR_XIRQS,
- .nr_msis = SPAPR_NR_MSIS,
.xics = true,
.xive = false,
-
- .claim = spapr_irq_claim_xics,
- .free = spapr_irq_free_xics,
- .print_info = spapr_irq_print_info_xics,
- .dt_populate = spapr_dt_xics,
- .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
- .post_load = spapr_irq_post_load_xics,
- .reset = spapr_irq_reset_xics,
- .set_irq = spapr_irq_set_irq_xics,
- .init_kvm = spapr_irq_init_kvm_xics,
};
/*
* XIVE IRQ backend.
*/
-static int spapr_irq_claim_xive(SpaprMachineState *spapr, int irq, bool lsi,
- Error **errp)
-{
- return spapr_xive_irq_claim(spapr->xive, irq, lsi, errp);
-}
-
-static void spapr_irq_free_xive(SpaprMachineState *spapr, int irq)
-{
- spapr_xive_irq_free(spapr->xive, irq);
-}
-
-static void spapr_irq_print_info_xive(SpaprMachineState *spapr,
- Monitor *mon)
-{
- CPUState *cs;
-
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- xive_tctx_pic_print_info(spapr_cpu_state(cpu)->tctx, mon);
- }
-
- spapr_xive_pic_print_info(spapr->xive, mon);
-}
-
-static void spapr_irq_cpu_intc_create_xive(SpaprMachineState *spapr,
- PowerPCCPU *cpu, Error **errp)
-{
- Error *local_err = NULL;
- Object *obj;
- SpaprCpuState *spapr_cpu = spapr_cpu_state(cpu);
-
- obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_cpu->tctx = XIVE_TCTX(obj);
-
- /*
- * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
- * don't beneficiate from the reset of the XIVE IRQ backend
- */
- spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
-}
-
-static int spapr_irq_post_load_xive(SpaprMachineState *spapr, int version_id)
-{
- return spapr_xive_post_load(spapr->xive, version_id);
-}
-
-static void spapr_irq_reset_xive(SpaprMachineState *spapr, Error **errp)
-{
- CPUState *cs;
- Error *local_err = NULL;
-
- CPU_FOREACH(cs) {
- PowerPCCPU *cpu = POWERPC_CPU(cs);
-
- /* (TCG) Set the OS CAM line of the thread interrupt context. */
- spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx);
- }
-
- spapr_irq_init_kvm(spapr, &spapr_irq_xive, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- /* Activate the XIVE MMIOs */
- spapr_xive_mmio_set_enabled(spapr->xive, true);
-}
-
-static void spapr_irq_set_irq_xive(void *opaque, int irq, int val)
-{
- SpaprMachineState *spapr = opaque;
-
- if (kvm_irqchip_in_kernel()) {
- kvmppc_xive_source_set_irq(&spapr->xive->source, irq, val);
- } else {
- xive_source_set_irq(&spapr->xive->source, irq, val);
- }
-}
-
-static void spapr_irq_init_kvm_xive(SpaprMachineState *spapr, Error **errp)
-{
- if (kvm_enabled()) {
- kvmppc_xive_connect(spapr->xive, errp);
- }
-}
-
SpaprIrq spapr_irq_xive = {
- .nr_xirqs = SPAPR_NR_XIRQS,
- .nr_msis = SPAPR_NR_MSIS,
.xics = false,
.xive = true,
-
- .claim = spapr_irq_claim_xive,
- .free = spapr_irq_free_xive,
- .print_info = spapr_irq_print_info_xive,
- .dt_populate = spapr_dt_xive,
- .cpu_intc_create = spapr_irq_cpu_intc_create_xive,
- .post_load = spapr_irq_post_load_xive,
- .reset = spapr_irq_reset_xive,
- .set_irq = spapr_irq_set_irq_xive,
- .init_kvm = spapr_irq_init_kvm_xive,
};
/*
@@ -327,138 +129,11 @@ SpaprIrq spapr_irq_xive = {
*/
/*
- * Returns the sPAPR IRQ backend negotiated by CAS. XICS is the
- * default.
- */
-static SpaprIrq *spapr_irq_current(SpaprMachineState *spapr)
-{
- return spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT) ?
- &spapr_irq_xive : &spapr_irq_xics;
-}
-
-static int spapr_irq_claim_dual(SpaprMachineState *spapr, int irq, bool lsi,
- Error **errp)
-{
- Error *local_err = NULL;
- int ret;
-
- ret = spapr_irq_xics.claim(spapr, irq, lsi, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return ret;
- }
-
- ret = spapr_irq_xive.claim(spapr, irq, lsi, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return ret;
- }
-
- return ret;
-}
-
-static void spapr_irq_free_dual(SpaprMachineState *spapr, int irq)
-{
- spapr_irq_xics.free(spapr, irq);
- spapr_irq_xive.free(spapr, irq);
-}
-
-static void spapr_irq_print_info_dual(SpaprMachineState *spapr, Monitor *mon)
-{
- spapr_irq_current(spapr)->print_info(spapr, mon);
-}
-
-static void spapr_irq_dt_populate_dual(SpaprMachineState *spapr,
- uint32_t nr_servers, void *fdt,
- uint32_t phandle)
-{
- spapr_irq_current(spapr)->dt_populate(spapr, nr_servers, fdt, phandle);
-}
-
-static void spapr_irq_cpu_intc_create_dual(SpaprMachineState *spapr,
- PowerPCCPU *cpu, Error **errp)
-{
- Error *local_err = NULL;
-
- spapr_irq_xive.cpu_intc_create(spapr, cpu, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- return;
- }
-
- spapr_irq_xics.cpu_intc_create(spapr, cpu, errp);
-}
-
-static int spapr_irq_post_load_dual(SpaprMachineState *spapr, int version_id)
-{
- /*
- * Force a reset of the XIVE backend after migration. The machine
- * defaults to XICS at startup.
- */
- if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
- if (kvm_irqchip_in_kernel()) {
- xics_kvm_disconnect(spapr, &error_fatal);
- }
- spapr_irq_xive.reset(spapr, &error_fatal);
- }
-
- return spapr_irq_current(spapr)->post_load(spapr, version_id);
-}
-
-static void spapr_irq_reset_dual(SpaprMachineState *spapr, Error **errp)
-{
- Error *local_err = NULL;
-
- /*
- * Deactivate the XIVE MMIOs. The XIVE backend will reenable them
- * if selected.
- */
- spapr_xive_mmio_set_enabled(spapr->xive, false);
-
- /* Destroy all KVM devices */
- if (kvm_irqchip_in_kernel()) {
- xics_kvm_disconnect(spapr, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- error_prepend(errp, "KVM XICS disconnect failed: ");
- return;
- }
- kvmppc_xive_disconnect(spapr->xive, &local_err);
- if (local_err) {
- error_propagate(errp, local_err);
- error_prepend(errp, "KVM XIVE disconnect failed: ");
- return;
- }
- }
-
- spapr_irq_current(spapr)->reset(spapr, errp);
-}
-
-static void spapr_irq_set_irq_dual(void *opaque, int irq, int val)
-{
- SpaprMachineState *spapr = opaque;
-
- spapr_irq_current(spapr)->set_irq(spapr, irq, val);
-}
-
-/*
* Define values in sync with the XIVE and XICS backend
*/
SpaprIrq spapr_irq_dual = {
- .nr_xirqs = SPAPR_NR_XIRQS,
- .nr_msis = SPAPR_NR_MSIS,
.xics = true,
.xive = true,
-
- .claim = spapr_irq_claim_dual,
- .free = spapr_irq_free_dual,
- .print_info = spapr_irq_print_info_dual,
- .dt_populate = spapr_irq_dt_populate_dual,
- .cpu_intc_create = spapr_irq_cpu_intc_create_dual,
- .post_load = spapr_irq_post_load_dual,
- .reset = spapr_irq_reset_dual,
- .set_irq = spapr_irq_set_irq_dual,
- .init_kvm = NULL, /* should not be used */
};
@@ -521,9 +196,85 @@ static int spapr_irq_check(SpaprMachineState *spapr, Error **errp)
/*
* sPAPR IRQ frontend routines for devices
*/
+#define ALL_INTCS(spapr_) \
+ { SPAPR_INTC((spapr_)->ics), SPAPR_INTC((spapr_)->xive), }
+
+int spapr_irq_cpu_intc_create(SpaprMachineState *spapr,
+ PowerPCCPU *cpu, Error **errp)
+{
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i;
+ int rc;
+
+ for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+ SpaprInterruptController *intc = intcs[i];
+ if (intc) {
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+ rc = sicc->cpu_intc_create(intc, cpu, errp);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+ }
+
+ return 0;
+}
+
+void spapr_irq_cpu_intc_reset(SpaprMachineState *spapr, PowerPCCPU *cpu)
+{
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+ SpaprInterruptController *intc = intcs[i];
+ if (intc) {
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+ sicc->cpu_intc_reset(intc, cpu);
+ }
+ }
+}
+
+static void spapr_set_irq(void *opaque, int irq, int level)
+{
+ SpaprMachineState *spapr = SPAPR_MACHINE(opaque);
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+ sicc->set_irq(spapr->active_intc, irq, level);
+}
+
+void spapr_irq_print_info(SpaprMachineState *spapr, Monitor *mon)
+{
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+ sicc->print_info(spapr->active_intc, mon);
+}
+
+void spapr_irq_dt(SpaprMachineState *spapr, uint32_t nr_servers,
+ void *fdt, uint32_t phandle)
+{
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+
+ sicc->dt(spapr->active_intc, nr_servers, fdt, phandle);
+}
+
+uint32_t spapr_irq_nr_msis(SpaprMachineState *spapr)
+{
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
+ if (smc->legacy_irq_allocation) {
+ return smc->nr_xirqs;
+ } else {
+ return SPAPR_XIRQ_BASE + smc->nr_xirqs - SPAPR_IRQ_MSI;
+ }
+}
+
void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
{
MachineState *machine = MACHINE(spapr);
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
if (machine_kernel_irqchip_split(machine)) {
error_setg(errp, "kernel_irqchip split mode not supported on pseries");
@@ -541,9 +292,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
}
/* Initialize the MSI IRQ allocator. */
- if (!SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
- spapr_irq_msi_init(spapr, spapr->irq->nr_msis);
- }
+ spapr_irq_msi_init(spapr);
if (spapr->irq->xics) {
Error *local_err = NULL;
@@ -563,8 +312,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
return;
}
- object_property_set_int(obj, spapr->irq->nr_xirqs, "nr-irqs",
- &local_err);
+ object_property_set_int(obj, smc->nr_xirqs, "nr-irqs", &local_err);
if (local_err) {
error_propagate(errp, local_err);
return;
@@ -585,8 +333,7 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
int i;
dev = qdev_create(NULL, TYPE_SPAPR_XIVE);
- qdev_prop_set_uint32(dev, "nr-irqs",
- spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
+ qdev_prop_set_uint32(dev, "nr-irqs", smc->nr_xirqs + SPAPR_XIRQ_BASE);
/*
* 8 XIVE END structures per CPU. One for each available
* priority
@@ -598,8 +345,11 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
/* Enable the CPU IPIs */
for (i = 0; i < nr_servers; ++i) {
- if (spapr_xive_irq_claim(spapr->xive, SPAPR_IRQ_IPI + i,
- false, errp) < 0) {
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(spapr->xive);
+
+ if (sicc->claim_irq(SPAPR_INTC(spapr->xive), SPAPR_IRQ_IPI + i,
+ false, errp) < 0) {
return;
}
}
@@ -607,32 +357,60 @@ void spapr_irq_init(SpaprMachineState *spapr, Error **errp)
spapr_xive_hcall_init(spapr);
}
- spapr->qirqs = qemu_allocate_irqs(spapr->irq->set_irq, spapr,
- spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE);
+ spapr->qirqs = qemu_allocate_irqs(spapr_set_irq, spapr,
+ smc->nr_xirqs + SPAPR_XIRQ_BASE);
}
int spapr_irq_claim(SpaprMachineState *spapr, int irq, bool lsi, Error **errp)
{
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i;
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+ int rc;
+
assert(irq >= SPAPR_XIRQ_BASE);
- assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
+
+ for (i = 0; i < ARRAY_SIZE(intcs); i++) {
+ SpaprInterruptController *intc = intcs[i];
+ if (intc) {
+ SpaprInterruptControllerClass *sicc = SPAPR_INTC_GET_CLASS(intc);
+ rc = sicc->claim_irq(intc, irq, lsi, errp);
+ if (rc < 0) {
+ return rc;
+ }
+ }
+ }
- return spapr->irq->claim(spapr, irq, lsi, errp);
+ return 0;
}
void spapr_irq_free(SpaprMachineState *spapr, int irq, int num)
{
- int i;
+ SpaprInterruptController *intcs[] = ALL_INTCS(spapr);
+ int i, j;
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
assert(irq >= SPAPR_XIRQ_BASE);
- assert((irq + num) <= (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert((irq + num) <= (smc->nr_xirqs + SPAPR_XIRQ_BASE));
for (i = irq; i < (irq + num); i++) {
- spapr->irq->free(spapr, i);
+ for (j = 0; j < ARRAY_SIZE(intcs); j++) {
+ SpaprInterruptController *intc = intcs[j];
+
+ if (intc) {
+ SpaprInterruptControllerClass *sicc
+ = SPAPR_INTC_GET_CLASS(intc);
+ sicc->free_irq(intc, i);
+ }
+ }
}
}
qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
{
+ SpaprMachineClass *smc = SPAPR_MACHINE_GET_CLASS(spapr);
+
/*
* This interface is basically for VIO and PHB devices to find the
* right qemu_irq to manipulate, so we only allow access to the
@@ -641,7 +419,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
* interfaces, we can change this if we need to in future.
*/
assert(irq >= SPAPR_XIRQ_BASE);
- assert(irq < (spapr->irq->nr_xirqs + SPAPR_XIRQ_BASE));
+ assert(irq < (smc->nr_xirqs + SPAPR_XIRQ_BASE));
if (spapr->ics) {
assert(ics_valid_irq(spapr->ics, irq));
@@ -656,16 +434,18 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq)
int spapr_irq_post_load(SpaprMachineState *spapr, int version_id)
{
- return spapr->irq->post_load(spapr, version_id);
+ SpaprInterruptControllerClass *sicc;
+
+ spapr_irq_update_active_intc(spapr);
+ sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+ return sicc->post_load(spapr->active_intc, version_id);
}
void spapr_irq_reset(SpaprMachineState *spapr, Error **errp)
{
assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr));
- if (spapr->irq->reset) {
- spapr->irq->reset(spapr, errp);
- }
+ spapr_irq_update_active_intc(spapr);
}
int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
@@ -689,6 +469,54 @@ int spapr_irq_get_phandle(SpaprMachineState *spapr, void *fdt, Error **errp)
return phandle;
}
+static void set_active_intc(SpaprMachineState *spapr,
+ SpaprInterruptController *new_intc)
+{
+ SpaprInterruptControllerClass *sicc;
+
+ assert(new_intc);
+
+ if (new_intc == spapr->active_intc) {
+ /* Nothing to do */
+ return;
+ }
+
+ if (spapr->active_intc) {
+ sicc = SPAPR_INTC_GET_CLASS(spapr->active_intc);
+ if (sicc->deactivate) {
+ sicc->deactivate(spapr->active_intc);
+ }
+ }
+
+ sicc = SPAPR_INTC_GET_CLASS(new_intc);
+ if (sicc->activate) {
+ sicc->activate(new_intc, &error_fatal);
+ }
+
+ spapr->active_intc = new_intc;
+}
+
+void spapr_irq_update_active_intc(SpaprMachineState *spapr)
+{
+ SpaprInterruptController *new_intc;
+
+ if (!spapr->ics) {
+ /*
+ * XXX before we run CAS, ov5_cas is initialized empty, which
+ * indicates XICS, even if we have ic-mode=xive. TODO: clean
+ * up the CAS path so that we have a clearer way of handling
+ * this.
+ */
+ new_intc = SPAPR_INTC(spapr->xive);
+ } else if (spapr_ovec_test(spapr->ov5_cas, OV5_XIVE_EXPLOIT)) {
+ new_intc = SPAPR_INTC(spapr->xive);
+ } else {
+ new_intc = SPAPR_INTC(spapr->ics);
+ }
+
+ set_active_intc(spapr, new_intc);
+}
+
/*
* XICS legacy routines - to deprecate one day
*/
@@ -744,21 +572,14 @@ int spapr_irq_find(SpaprMachineState *spapr, int num, bool align, Error **errp)
return first + ics->offset;
}
-#define SPAPR_IRQ_XICS_LEGACY_NR_XIRQS 0x400
-
SpaprIrq spapr_irq_xics_legacy = {
- .nr_xirqs = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
- .nr_msis = SPAPR_IRQ_XICS_LEGACY_NR_XIRQS,
.xics = true,
.xive = false,
-
- .claim = spapr_irq_claim_xics,
- .free = spapr_irq_free_xics,
- .print_info = spapr_irq_print_info_xics,
- .dt_populate = spapr_dt_xics,
- .cpu_intc_create = spapr_irq_cpu_intc_create_xics,
- .post_load = spapr_irq_post_load_xics,
- .reset = spapr_irq_reset_xics,
- .set_irq = spapr_irq_set_irq_xics,
- .init_kvm = spapr_irq_init_kvm_xics,
};
+
+static void spapr_irq_register_types(void)
+{
+ type_register_static(&spapr_intc_info);
+}
+
+type_init(spapr_irq_register_types)