Skip to content

Commit 0f1ac8f

Browse files
Steven Rostedtrostedt
authored andcommitted
tracing/lockdep: Disable lockdep first in entering NMI
When function tracing with either debug locks enabled or tracing preempt disabled, the add_preempt_count() is traced. This is an issue with lockdep and function tracing. As function tracing can disable interrupts, and lockdep records that change, lockdep may not be able to handle this recursion if it happens from an NMI context. The first thing that an NMI does is: #define nmi_enter() \ do { \ ftrace_nmi_enter(); \ BUG_ON(in_nmi()); \ add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \ lockdep_off(); \ rcu_nmi_enter(); \ trace_hardirq_enter(); \ } while (0) When the add_preempt_count() is traced, and the tracing callback disables interrupts, it will jump into the lockdep code. There's some places in lockdep that can't handle this re-entrance, and causes lockdep to fail. As the lockdep_off() (and lockdep_on) is a simple: void lockdep_off(void) { current->lockdep_recursion++; } and is never traced, it can be called first in nmi_enter() and lockdep_on() last in nmi_exit(). Cc: Peter Zijlstra <[email protected]> Signed-off-by: Steven Rostedt <[email protected]>
1 parent 84c6cf0 commit 0f1ac8f

File tree

1 file changed

+2
-2
lines changed

1 file changed

+2
-2
lines changed

include/linux/hardirq.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -180,10 +180,10 @@ extern void irq_exit(void);
180180

181181
#define nmi_enter() \
182182
do { \
183+
lockdep_off(); \
183184
ftrace_nmi_enter(); \
184185
BUG_ON(in_nmi()); \
185186
add_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
186-
lockdep_off(); \
187187
rcu_nmi_enter(); \
188188
trace_hardirq_enter(); \
189189
} while (0)
@@ -192,10 +192,10 @@ extern void irq_exit(void);
192192
do { \
193193
trace_hardirq_exit(); \
194194
rcu_nmi_exit(); \
195-
lockdep_on(); \
196195
BUG_ON(!in_nmi()); \
197196
sub_preempt_count(NMI_OFFSET + HARDIRQ_OFFSET); \
198197
ftrace_nmi_exit(); \
198+
lockdep_on(); \
199199
} while (0)
200200

201201
#endif /* LINUX_HARDIRQ_H */

0 commit comments

Comments
 (0)