Module Name:    src
Committed By:   jmcneill
Date:           Wed Feb  7 20:42:17 UTC 2018

Modified Files:
        src/sys/arch/arm/cortex: gic.c

Log Message:
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.


To generate a diff of this commit:
cvs rdiff -u -r1.31 -r1.32 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.31 src/sys/arch/arm/cortex/gic.c:1.32
--- src/sys/arch/arm/cortex/gic.c:1.31	Fri Jul 14 06:33:26 2017
+++ src/sys/arch/arm/cortex/gic.c	Wed Feb  7 20:42:17 2018
@@ -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 @@ armgic_irq_handler(void *tf)
 
 	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 @@ armgic_irq_handler(void *tf)
 			}
 		}
 
+		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 @@ armgic_irq_handler(void *tf)
 	/*
 	 * 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);

Reply via email to