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 Don't assume that CPU index = GIC CPU in...



details:   https://anonhg.NetBSD.org/src/rev/b8cd3a795dec
branches:  trunk
changeset: 824795:b8cd3a795dec
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Sun Jun 18 22:11:50 2017 +0000

description:
Don't assume that CPU index = GIC CPU interface number. We can determine
the current CPU interface number by reading from the read-only
GICD_ITARGETSR0 through GICD_ITARGETSR7 registers.

This gets interrupts working on Exynos 5422, where the boot processor has
GIC CPU interface #4.

diffstat:

 sys/arch/arm/cortex/gic.c |  39 ++++++++++++++++++++++++++++++++++-----
 1 files changed, 34 insertions(+), 5 deletions(-)

diffs (91 lines):

diff -r 57ae17476800 -r b8cd3a795dec sys/arch/arm/cortex/gic.c
--- a/sys/arch/arm/cortex/gic.c Sun Jun 18 20:24:59 2017 +0000
+++ b/sys/arch/arm/cortex/gic.c Sun Jun 18 22:11:50 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gic.c,v 1.23 2017/06/05 20:02:11 skrll Exp $   */
+/*     $NetBSD: gic.c,v 1.24 2017/06/18 22:11:50 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.23 2017/06/05 20:02:11 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.24 2017/06/18 22:11:50 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -100,6 +100,7 @@
 #ifdef MULTIPROCESSOR
        uint32_t sc_mptargets;
 #endif
+       uint32_t sc_bptargets;
 } armgic_softc = {
        .sc_pic = {
                .pic_ops = &armgic_picops,
@@ -139,6 +140,29 @@
        bus_space_write_4(sc->sc_memt, sc->sc_gicdh, o, v);
 }
 
+static uint32_t
+gicd_find_targets(struct armgic_softc *sc)
+{
+       uint32_t targets = 0;
+
+       /*
+        * GICD_ITARGETSR0 through 7 are read-only, and each field returns
+        * a value that corresponds only to the processor reading the
+        * register. Use this to determine the current processor's
+        * CPU interface number.
+        */
+       for (int i = 0; i < 8; i++) {
+               targets = gicd_read(sc, GICD_ITARGETSRn(i));
+               if (targets != 0)
+                       break;
+       }
+       targets |= (targets >> 16);
+       targets |= (targets >> 8);
+       targets &= 0xff;
+
+       return targets ? targets : 1;
+}
+
 /*
  * In the GIC prioritization scheme, lower numbers have higher priority.
  * Only write priorities that could be non-secure.
@@ -326,7 +350,7 @@
                } else
 #endif
 #endif
-               targets |= 1 << byte_shift;
+               targets |= sc->sc_bptargets << byte_shift;
                gicd_write(sc, targets_reg, targets);
 
                /*
@@ -417,11 +441,11 @@
 armgic_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
 {
        struct armgic_softc * const sc = PICTOSOFTC(pic);
-       sc->sc_mptargets |= 1 << cpu_index(ci);
+       sc->sc_mptargets |= gicd_find_targets(sc);
        KASSERTMSG(ci->ci_cpl == IPL_HIGH, "ipl %d not IPL_HIGH", ci->ci_cpl);
        armgic_cpu_init_priorities(sc);
        if (!CPU_IS_PRIMARY(ci)) {
-               if (sc->sc_mptargets != 1) {
+               if (popcount(sc->sc_mptargets) != 1) {
                        armgic_cpu_init_targets(sc);
                }
                if (sc->sc_enabled_local) {
@@ -502,6 +526,11 @@
        u_int priorities = 1 << popcount32(pmr);
 
        /*
+        * Find the boot processor's CPU interface number.
+        */
+       sc->sc_bptargets = gicd_find_targets(sc);
+
+       /*
         * Let's find out how many real sources we have.
         */
        for (size_t i = 0, group = 0;



Home | Main Index | Thread Index | Old Index