Module Name:    src
Committed By:   jmcneill
Date:           Sat Nov 10 01:56:28 UTC 2018

Modified Files:
        src/sys/arch/arm/cortex: gicv3.c gicv3.h

Log Message:
Implement pic_get_affinity/pic_set_affinity for SPIs


To generate a diff of this commit:
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/arm/cortex/gicv3.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/arm/cortex/gicv3.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/arm/cortex/gicv3.c
diff -u src/sys/arch/arm/cortex/gicv3.c:1.5 src/sys/arch/arm/cortex/gicv3.c:1.6
--- src/sys/arch/arm/cortex/gicv3.c:1.5	Fri Nov  9 23:36:24 2018
+++ src/sys/arch/arm/cortex/gicv3.c	Sat Nov 10 01:56:28 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: gicv3.c,v 1.5 2018/11/09 23:36:24 jmcneill Exp $ */
+/* $NetBSD: gicv3.c,v 1.6 2018/11/10 01:56:28 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca>
@@ -31,7 +31,7 @@
 #define	_INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.5 2018/11/09 23:36:24 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gicv3.c,v 1.6 2018/11/10 01:56:28 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/kernel.h>
@@ -68,6 +68,12 @@ gicd_write_4(struct gicv3_softc *sc, bus
 	bus_space_write_4(sc->sc_bst, sc->sc_bsh_d, reg, val);
 }
 
+static inline uint64_t
+gicd_read_8(struct gicv3_softc *sc, bus_size_t reg)
+{
+	return bus_space_read_8(sc->sc_bst, sc->sc_bsh_d, reg);
+}
+
 static inline void
 gicd_write_8(struct gicv3_softc *sc, bus_size_t reg, uint64_t val)
 {
@@ -177,7 +183,7 @@ gicv3_establish_irq(struct pic_softc *pi
 			irouter = GICD_IROUTER_Interrupt_Routing_mode;
 		} else {
 			/* Route non-MP-safe interrupts to the primary PE only */
-			irouter = sc->sc_default_irouter;
+			irouter = sc->sc_irouter[0];
 		}
 		gicd_write_8(sc, GICD_IROUTER(is->is_irq), irouter);
 
@@ -365,19 +371,17 @@ gicv3_cpu_init(struct pic_softc *pic, st
 	ci->ci_gic_redist = gicv3_find_redist(sc);
 	ci->ci_gic_sgir = gicv3_sgir(sc);
 
-	if (CPU_IS_PRIMARY(ci)) {
-		/* Store route to primary CPU for non-MPSAFE SPIs */
-		const uint64_t cpu_identity = gicv3_cpu_identity();
-		const u_int aff0 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff0);
-		const u_int aff1 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff1);
-		const u_int aff2 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff2);
-		const u_int aff3 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff3);
-		sc->sc_default_irouter =
-		    __SHIFTIN(aff0, GICD_IROUTER_Aff0) |
-		    __SHIFTIN(aff1, GICD_IROUTER_Aff1) |
-		    __SHIFTIN(aff2, GICD_IROUTER_Aff2) |
-		    __SHIFTIN(aff3, GICD_IROUTER_Aff3);
-	}
+	/* Store route to CPU for SPIs */
+	const uint64_t cpu_identity = gicv3_cpu_identity();
+	const u_int aff0 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff0);
+	const u_int aff1 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff1);
+	const u_int aff2 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff2);
+	const u_int aff3 = __SHIFTOUT(cpu_identity, GICR_TYPER_Affinity_Value_Aff3);
+	sc->sc_irouter[cpu_index(ci)] =
+	    __SHIFTIN(aff0, GICD_IROUTER_Aff0) |
+	    __SHIFTIN(aff1, GICD_IROUTER_Aff1) |
+	    __SHIFTIN(aff2, GICD_IROUTER_Aff2) |
+	    __SHIFTIN(aff3, GICD_IROUTER_Aff3);
 
 	/* Enable System register access and disable IRQ/FIQ bypass */
 	icc_sre = ICC_SRE_EL1_SRE | ICC_SRE_EL1_DFB | ICC_SRE_EL1_DIB;
