diff mbox

[4.4-rc5,v22,4/4] ARM: Allow IPI_CPU_BACKTRACE to exploit FIQ

Message ID 1450644757-18734-5-git-send-email-daniel.thompson@linaro.org (mailing list archive)
State New, archived
Headers show

Commit Message

Daniel Thompson Dec. 20, 2015, 8:52 p.m. UTC
The GIC (v1 & v2) driver allows its implementation of handle_arch_irq()
to be called from the FIQ handler but currently the ARM code is not
able to exploit this.

Extend handle_fiq_as_nmi() to call handle_arch_irq(). This will affect
all interrupt controllers, including ones that do not support FIQ. This
is OK because a spurious FIQ is normally fatal. Handling a spurious FIQ
like a normal interrupt does risk deadlock but does give us a chance
of surviving long enough to get an error message out.

We also extend the SMP code to indicate to irq drivers which IPIs they
should seek to implement using FIQ.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
 arch/arm/include/asm/smp.h | 9 +++++++++
 arch/arm/kernel/smp.c      | 6 ++++++
 arch/arm/kernel/traps.c    | 9 ++++++++-
 3 files changed, 23 insertions(+), 1 deletion(-)

Comments

kernel test robot Dec. 20, 2015, 10:12 p.m. UTC | #1
Hi Daniel,

[auto build test ERROR on v4.4-rc5]
[also build test ERROR on next-20151218]
[cannot apply to tip/irq/core]

