Author: jhibbits
Date: Sun May 20 03:23:17 2018
New Revision: 333912
URL: https://svnweb.freebsd.org/changeset/base/333912

Log:
  Add support for the XIVE XICS emulation mode for POWER9 systems
  
  Summary:
  POWER9 systems use a new interrupt controller, XIVE, managed through OPAL
  firmware calls.  The OPAL firmware includes support for emulating the previous
  generation XICS presentation layer in addition to a new "XIVE Exploitation"
  mode.  As a stopgap until we have XIVE exploitation mode, enable XICS 
emulation
  mode so that we at least have an interrupt controller.
  
  Since the CPPR is local to the current CPU, it cannot be updated for APs when
  initializing on the BSP.  This adds a new function, directly called by the
  powernv platform code, to initialize the CPPR on AP bringup.
  
  Reviewed by:  nwhitehorn
  Differential Revision: https://reviews.freebsd.org/D15492

Modified:
  head/sys/powerpc/aim/mp_cpudep.c
  head/sys/powerpc/include/cpu.h
  head/sys/powerpc/include/spr.h
  head/sys/powerpc/powernv/opal.h
  head/sys/powerpc/powernv/platform_powernv.c
  head/sys/powerpc/powerpc/cpu.c
  head/sys/powerpc/pseries/xics.c

Modified: head/sys/powerpc/aim/mp_cpudep.c
==============================================================================
--- head/sys/powerpc/aim/mp_cpudep.c    Sun May 20 02:27:58 2018        
(r333911)
+++ head/sys/powerpc/aim/mp_cpudep.c    Sun May 20 03:23:17 2018        
(r333912)
@@ -96,7 +96,7 @@ cpudep_ap_early_bootstrap(void)
                        mtspr(SPR_LPID, 0);
                        isync();
 
-                       mtspr(SPR_LPCR, LPCR_LPES);
+                       mtspr(SPR_LPCR, lpcr);
                        isync();
                }
 #endif
