Module Name: src Committed By: jmcneill Date: Sun Jul 15 16:04:07 UTC 2018
Modified Files: src/sys/arch/arm/cortex: gic.c Log Message: Support pic_set_affinity and pic_get_affinity To generate a diff of this commit: cvs rdiff -u -r1.34 -r1.35 src/sys/arch/arm/cortex/gic.c 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/gic.c diff -u src/sys/arch/arm/cortex/gic.c:1.34 src/sys/arch/arm/cortex/gic.c:1.35 --- src/sys/arch/arm/cortex/gic.c:1.34 Sat Apr 28 18:26:53 2018 +++ src/sys/arch/arm/cortex/gic.c Sun Jul 15 16:04:07 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: gic.c,v 1.34 2018/04/28 18:26:53 jakllsch Exp $ */ +/* $NetBSD: gic.c,v 1.35 2018/07/15 16:04:07 jmcneill Exp $ */ /*- * Copyright (c) 2012 The NetBSD Foundation, Inc. * All rights reserved. @@ -34,7 +34,7 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.34 2018/04/28 18:26:53 jakllsch Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.35 2018/07/15 16:04:07 jmcneill Exp $"); #include <sys/param.h> #include <sys/bus.h> @@ -75,6 +75,8 @@ static void armgic_source_name(struct pi #ifdef MULTIPROCESSOR static void armgic_cpu_init(struct pic_softc *, struct cpu_info *); static void armgic_ipi_send(struct pic_softc *, const kcpuset_t *, u_long); +static void armgic_get_affinity(struct pic_softc *, size_t, kcpuset_t *); +static int armgic_set_affinity(struct pic_softc *, size_t, const kcpuset_t *); #endif static const struct pic_ops armgic_picops = { @@ -88,6 +90,8 @@ static const struct pic_ops armgic_picop #ifdef MULTIPROCESSOR .pic_cpu_init = armgic_cpu_init, .pic_ipi_send = armgic_ipi_send, + .pic_get_affinity = armgic_get_affinity, + .pic_set_affinity = armgic_set_affinity, #endif }; @@ -104,6 +108,7 @@ static struct armgic_softc { uint32_t sc_gic_valid_lines[1024/32]; uint32_t sc_enabled_local; #ifdef MULTIPROCESSOR + uint32_t sc_target[MAXCPUS]; uint32_t sc_mptargets; #endif uint32_t sc_bptargets; @@ -222,6 +227,63 @@ armgic_set_priority(struct pic_softc *pi gicc_write(sc, GICC_PMR, priority); } +#ifdef MULTIPROCESSOR +static void +armgic_get_affinity(struct pic_softc *pic, size_t irq, kcpuset_t *affinity) +{ + struct armgic_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 < MAXCPUS; n++) { + if (sc->sc_target[n] != 0) + kcpuset_set(affinity, n); + } + } else { + /* Find distributor targets (SPI) */ + const u_int byte_shift = 8 * (irq & 3); + const bus_size_t targets_reg = GICD_ITARGETSRn(irq / 4); + const uint32_t targets = gicd_read(sc, targets_reg); + const uint32_t targets_val = (targets >> byte_shift) & 0xff; + + for (n = 0; n < MAXCPUS; n++) { + if (sc->sc_target[n] & targets_val) + kcpuset_set(affinity, n); + } + } +} + +static int +armgic_set_affinity(struct pic_softc *pic, size_t irq, + const kcpuset_t *affinity) +{ + struct armgic_softc * const sc = PICTOSOFTC(pic); + const size_t group = irq / 32; + if (group == 0) + return EINVAL; + + const u_int byte_shift = 8 * (irq & 3); + const bus_size_t targets_reg = GICD_ITARGETSRn(irq / 4); + uint32_t targets_val = 0; + int n; + + for (n = 0; n < MAXCPUS; n++) { + if (kcpuset_isset(affinity, n)) + targets_val |= sc->sc_target[n]; + } + + uint32_t targets = gicd_read(sc, targets_reg); + targets &= ~(0xff << byte_shift); + targets |= (targets_val << byte_shift); + gicd_write(sc, targets_reg, targets); + + return 0; +} +#endif + #ifdef __HAVE_PIC_FAST_SOFTINTS void softint_init_md(lwp_t *l, u_int level, uintptr_t *machdep_p) @@ -451,7 +513,8 @@ void armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci) { struct armgic_softc * const sc = PICTOSOFTC(pic); - sc->sc_mptargets |= gicd_find_targets(sc); + sc->sc_target[cpu_index(ci)] = gicd_find_targets(sc); + sc->sc_mptargets |= sc->sc_target[cpu_index(ci)]; KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl); armgic_cpu_init_priorities(sc); if (!CPU_IS_PRIMARY(ci)) {