Skip to content

Commit f93524e

Browse files
Peter ZijlstraKAGA-KOKO
authored andcommitted
sched,rcu,tracing: Avoid tracing before in_nmi() is correct
If a tracer is invoked before in_nmi() becomes true, the tracer can no longer detect it is called from NMI context and behave correctly. Therefore change nmi_{enter,exit}() to use __preempt_count_{add,sub}() as the normal preempt_count_{add,sub}() have a (desired) function trace entry. This fixes a potential issue with the current code; when the function-tracer has stack-tracing enabled __trace_stack() will malfunction when it hits the preempt_count_add() function entry from NMI context. Suggested-by: Steven Rostedt (VMware) <[email protected]> Signed-off-by: Peter Zijlstra (Intel) <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Reviewed-by: Steven Rostedt (VMware) <[email protected]> Reviewed-by: Alexandre Chartre <[email protected]> Link: https://lkml.kernel.org/r/[email protected]
1 parent 178ba00 commit f93524e

File tree

1 file changed

+11
-2
lines changed

1 file changed

+11
-2
lines changed

include/linux/hardirq.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,15 @@ extern void irq_exit(void);
6565
#define arch_nmi_exit() do { } while (0)
6666
#endif
6767

68+
/*
69+
* NMI vs Tracing
70+
* --------------
71+
*
72+
* We must not land in a tracer until (or after) we've changed preempt_count
73+
* such that in_nmi() becomes true. To that effect all NMI C entry points must
74+
* be marked 'notrace' and call nmi_enter() as soon as possible.
75+
*/
76+
6877
/*
6978
* nmi_enter() can nest up to 15 times; see NMI_BITS.
7079
*/
@@ -75,7 +84,7 @@ extern void irq_exit(void);
7584
lockdep_off(); \
7685
ftrace_nmi_enter(); \
7786
BUG_ON(in_nmi() == NMI_MASK); \
78-
preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \
87+
__preempt_count_add(NMI_OFFSET + HARDIRQ_OFFSET); \
7988
rcu_nmi_enter(); \
8089
lockdep_hardirq_enter(); \
8190
} while (0)
@@ -85,7 +94,7 @@ extern void irq_exit(void);
8594
lockdep_hardirq_exit(); \
8695
rcu_nmi_exit(); \
8796
BUG_ON(!in_nmi()); \
88-
preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \
97+
__preempt_count_sub(NMI_OFFSET + HARDIRQ_OFFSET); \
8998
ftrace_nmi_exit(); \
9099
lockdep_on(); \
91100
printk_nmi_exit(); \

0 commit comments

Comments
 (0)