Commit 299f45902ab03c0f8a58ef1c9a02567b180e1f80

Authored by Steven Rostedt (Red Hat)
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