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);