url:    https://github.com/0day-ci/linux/commits/Daniel-Thompson/irq-arm-Use-FIQ-for-NMI-backtrace-when-possible/20151221-045854
config: arm-iop-adma (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All errors (new ones prefixed by >>):

   arch/arm/kernel/traps.c: In function 'handle_fiq_as_nmi':
>> arch/arm/kernel/traps.c:489:2: error: implicit declaration of function 'handle_arch_irq' [-Werror=implicit-function-declaration]
     handle_arch_irq(regs);
     ^
   cc1: some warnings being treated as errors

vim +/handle_arch_irq +489 arch/arm/kernel/traps.c

   483		 * Either the interrupt controller supports FIQ, meaning it will
   484		 * do the right thing with this call, or we will end up treating a
   485		 * spurious FIQ (which is normally fatal) as though it were an IRQ
   486		 * which, although it risks deadlock, still gives us a sporting
   487		 * chance of surviving long enough to log errors.
   488		 */
 > 489		handle_arch_irq(regs);
   490	
   491		nmi_exit();
   492	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
kernel test robot Dec. 20, 2015, 10:52 p.m. UTC | #2
Hi Daniel,

[auto build test ERROR on v4.4-rc5]
[also build test ERROR on next-20151218]
[cannot apply to tip/irq/core]

url:    https://github.com/0day-ci/linux/commits/Daniel-Thompson/irq-arm-Use-FIQ-for-NMI-backtrace-when-possible/20151221-045854
config: arm-socfpga_defconfig (attached as .config)
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm 

All error/warnings (new ones prefixed by >>):

   In file included from include/uapi/linux/stddef.h:1:0,
                    from include/linux/stddef.h:4,
                    from include/uapi/linux/posix_types.h:4,
                    from include/uapi/linux/types.h:13,
                    from include/linux/types.h:5,
                    from include/linux/list.h:4,
                    from include/linux/module.h:9,
                    from arch/arm/kernel/smp.c:10:
   arch/arm/kernel/smp.c: In function 'raise_nmi':
>> include/linux/compiler.h:484:38: error: call to '__compiletime_assert_766' declared with attribute error: BUILD_BUG_ON failed: SMP_IPI_FIQ_MASK != BIT(IPI_CPU_BACKTRACE)
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
                                         ^
   include/linux/compiler.h:467:4: note: in definition of macro '__compiletime_assert'
       prefix ## suffix();    \
       ^
   include/linux/compiler.h:484:2: note: in expansion of macro '_compiletime_assert'
     _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
     ^
   include/linux/bug.h:50:37: note: in expansion of macro 'compiletime_assert'
    #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
                                        ^
   include/linux/bug.h:74:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
     BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
     ^
>> arch/arm/kernel/smp.c:766:2: note: in expansion of macro 'BUILD_BUG_ON'
     BUILD_BUG_ON(SMP_IPI_FIQ_MASK != BIT(IPI_CPU_BACKTRACE));
     ^

vim +/__compiletime_assert_766 +484 include/linux/compiler.h

9a8ab1c3 Daniel Santos  2013-02-21  478   *
9a8ab1c3 Daniel Santos  2013-02-21  479   * In tradition of POSIX assert, this macro will break the build if the
9a8ab1c3 Daniel Santos  2013-02-21  480   * supplied condition is *false*, emitting the supplied error message if the
9a8ab1c3 Daniel Santos  2013-02-21  481   * compiler has support to do so.
9a8ab1c3 Daniel Santos  2013-02-21  482   */
9a8ab1c3 Daniel Santos  2013-02-21  483  #define compiletime_assert(condition, msg) \
9a8ab1c3 Daniel Santos  2013-02-21 @484  	_compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
9a8ab1c3 Daniel Santos  2013-02-21  485  
47933ad4 Peter Zijlstra 2013-11-06  486  #define compiletime_assert_atomic_type(t)				\
47933ad4 Peter Zijlstra 2013-11-06  487  	compiletime_assert(__native_word(t),				\

:::::: The code at line 484 was first introduced by commit
:::::: 9a8ab1c39970a4938a72d94e6fd13be88a797590 bug.h, compiler.h: introduce compiletime_assert & BUILD_BUG_ON_MSG

:::::: TO: Daniel Santos <daniel.santos@pobox.com>
:::::: CC: Linus Torvalds <torvalds@linux-foundation.org>

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Daniel Thompson Jan. 4, 2016, 10 a.m. UTC | #3
On 20/12/15 22:12, kbuild test robot wrote:
> Hi Daniel,
>
> [auto build test ERROR on v4.4-rc5]
> [also build test ERROR on next-20151218]
> [cannot apply to tip/irq/core]
>
> url:    https://github.com/0day-ci/linux/commits/Daniel-Thompson/irq-arm-Use-FIQ-for-NMI-backtrace-when-possible/20151221-045854
> config: arm-iop-adma (attached as .config)
> reproduce:
>          wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
>          chmod +x ~/bin/make.cross
>          # save the attached .config to linux build tree
>          make.cross ARCH=arm
>
> All errors (new ones prefixed by >>):
>
>     arch/arm/kernel/traps.c: In function 'handle_fiq_as_nmi':
>>> arch/arm/kernel/traps.c:489:2: error: implicit declaration of function 'handle_arch_irq' [-Werror=implicit-function-declaration]
>       handle_arch_irq(regs);
>       ^
>     cc1: some warnings being treated as errors

Thanks. I'll look at this.


> vim +/handle_arch_irq +489 arch/arm/kernel/traps.c
>
>     483		 * Either the interrupt controller supports FIQ, meaning it will
>     484		 * do the right thing with this call, or we will end up treating a
>     485		 * spurious FIQ (which is normally fatal) as though it were an IRQ
>     486		 * which, although it risks deadlock, still gives us a sporting
>     487		 * chance of surviving long enough to log errors.
>     488		 */
>   > 489		handle_arch_irq(regs);
>     490	
>     491		nmi_exit();
>     492	
>
> ---
> 0-DAY kernel test infrastructure                Open Source Technology Center
> https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
>
Daniel Thompson Jan. 4, 2016, 10:05 a.m. UTC | #4
On 20/12/15 22:52, kbuild test robot wrote:
> Hi Daniel,
>
> [auto build test ERROR on v4.4-rc5]
> [also build test ERROR on next-20151218]
> [cannot apply to tip/irq/core]
>
> url:    https://github.com/0day-ci/linux/commits/Daniel-Thompson/irq-arm-Use-FIQ-for-NMI-backtrace-when-possible/20151221-045854
> config: arm-socfpga_defconfig (attached as .config)
> reproduce:
>          wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
>          chmod +x ~/bin/make.cross
>          # save the attached .config to linux build tree
>          make.cross ARCH=arm
>
> All error/warnings (new ones prefixed by >>):
>
>     In file included from include/uapi/linux/stddef.h:1:0,
>                      from include/linux/stddef.h:4,
>                      from include/uapi/linux/posix_types.h:4,
>                      from include/uapi/linux/types.h:13,
>                      from include/linux/types.h:5,
>                      from include/linux/list.h:4,
>                      from include/linux/module.h:9,
>                      from arch/arm/kernel/smp.c:10:
>     arch/arm/kernel/smp.c: In function 'raise_nmi':
>>> include/linux/compiler.h:484:38: error: call to '__compiletime_assert_766' declared with attribute error: BUILD_BUG_ON failed: SMP_IPI_FIQ_MASK != BIT(IPI_CPU_BACKTRACE)
>       _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
>                                           ^
>     include/linux/compiler.h:467:4: note: in definition of macro '__compiletime_assert'
>         prefix ## suffix();    \
>         ^
>     include/linux/compiler.h:484:2: note: in expansion of macro '_compiletime_assert'
>       _compiletime_assert(condition, msg, __compiletime_assert_, __LINE__)
>       ^
>     include/linux/bug.h:50:37: note: in expansion of macro 'compiletime_assert'
>      #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
>                                          ^
>     include/linux/bug.h:74:2: note: in expansion of macro 'BUILD_BUG_ON_MSG'
>       BUILD_BUG_ON_MSG(condition, "BUILD_BUG_ON failed: " #condition)
>       ^
>>> arch/arm/kernel/smp.c:766:2: note: in expansion of macro 'BUILD_BUG_ON'
>       BUILD_BUG_ON(SMP_IPI_FIQ_MASK != BIT(IPI_CPU_BACKTRACE));

This should be a false alarm or at least, the BUILD_BUG_ON() is doing 
exactly what it was intended to.

I forgot to mention it in the covering letter (and will fix next time) 
but my patchset requires a fix from Marc Zyngier which changes the 
numeric value of IPI_CPU_BACKTRACE[1].


Daniel.

1: http://thread.gmane.org/gmane.linux.ports.arm.kernel/464985
diff mbox

Patch

diff --git a/arch/arm/include/asm/smp.h b/arch/arm/include/asm/smp.h
index 3d6dc8b460e4..daf869cff02e 100644
--- a/arch/arm/include/asm/smp.h
+++ b/arch/arm/include/asm/smp.h
@@ -18,6 +18,15 @@ 
 # error "<asm/smp.h> included in non-SMP build"
 #endif
 
+/*
+ * Identify which IPIs are safe for the irqchip to handle using FIQ.
+ *
+ * This information is advisory. The interrupt controller may not be capable
+ * of routing these IPIs to FIQ and the kernel will continue to work if they
+ * are routed to IRQ as normal.
+ */
+#define SMP_IPI_FIQ_MASK 0x80
+
 #define raw_smp_processor_id() (current_thread_info()->cpu)
 
 struct seq_file;
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index fe517f1e88d8..853089e1aa8a 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -639,6 +639,11 @@  void handle_IPI(int ipinr, struct pt_regs *regs)
 		break;
 
 	case IPI_CPU_BACKTRACE:
+		if (in_nmi()) {
+			nmi_cpu_backtrace(regs);
+			break;
+		}
+
 		irq_enter();
 		nmi_cpu_backtrace(regs);
 		irq_exit();
@@ -750,6 +755,7 @@  static void raise_nmi(cpumask_t *mask)
 	if (cpumask_test_cpu(smp_processor_id(), mask) && irqs_disabled())
 		nmi_cpu_backtrace(NULL);
 
+	BUILD_BUG_ON(SMP_IPI_FIQ_MASK != BIT(IPI_CPU_BACKTRACE));
 	smp_cross_call(mask, IPI_CPU_BACKTRACE);
 }
 
diff --git a/arch/arm/kernel/traps.c b/arch/arm/kernel/traps.c
index bc698383e822..a04426ee7684 100644
--- a/arch/arm/kernel/traps.c
+++ b/arch/arm/kernel/traps.c
@@ -479,7 +479,14 @@  asmlinkage void __exception_irq_entry handle_fiq_as_nmi(struct pt_regs *regs)
 
 	nmi_enter();
 
-	/* nop. FIQ handlers for special arch/arm features can be added here. */
+	/*
+	 * Either the interrupt controller supports FIQ, meaning it will
+	 * do the right thing with this call, or we will end up treating a
+	 * spurious FIQ (which is normally fatal) as though it were an IRQ
+	 * which, although it risks deadlock, still gives us a sporting
+	 * chance of surviving long enough to log errors.
+	 */
+	handle_arch_irq(regs);
 
 	nmi_exit();