Commit 299f45902ab03c0f8a58ef1c9a02567b180e1f80
Committed by
Greg Kroah-Hartman
1 parent
409b0c0169
x86/tlb/trace: Do not trace on CPU that is offline
commit 6c8465a82a605bc692304bab42703017dcfff013 upstream. When taking a CPU down for suspend and resume, a tracepoint may be called when the CPU has been designated offline. As tracepoints require RCU for protection, they must not be called if the current CPU is offline. Unfortunately, trace_tlb_flush() is called in this scenario as was noted by LOCKDEP: ... Disabling non-boot CPUs ... intel_pstate CPU 1 exiting =============================== smpboot: CPU 1 didn't die... [ INFO: suspicious RCU usage. ] 3.19.0-rc7-next-20150204.1-iniza-small #1 Not tainted ------------------------------- include/trace/events/tlb.h:35 suspicious rcu_dereference_check() usage! other info that might help us debug this: RCU used illegally from offline CPU! rcu_scheduler_active = 1, debug_locks = 0 no locks held by swapper/1/0. stack backtrace: CPU: 1 PID: 0 Comm: swapper/1 Not tainted 3.19.0-rc7-next-20150204.1-iniza-small #1 Hardware name: SAMSUNG ELECTRONICS CO., LTD. 530U3BI/530U4BI/530U4BH/530U3BI/530U4BI/530U4BH, BIOS 13XK 03/28/2013 0000000000000001 ffff88011a44fe18 ffffffff817e370d 0000000000000011 ffff88011a448290 ffff88011a44fe48 ffffffff810d6847 ffff8800c66b9600 0000000000000001 ffff88011a44c000 ffffffff81cb3900 ffff88011a44fe78 Call Trace: [<ffffffff817e370d>] dump_stack+0x4c/0x65 [<ffffffff810d6847>] lockdep_rcu_suspicious+0xe7/0x120 [<ffffffff810b71a5>] idle_task_exit+0x205/0x2c0 [<ffffffff81054c4e>] play_dead_common+0xe/0x50 [<ffffffff81054ca5>] native_play_dead+0x15/0x140 [<ffffffff8102963f>] arch_cpu_idle_dead+0xf/0x20 [<ffffffff810cd89e>] cpu_startup_entry+0x37e/0x580 [<ffffffff81053e20>] start_secondary+0x140/0x150 intel_pstate CPU 2 exiting ... By converting the tlb_flush tracepoint to a TRACE_EVENT_CONDITION where the condition is cpu_online(smp_processor_id()), we can avoid calling RCU protected code when the CPU is offline. Link: http://lkml.kernel.org/r/CA+icZUUGiGDoL5NU8RuxKzFjoLjEKRtUWx=JB8B9a0EQv-eGzQ@mail.gmail.com Fixes: d17d8f9dedb9 "x86/mm: Add tracepoints for TLB flushes" Reported-by: Sedat Dilek <sedat.dilek@gmail.com> Tested-by: Sedat Dilek <sedat.dilek@gmail.com> Suggested-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> Acked-by: Dave Hansen <dave@sr71.net> Signed-off-by: Steven Rostedt <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Showing 1 changed file with 3 additions and 1 deletions Inline Diff
include/trace/events/tlb.h
1 | #undef TRACE_SYSTEM | 1 | #undef TRACE_SYSTEM |
2 | #define TRACE_SYSTEM tlb | 2 | #define TRACE_SYSTEM tlb |
3 | 3 | ||
4 | #if !defined(_TRACE_TLB_H) || defined(TRACE_HEADER_MULTI_READ) | 4 | #if !defined(_TRACE_TLB_H) || defined(TRACE_HEADER_MULTI_READ) |
5 | #define _TRACE_TLB_H | 5 | #define _TRACE_TLB_H |
6 | 6 | ||
7 | #include <linux/mm_types.h> | 7 | #include <linux/mm_types.h> |
8 | #include <linux/tracepoint.h> | 8 | #include <linux/tracepoint.h> |
9 | 9 | ||
10 | #define TLB_FLUSH_REASON \ | 10 | #define TLB_FLUSH_REASON \ |
11 | { TLB_FLUSH_ON_TASK_SWITCH, "flush on task switch" }, \ | 11 | { TLB_FLUSH_ON_TASK_SWITCH, "flush on task switch" }, \ |
12 | { TLB_REMOTE_SHOOTDOWN, "remote shootdown" }, \ | 12 | { TLB_REMOTE_SHOOTDOWN, "remote shootdown" }, \ |
13 | { TLB_LOCAL_SHOOTDOWN, "local shootdown" }, \ | 13 | { TLB_LOCAL_SHOOTDOWN, "local shootdown" }, \ |
14 | { TLB_LOCAL_MM_SHOOTDOWN, "local mm shootdown" } | 14 | { TLB_LOCAL_MM_SHOOTDOWN, "local mm shootdown" } |
15 | 15 | ||
16 | TRACE_EVENT(tlb_flush, | 16 | TRACE_EVENT_CONDITION(tlb_flush, |
17 | 17 | ||
18 | TP_PROTO(int reason, unsigned long pages), | 18 | TP_PROTO(int reason, unsigned long pages), |
19 | TP_ARGS(reason, pages), | 19 | TP_ARGS(reason, pages), |
20 | |||
21 | TP_CONDITION(cpu_online(smp_processor_id())), | ||
20 | 22 | ||
21 | TP_STRUCT__entry( | 23 | TP_STRUCT__entry( |
22 | __field( int, reason) | 24 | __field( int, reason) |
23 | __field(unsigned long, pages) | 25 | __field(unsigned long, pages) |
24 | ), | 26 | ), |
25 | 27 | ||
26 | TP_fast_assign( | 28 | TP_fast_assign( |
27 | __entry->reason = reason; | 29 | __entry->reason = reason; |
28 | __entry->pages = pages; | 30 | __entry->pages = pages; |
29 | ), | 31 | ), |
30 | 32 | ||
31 | TP_printk("pages:%ld reason:%s (%d)", | 33 | TP_printk("pages:%ld reason:%s (%d)", |
32 | __entry->pages, | 34 | __entry->pages, |
33 | __print_symbolic(__entry->reason, TLB_FLUSH_REASON), | 35 | __print_symbolic(__entry->reason, TLB_FLUSH_REASON), |
34 | __entry->reason) | 36 | __entry->reason) |
35 | ); | 37 | ); |
36 | 38 | ||
37 | #endif /* _TRACE_TLB_H */ | 39 | #endif /* _TRACE_TLB_H */ |
38 | 40 | ||
39 | /* This part must be outside protection */ | 41 | /* This part must be outside protection */ |
40 | #include <trace/define_trace.h> | 42 | #include <trace/define_trace.h> |
41 | 43 |