[PATCH v2 3/3] ARM: vfp: Fix broken softirq handling with instrumentation enabled

Peter Zijlstra peterz at infradead.org
Tue Mar 14 14:45:59 PDT 2023


On Tue, Mar 14, 2023 at 09:46:21PM +0100, Linus Walleij wrote:
> Hi Ard,
> 
> On Tue, Mar 14, 2023 at 8:28 PM Ard Biesheuvel <ardb at kernel.org> wrote:
> 
> > Commit 62b95a7b44d1 ("ARM: 9282/1: vfp: Manipulate task VFP state with
> > softirqs disabled") replaced the en/disable preemption calls inside the
> > VFP state handling code with en/disabling of soft IRQs, which is
> > necessary to allow kernel use of the VFP/SIMD unit when handling a soft
> > IRQ.
> >
> > Unfortunately, when lockdep is enabled (or other instrumentation that
> > enables TRACE_IRQFLAGS), the disable path implemented in asm fails to
> > perform the lockdep and RCU related bookkeeping, resulting in spurious
> > warnings and other badness.
> 
> Not good.
> 
> > Set let's rework the VFP entry code a little bit so we can make the
> > local_bh_disable() call from C, with all the instrumentations that
> > happen to have been configured. Calling local_bh_enable() can be done
> > from asm, as it is always a callable function.
> 
> Here it says local_bh_enable() is called
> 
> (...)
> 
> > +local_bh_enable_and_ret:
> > +       adr     r0, .
> > +       mov     r1, #SOFTIRQ_DISABLE_OFFSET
> > +       b       __local_bh_enable_ip    @ tail call
> 
> Please add a comment here that this is an open coded version of
> local_bh_enable() from the <linux/bottom_half.h> header file
> and we hope that inline code will not change.
> 
> I.e this:
> 
> static inline void local_bh_enable(void)
> {
>         __local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
> }
> 
> I almost want to make a warning comment into <linux/bottom_half.h>
> that the same function exists in an open coded version in arch/arm/vfp/vfphw.S
> so this static inline cannot be refactored without consequences.

So we could do something like the below to make local_bh_enable() both
an inline and an actual symbol for those who need to call it from asm.

It seems to compile on both GCC-12 and Clang-15.

diff --git a/include/linux/bottom_half.h b/include/linux/bottom_half.h
index fc53e0ad56d9..85fcdf647f9f 100644
--- a/include/linux/bottom_half.h
+++ b/include/linux/bottom_half.h
@@ -28,7 +28,7 @@ static inline void local_bh_enable_ip(unsigned long ip)
 	__local_bh_enable_ip(ip, SOFTIRQ_DISABLE_OFFSET);
 }
 
-static inline void local_bh_enable(void)
+extern inline void local_bh_enable(void)
 {
 	__local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
 }
diff --git a/kernel/softirq.c b/kernel/softirq.c
index c8a6913c067d..91d8677f890a 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -1010,3 +1010,8 @@ unsigned int __weak arch_dynirq_lower_bound(unsigned int from)
 {
 	return from;
 }
+
+void local_bh_enable(void)
+{
+	__local_bh_enable_ip(_THIS_IP_, SOFTIRQ_DISABLE_OFFSET);
+}



More information about the linux-arm-kernel mailing list