svn commit: r333912 - in head/sys/powerpc: aim include powernv powerpc pseries

Justin Hibbits jhibbits at FreeBSD.org
Sun May 20 03:23:20 UTC 2018


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


More information about the svn-src-head mailing list