@@ -446,6 +450,54 @@ gicv3_ipi_send(struct pic_softc *pic, co
 			icc_sgi1r_write(intid | aff | targets);
 	}
 }
+
+static void
+gicv3_get_affinity(struct pic_softc *pic, size_t irq, kcpuset_t *affinity)
+{
+	struct gicv3_softc * const sc = PICTOSOFTC(pic);
+	const size_t group = irq / 32;
+	int n;
+
+	kcpuset_zero(affinity);
+	if (group == 0) {
+		/* All CPUs are targets for group 0 (SGI/PPI) */
+		for (n = 0; n < ncpu; n++) {
+			if (sc->sc_irouter[n] != UINT64_MAX)
+				kcpuset_set(affinity, n);
+		}
+	} else {
+		/* Find distributor targets (SPI) */
+		const uint64_t irouter = gicd_read_8(sc, GICD_IROUTER(irq));
+		for (n = 0; n < ncpu; n++) {
+			if (irouter == GICD_IROUTER_Interrupt_Routing_mode ||
+			    irouter == sc->sc_irouter[n])
+				kcpuset_set(affinity, n);
+		}
+	}
+}
+
+static int
+gicv3_set_affinity(struct pic_softc *pic, size_t irq, const kcpuset_t *affinity)
+{
+	struct gicv3_softc * const sc = PICTOSOFTC(pic);
+	const size_t group = irq / 32;
+	uint64_t irouter;
+
+	if (group == 0)
+		return EINVAL;
+
+	const int set = kcpuset_countset(affinity);
+	if (set == ncpu)
+		irouter = GICD_IROUTER_Interrupt_Routing_mode;
+	else if (set == 1)
+		irouter = sc->sc_irouter[kcpuset_ffs(affinity)];
+	else
+		return EINVAL;
+
+	gicd_write_8(sc, GICD_IROUTER(irq), irouter);
+
+	return 0;
+}
 #endif
 
 static const struct pic_ops gicv3_picops = {
@@ -456,6 +508,8 @@ static const struct pic_ops gicv3_picops
 #ifdef MULTIPROCESSOR
 	.pic_cpu_init = gicv3_cpu_init,
 	.pic_ipi_send = gicv3_ipi_send,
+	.pic_get_affinity = gicv3_get_affinity,
+	.pic_set_affinity = gicv3_set_affinity,
 #endif
 };
 
@@ -637,11 +691,15 @@ int
 gicv3_init(struct gicv3_softc *sc)
 {
 	const uint32_t gicd_typer = gicd_read_4(sc, GICD_TYPER);
+	int n;
 
 	KASSERT(CPU_IS_PRIMARY(curcpu()));
 
 	LIST_INIT(&sc->sc_cpu_init);
 
+	for (n = 0; n < MAXCPUS; n++)
+		sc->sc_irouter[n] = UINT64_MAX;
+
 	sc->sc_pic.pic_ops = &gicv3_picops;
 	sc->sc_pic.pic_maxsources = GICD_TYPER_LINES(gicd_typer);
 	snprintf(sc->sc_pic.pic_name, sizeof(sc->sc_pic.pic_name), "gicv3");

Index: src/sys/arch/arm/cortex/gicv3.h
diff -u src/sys/arch/arm/cortex/gicv3.h:1.2 src/sys/arch/arm/cortex/gicv3.h:1.3
--- src/sys/arch/arm/cortex/gicv3.h:1.2	Fri Nov  9 23:36:24 2018
+++ src/sys/arch/arm/cortex/gicv3.h	Sat Nov 10 01:56:28 2018
@@ -1,4 +1,4 @@
-/* $NetBSD: gicv3.h,v 1.2 2018/11/09 23:36:24 jmcneill Exp $ */
+/* $NetBSD: gicv3.h,v 1.3 2018/11/10 01:56:28 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2018 Jared McNeill <jmcne...@invisible.ca>
@@ -58,7 +58,7 @@ struct gicv3_softc {
 	u_int			sc_bsh_r_count;
 
 	uint32_t		sc_enabled_sgippi;
-	uint64_t		sc_default_irouter;
+	uint64_t		sc_irouter[MAXCPUS];
 
 	/* LPI configuration table */
 	struct gicv3_dma	sc_lpiconf;

Reply via email to