diff --git a/hw/ppc/spapr_irq.c b/hw/ppc/spapr_irq.c index 83882cfad3..249a2688ac 100644 --- a/hw/ppc/spapr_irq.c +++ b/hw/ppc/spapr_irq.c @@ -586,6 +586,7 @@ qemu_irq spapr_qirq(SpaprMachineState *spapr, int irq) int spapr_irq_post_load(SpaprMachineState *spapr, int version_id) { + spapr_irq_update_active_intc(spapr); return spapr->irq->post_load(spapr, version_id); } @@ -593,6 +594,8 @@ void spapr_irq_reset(SpaprMachineState *spapr, Error **errp) { assert(!spapr->irq_map || bitmap_empty(spapr->irq_map, spapr->irq_map_nr)); + spapr_irq_update_active_intc(spapr); + if (spapr->irq->reset) { spapr->irq->reset(spapr, errp); } @@ -619,6 +622,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 */ diff --git a/include/hw/ppc/spapr.h b/include/hw/ppc/spapr.h index 2009eb64f9..3b34cf5207 100644 --- a/include/hw/ppc/spapr.h +++ b/include/hw/ppc/spapr.h @@ -144,7 +144,6 @@ struct SpaprMachineState { struct SpaprVioBus *vio_bus; QLIST_HEAD(, SpaprPhbState) phbs; struct SpaprNvram *nvram; - ICSState *ics; SpaprRtcState rtc; SpaprResizeHpt resize_hpt; @@ -196,9 +195,11 @@ struct SpaprMachineState { int32_t irq_map_nr; unsigned long *irq_map; - SpaprXive *xive; SpaprIrq *irq; qemu_irq *qirqs; + SpaprInterruptController *active_intc; + ICSState *ics; + SpaprXive *xive; bool cmd_line_caps[SPAPR_CAP_NUM]; SpaprCapabilities def, eff, mig; diff --git a/include/hw/ppc/spapr_irq.h b/include/hw/ppc/spapr_irq.h index adfef0fcbe..593059eff5 100644 --- a/include/hw/ppc/spapr_irq.h +++ b/include/hw/ppc/spapr_irq.h @@ -44,6 +44,9 @@ typedef struct SpaprInterruptController SpaprInterruptController; typedef struct SpaprInterruptControllerClass { InterfaceClass parent; + int (*activate)(SpaprInterruptController *intc, Error **errp); + void (*deactivate)(SpaprInterruptController *intc); + /* * These methods will typically be called on all intcs, active and * inactive @@ -55,6 +58,8 @@ typedef struct SpaprInterruptControllerClass { void (*free_irq)(SpaprInterruptController *intc, int irq); } SpaprInterruptControllerClass; +void spapr_irq_update_active_intc(SpaprMachineState *spapr); + int spapr_irq_cpu_intc_create(SpaprMachineState *spapr, PowerPCCPU *cpu, Error **errp);