@@ -401,7 +401,7 @@ cpudep_ap_setup()
        case IBMPOWER9:
 #ifdef __powerpc64__
                if (mfmsr() & PSL_HV) {
-                       mtspr(SPR_LPCR, mfspr(SPR_LPCR) | LPCR_LPES |
+                       mtspr(SPR_LPCR, mfspr(SPR_LPCR) | lpcr |
                            LPCR_PECE_WAKESET);
                        isync();
                }

Modified: head/sys/powerpc/include/cpu.h
==============================================================================
--- head/sys/powerpc/include/cpu.h      Sun May 20 02:27:58 2018        
(r333911)
+++ head/sys/powerpc/include/cpu.h      Sun May 20 03:23:17 2018        
(r333912)
@@ -135,6 +135,7 @@ extern char etext[];
 #ifdef __powerpc64__
 extern void enter_idle_powerx(void);
 extern uint64_t can_wakeup;
+extern register_t lpcr;
 #endif
 
 void   cpu_halt(void);

Modified: head/sys/powerpc/include/spr.h
==============================================================================
--- head/sys/powerpc/include/spr.h      Sun May 20 02:27:58 2018        
(r333911)
+++ head/sys/powerpc/include/spr.h      Sun May 20 03:23:17 2018        
(r333912)
@@ -215,14 +215,6 @@
 #define          FSL_E300C3              0x8085
 #define          FSL_E300C4              0x8086
 
-#define        SPR_LPCR                0x13e   /* Logical Partitioning Control 
*/
-#define          LPCR_LPES             0x008   /* Bit 60 */
-#define   LPCR_PECE_DRBL        (1ULL << 16)    /* Directed Privileged 
Doorbell */
-#define   LPCR_PECE_HDRBL       (1ULL << 15)    /* Directed Hypervisor 
Doorbell */
-#define   LPCR_PECE_EXT         (1ULL << 14)    /* External exceptions */
-#define   LPCR_PECE_DECR        (1ULL << 13)    /* Decrementer exceptions */
-#define   LPCR_PECE_ME          (1ULL << 12)    /* Machine Check and 
Hypervisor */
-                                                /* Maintenance exceptions */
 #define   LPCR_PECE_WAKESET     (LPCR_PECE_EXT | LPCR_PECE_DECR | LPCR_PECE_ME)
  
 #define        SPR_EPCR                0x133
@@ -242,7 +234,14 @@
 #define        SPR_HSRR0               0x13a
 #define        SPR_HSRR1               0x13b
 #define        SPR_LPCR                0x13e   /* Logical Partitioning Control 
*/
-#define          LPCR_LPES             0x008   /* Bit 60 */
+#define          LPCR_LPES               0x008 /* Bit 60 */
+#define          LPCR_HVICE              0x002 /* Hypervisor Virtualization 
Interrupt (Arch 3.0) */
+#define          LPCR_PECE_DRBL          (1ULL << 16) /* Directed Privileged 
Doorbell */
+#define          LPCR_PECE_HDRBL         (1ULL << 15) /* Directed Hypervisor 
Doorbell */
+#define          LPCR_PECE_EXT           (1ULL << 14) /* External exceptions */
+#define          LPCR_PECE_DECR          (1ULL << 13) /* Decrementer 
exceptions */
+#define          LPCR_PECE_ME            (1ULL << 12) /* Machine Check and 
Hypervisor */
+                                               /* Maintenance exceptions */
 #define        SPR_LPID                0x13f   /* Logical Partitioning Control 
*/
 
 #define        SPR_PTCR                0x1d0   /* Partition Table Control 
Register */

Modified: head/sys/powerpc/powernv/opal.h
==============================================================================
--- head/sys/powerpc/powernv/opal.h     Sun May 20 02:27:58 2018        
(r333911)
+++ head/sys/powerpc/powernv/opal.h     Sun May 20 03:23:17 2018        
(r333912)
@@ -73,7 +73,12 @@ int opal_call(uint64_t token, ...);
 #define        OPAL_REINIT_CPUS                70
 #define        OPAL_CHECK_ASYNC_COMPLETION     86
 #define        OPAL_I2C_REQUEST                109
+#define        OPAL_INT_GET_XIRR               122
+#define        OPAL_INT_SET_CPPR               123
+#define        OPAL_INT_EOI                    124
+#define        OPAL_INT_SET_MFRR               125
 #define        OPAL_PCI_TCE_KILL               126
+#define        OPAL_XIVE_RESET                 128
 
 /* For OPAL_PCI_SET_PE */
 #define        OPAL_UNMAP_PE                   0

Modified: head/sys/powerpc/powernv/platform_powernv.c
==============================================================================
--- head/sys/powerpc/powernv/platform_powernv.c Sun May 20 02:27:58 2018        
(r333911)
+++ head/sys/powerpc/powernv/platform_powernv.c Sun May 20 03:23:17 2018        
(r333912)
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
 extern void *ap_pcpu;
 #endif
 
+extern void xicp_smp_cpu_startup(void);
 static int powernv_probe(platform_t);
 static int powernv_attach(platform_t);
 void powernv_mem_regions(platform_t, struct mem_region *phys, int *physsz,
@@ -152,14 +153,14 @@ powernv_attach(platform_t plat)
        mtspr(SPR_LPID, 0);
        isync();
 
-       mtspr(SPR_LPCR, LPCR_LPES);
+       if (cpu_features2 & PPC_FEATURE2_ARCH_3_00)
+               lpcr |= LPCR_HVICE;
+
+       mtspr(SPR_LPCR, lpcr);
        isync();
 
        mtmsr(msr);
 
-       /* Init CPU bits */
-       powernv_smp_ap_init(plat);
-
        powernv_cpuref_init();
 
        /* Set SLB count from device tree */
@@ -460,6 +461,8 @@ powernv_reset(platform_t platform)
 static void
 powernv_smp_ap_init(platform_t platform)
 {
+
+       xicp_smp_cpu_startup();
 }
 
 static void

Modified: head/sys/powerpc/powerpc/cpu.c
==============================================================================
--- head/sys/powerpc/powerpc/cpu.c      Sun May 20 02:27:58 2018        
(r333911)
+++ head/sys/powerpc/powerpc/cpu.c      Sun May 20 03:23:17 2018        
(r333912)
@@ -240,6 +240,10 @@ SYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features, CTLFLAG_RD,
 SYSCTL_OPAQUE(_hw, OID_AUTO, cpu_features2, CTLFLAG_RD,
     &cpu_features2, sizeof(cpu_features2), "LX", "PowerPC CPU features 2");
 
+#ifdef __powerpc64__
+register_t     lpcr = LPCR_LPES;
+#endif
+
 /* Provide some user-friendly aliases for bits in cpu_features */
 SYSCTL_PROC(_hw, OID_AUTO, floatingpoint, CTLTYPE_INT | CTLFLAG_RD,
     0, PPC_FEATURE_HAS_FPU, cpu_feature_bit, "I",

Modified: head/sys/powerpc/pseries/xics.c
==============================================================================
--- head/sys/powerpc/pseries/xics.c     Sun May 20 02:27:58 2018        
(r333911)
+++ head/sys/powerpc/pseries/xics.c     Sun May 20 03:23:17 2018        
(r333912)
@@ -61,6 +61,9 @@ __FBSDID("$FreeBSD$");
 #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);
@@ -74,6 +77,10 @@ static void  xicp_ipi(device_t, u_int);
 static void    xicp_mask(device_t, u_int);
 static void    xicp_unmask(device_t, u_int);
 
+#ifdef POWERNV
+void   xicp_smp_cpu_startup(void);
+#endif
+
 static device_method_t  xicp_methods[] = {
        /* Device interface */
        DEVMETHOD(device_probe,         xicp_probe),
@@ -117,6 +124,7 @@ struct xicp_softc {
                int cpu;
        } intvecs[256];
        int nintvecs;
+       bool xics_emu;
 };
 
 static driver_t xicp_driver = {
@@ -131,6 +139,8 @@ static driver_t xics_driver = {
        0
 };
 
+static uint32_t cpu_xirr[MAXCPU];
+
 static devclass_t xicp_devclass;
 static devclass_t xics_devclass;
 
@@ -161,7 +171,8 @@ static int
 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 +183,8 @@ static int
 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,6 +217,15 @@ xicp_attach(device_t dev)
                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;
@@ -214,18 +235,26 @@ xicp_attach(device_t dev)
        if (mfmsr() & PSL_HV) {
                int i;
 
-               for (i = 0; i < sc->cpu_range[1] - sc->cpu_range[0]; i++) {
-                       sc->mem[i] = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
-                           &i, RF_ACTIVE);
-                       if (sc->mem[i] == NULL) {
-                               device_printf(dev, "Could not alloc mem "
-                                   "resource %d\n", i);
-                               return (ENXIO);
+               if (sc->xics_emu) {
+                       opal_call(OPAL_INT_SET_CPPR, 0xff);
+                       for (i = 0; i < mp_ncpus; i++) {
+                               opal_call(OPAL_INT_SET_MFRR,
+                                   pcpu_find(i)->pc_hwref, 0xff);
                        }
+               } else {
+                       for (i = 0; i < sc->cpu_range[1] - sc->cpu_range[0]; 
i++) {
+                               sc->mem[i] = bus_alloc_resource_any(dev, 
SYS_RES_MEMORY,
+                                   &i, RF_ACTIVE);
+                               if (sc->mem[i] == NULL) {
+                                       device_printf(dev, "Could not alloc mem 
"
+                                           "resource %d\n", i);
+                                       return (ENXIO);
+                               }
 
-                       /* Unmask interrupts on all cores */
-                       bus_write_1(sc->mem[i], 4, 0xff);
-                       bus_write_1(sc->mem[i], 12, 0xff);
+                               /* Unmask interrupts on all cores */
+                               bus_write_1(sc->mem[i], 4, 0xff);
+                               bus_write_1(sc->mem[i], 12, 0xff);
+                       }
                }
        }
 #endif
@@ -316,19 +345,25 @@ xicp_dispatch(device_t dev, struct trapframe *tf)
        uint64_t xirr, junk;
        int i;
 
+       sc = device_get_softc(dev);
 #ifdef POWERNV
-       if (mfmsr() & PSL_HV) {
+       if ((mfmsr() & PSL_HV) && !sc->xics_emu) {
                regs = xicp_mem_for_cpu(PCPU_GET(hwref));
                KASSERT(regs != NULL,
                    ("Can't find regs for CPU %ld", 
(uintptr_t)PCPU_GET(hwref)));
        }
 #endif
 
-       sc = device_get_softc(dev);
        for (;;) {
                /* 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, &cpu_xirr[PCPU_GET(cpuid)],
+                           false);
+                       xirr = cpu_xirr[PCPU_GET(cpuid)];
+#endif
                } else {
                        /* Return value in R4, use the PFT call */
                        phyp_pft_hcall(H_XIRR, 0, 0, 0, 0, &xirr, &junk, &junk);
@@ -338,6 +373,10 @@ xicp_dispatch(device_t dev, struct trapframe *tf)
                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 +387,11 @@ xicp_dispatch(device_t dev, struct trapframe *tf)
                        /* Clear IPI */
                        if (regs)
                                bus_write_1(regs, 12, 0xff);
+#ifdef POWERNV
+                       else if (sc->xics_emu)
+                               opal_call(OPAL_INT_SET_MFRR,
+                                   PCPU_GET(hwref), 0xff);
+#endif
                        else
                                phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(hwref)),
                                    0xff);
@@ -409,6 +453,9 @@ xicp_enable(device_t dev, u_int irq, u_int vector)
 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 +463,13 @@ xicp_eoi(device_t dev, u_int irq)
        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 +479,19 @@ xicp_ipi(device_t dev, u_int cpu)
 {
 
 #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) {
+                       int64_t rv;
+                       rv = opal_call(OPAL_INT_SET_MFRR, cpu, XICP_PRIORITY);
+                       if (rv != 0)
+                           device_printf(dev, "IPI SET_MFRR result: %ld\n", 
rv);
+               } else
+                       bus_write_1(xicp_mem_for_cpu(cpu), 12, XICP_PRIORITY);
+       } else
 #endif
                phyp_hcall(H_IPI, (uint64_t)cpu, XICP_PRIORITY);
 }
@@ -490,3 +549,18 @@ xicp_unmask(device_t dev, u_int irq)
        }
 }
 
+#ifdef POWERNV
+/* This is only used on POWER9 systems with the XIVE's XICS emulation. */
+void
+xicp_smp_cpu_startup(void)
+{
+       struct xicp_softc *sc;
+
+       if (mfmsr() & PSL_HV) {
+               sc = device_get_softc(root_pic);
+
+               if (sc->xics_emu)
+                       opal_call(OPAL_INT_SET_CPPR, 0xff);
+       }
+}
+#endif
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to