Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/arm/cortex Implement pic_get_affinity/pic_set_affin...



details:   https://anonhg.NetBSD.org/src/rev/b6631202406f
branches:  trunk
changeset: 836865:b6631202406f
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sat Nov 10 01:56:28 2018 +0000

description:
Implement pic_get_affinity/pic_set_affinity for SPIs

diffstat:

 sys/arch/arm/cortex/gicv3.c |  90 +++++++++++++++++++++++++++++++++++++--------
 sys/arch/arm/cortex/gicv3.h |   4 +-
 2 files changed, 76 insertions(+), 18 deletions(-)

diffs (169 lines):

diff -r f3706ec812cc -r b6631202406f sys/arch/arm/cortex/gicv3.c
--- a/sys/arch/arm/cortex/gicv3.c       Sat Nov 10 01:44:26 2018 +0000
+++ b/sys/arch/arm/cortex/gicv3.c       Sat Nov 10 01:56:28 2018 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -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 @@
        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 @@
                        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 @@
        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 @@
                        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 @@
 #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 @@
 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");
diff -r f3706ec812cc -r b6631202406f sys/arch/arm/cortex/gicv3.h
--- a/sys/arch/arm/cortex/gicv3.h       Sat Nov 10 01:44:26 2018 +0000
+++ b/sys/arch/arm/cortex/gicv3.h       Sat Nov 10 01:56:28 2018 +0000
@@ -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 <jmcneill%invisible.ca@localhost>
@@ -58,7 +58,7 @@
        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;



Home | Main Index | Thread Index | Old Index