diff options
Diffstat (limited to 'kernel/trace/trace_stack.c')
-rw-r--r-- | kernel/trace/trace_stack.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c index b746399ab59c..8abf1ba18085 100644 --- a/kernel/trace/trace_stack.c +++ b/kernel/trace/trace_stack.c | |||
@@ -85,9 +85,19 @@ check_stack(unsigned long ip, unsigned long *stack) | |||
85 | if (!object_is_on_stack(stack)) | 85 | if (!object_is_on_stack(stack)) |
86 | return; | 86 | return; |
87 | 87 | ||
88 | /* Can't do this from NMI context (can cause deadlocks) */ | ||
89 | if (in_nmi()) | ||
90 | return; | ||
91 | |||
88 | local_irq_save(flags); | 92 | local_irq_save(flags); |
89 | arch_spin_lock(&max_stack_lock); | 93 | arch_spin_lock(&max_stack_lock); |
90 | 94 | ||
95 | /* | ||
96 | * RCU may not be watching, make it see us. | ||
97 | * The stack trace code uses rcu_sched. | ||
98 | */ | ||
99 | rcu_irq_enter(); | ||
100 | |||
91 | /* In case another CPU set the tracer_frame on us */ | 101 | /* In case another CPU set the tracer_frame on us */ |
92 | if (unlikely(!frame_size)) | 102 | if (unlikely(!frame_size)) |
93 | this_size -= tracer_frame; | 103 | this_size -= tracer_frame; |
@@ -169,6 +179,7 @@ check_stack(unsigned long ip, unsigned long *stack) | |||
169 | } | 179 | } |
170 | 180 | ||
171 | out: | 181 | out: |
182 | rcu_irq_exit(); | ||
172 | arch_spin_unlock(&max_stack_lock); | 183 | arch_spin_unlock(&max_stack_lock); |
173 | local_irq_restore(flags); | 184 | local_irq_restore(flags); |
174 | } | 185 | } |