Index: sys/powerpc/pseries/xics.c =================================================================== --- sys/powerpc/pseries/xics.c +++ sys/powerpc/pseries/xics.c @@ -61,6 +61,9 @@ #define XICP_IPI 2 #define MAX_XICP_IRQS (1<<24) /* 24-bit XIRR field */ +#define XIVE_XICS_MODE_EMU 0 +#define XIVE_XICS_MODE_EXP 1 + static int xicp_probe(device_t); static int xicp_attach(device_t); static int xics_probe(device_t); @@ -117,6 +120,7 @@ int cpu; } intvecs[256]; int nintvecs; + bool xics_emu; }; static driver_t xicp_driver = { @@ -161,7 +165,8 @@ xicp_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "ibm,ppc-xicp")) + if (!ofw_bus_is_compatible(dev, "ibm,ppc-xicp") && + !ofw_bus_is_compatible(dev, "ibm,opal-intc")) return (ENXIO); device_set_desc(dev, "External Interrupt Presentation Controller"); @@ -172,7 +177,8 @@ xics_probe(device_t dev) { - if (!ofw_bus_is_compatible(dev, "ibm,ppc-xics")) + if (!ofw_bus_is_compatible(dev, "ibm,ppc-xics") && + !ofw_bus_is_compatible(dev, "IBM,opal-xics")) return (ENXIO); device_set_desc(dev, "External Interrupt Source Controller"); @@ -205,13 +211,22 @@ sc->cpu_range[1] += sc->cpu_range[0]; device_printf(dev, "Handling CPUs %d-%d\n", sc->cpu_range[0], sc->cpu_range[1]-1); +#ifdef POWERNV + } else if (ofw_bus_is_compatible(dev, "ibm,opal-intc")) { + /* + * For now run POWER9 XIVE interrupt controller in XICS + * compatibility mode. + */ + sc->xics_emu = true; + opal_call(OPAL_XIVE_RESET, XIVE_XICS_MODE_EMU); +#endif } else { sc->cpu_range[0] = 0; sc->cpu_range[1] = mp_ncpus; } #ifdef POWERNV - if (mfmsr() & PSL_HV) { + if ((mfmsr() & PSL_HV) && !sc->xics_emu) { int i; for (i = 0; i < sc->cpu_range[1] - sc->cpu_range[0]; i++) { @@ -329,6 +344,10 @@ /* Return value in R4, use the PFT call */ if (regs) { xirr = bus_read_4(regs, 4); +#ifdef POWERNV + } else if (sc->xics_emu) { + opal_call(OPAL_INT_GET_XIRR, vtophys(&xirr), false); +#endif } else { /* Return value in R4, use the PFT call */ phyp_pft_hcall(H_XIRR, 0, 0, 0, 0, &xirr, &junk, &junk); @@ -338,6 +357,10 @@ if (xirr == 0) { /* No more pending interrupts? */ if (regs) bus_write_1(regs, 4, 0xff); +#ifdef POWERNV + else if (sc->xics_emu) + opal_call(OPAL_INT_SET_CPPR, 0xff); +#endif else phyp_hcall(H_CPPR, (uint64_t)0xff); break; @@ -348,6 +371,10 @@ /* Clear IPI */ if (regs) bus_write_1(regs, 12, 0xff); +#ifdef POWERNV + else if (sc->xics_emu) + opal_call(OPAL_INT_SET_MFRR, 0xff); +#endif else phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(hwref)), 0xff); @@ -409,6 +436,9 @@ static void xicp_eoi(device_t dev, u_int irq) { +#ifdef POWERNV + struct xicp_softc *sc; +#endif uint64_t xirr; if (irq == MAX_XICP_IRQS) /* Remap IPI interrupt to internal value */ @@ -416,9 +446,13 @@ xirr = irq | (XICP_PRIORITY << 24); #ifdef POWERNV - if (mfmsr() & PSL_HV) - bus_write_4(xicp_mem_for_cpu(PCPU_GET(hwref)), 4, xirr); - else + if (mfmsr() & PSL_HV) { + sc = device_get_softc(dev); + if (sc->xics_emu) + opal_call(OPAL_INT_EOI, xirr); + else + bus_write_4(xicp_mem_for_cpu(PCPU_GET(hwref)), 4, xirr); + } else #endif phyp_hcall(H_EOI, xirr); } @@ -428,11 +462,16 @@ { #ifdef POWERNV + struct xicp_softc *sc; cpu = pcpu_find(cpu)->pc_hwref; - if (mfmsr() & PSL_HV) - bus_write_1(xicp_mem_for_cpu(cpu), 12, XICP_PRIORITY); - else + if (mfmsr() & PSL_HV) { + sc = device_get_softc(dev); + if (sc->xics_emu) + opal_call(OPAL_INT_SET_MFRR, cpu, XICP_PRIORITY); + else + bus_write_1(xicp_mem_for_cpu(cpu), 12, XICP_PRIORITY); + } else #endif phyp_hcall(H_IPI, (uint64_t)cpu, XICP_PRIORITY); }