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 PR# port-evbarm/49468: Cortex GIC assert...



details:   https://anonhg.NetBSD.org/src/rev/ecbb1695b911
branches:  trunk
changeset: 829652:ecbb1695b911
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Wed Feb 07 20:42:17 2018 +0000

description:
PR# port-evbarm/49468: Cortex GIC assertion triggered on Allwinner A80 SoC

The priority level is changed by writing to GICC_PMR with interrupts
disabled. However, interrupts are enabled/disabled downstream of the GICC
at the CPU. When raising priority level, there is a window between the time
that interrupts are disabled and the GICC_PMR register is written. If an
interrupt occurs at a previously allowed priority before GICC_PMR is
changed, the CPU will receive the signal when interrupts are re-enabled.
At this time, GICC_PMR is now the new priority level, so reads of
GICC_IAR will report a spurious IRQ.

Move the "old_ipl != IPL_HIGH" test until after we have confirmed that
there is at least one pending IRQ.

diffstat:

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

diffs (46 lines):

diff -r 232be56eb79c -r ecbb1695b911 sys/arch/arm/cortex/gic.c
--- a/sys/arch/arm/cortex/gic.c Wed Feb 07 15:55:58 2018 +0000
+++ b/sys/arch/arm/cortex/gic.c Wed Feb 07 20:42:17 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gic.c,v 1.31 2017/07/14 06:33:26 skrll Exp $   */
+/*     $NetBSD: gic.c,v 1.32 2018/02/07 20:42:17 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.31 2017/07/14 06:33:26 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.32 2018/02/07 20:42:17 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -259,9 +259,6 @@
 
        ci->ci_data.cpu_nintr++;
 
-       KASSERTMSG(old_ipl != IPL_HIGH, "old_ipl %d pmr %#x hppir %#x",
-           old_ipl, gicc_read(sc, GICC_PMR), gicc_read(sc, GICC_HPPIR));
-
        for (;;) {
                uint32_t iar = gicc_read(sc, GICC_IAR);
                uint32_t irq = __SHIFTOUT(iar, GICC_IAR_IRQ);
@@ -277,6 +274,9 @@
                        }
                }
 
+               KASSERTMSG(old_ipl != IPL_HIGH, "old_ipl %d pmr %#x hppir %#x",
+                   old_ipl, gicc_read(sc, GICC_PMR), gicc_read(sc, GICC_HPPIR));
+
                //const uint32_t cpuid = __SHIFTOUT(iar, GICC_IAR_CPUID_MASK);
                struct intrsource * const is = sc->sc_pic.pic_sources[irq];
                KASSERT(is != &armgic_dummy_source);
@@ -318,7 +318,6 @@
        /*
         * Now handle any pending ints.
         */
-       KASSERT(old_ipl != IPL_HIGH);
        pic_do_pending_ints(I32_bit, old_ipl, tf);
        KASSERTMSG(ci->ci_cpl == old_ipl, "ci_cpl %d old_ipl %d", ci->ci_cpl, old_ipl);
        KASSERT(old_mtx_count == ci->ci_mtx_count);



Home | Main Index | Thread Index | Old Index