History

Merge branch 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'tracing-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip: (40 commits) tracing: Separate raw syscall from syscall tracer ring-buffer-benchmark: Add parameters to set produce/consumer priorities tracing, function tracer: Clean up strstrip() usage ring-buffer benchmark: Run producer/consumer threads at nice +19 tracing: Remove the stale include/trace/power.h tracing: Only print objcopy version warning once from recordmcount tracing: Prevent build warning: 'ftrace_graph_buf' defined but not used ring-buffer: Move access to commit_page up into function used tracing: do not disable interrupts for trace_clock_local ring-buffer: Add multiple iterations between benchmark timestamps kprobes: Sanitize struct kretprobe_instance allocations tracing: Fix to use __always_unused attribute compiler: Introduce __always_unused tracing: Exit with error if a weak function is used in recordmcount.pl tracing: Move conditional into update_funcs() in recordmcount.pl tracing: Add regex for weak functions in recordmcount.pl tracing: Move mcount section search to front of loop in recordmcount.pl tracing: Fix objcopy revision check in recordmcount.pl tracing: Check absolute path of input file in recordmcount.pl tracing: Correct the check for number of arguments in recordmcount.pl ...

Linus Torvalds committed 16 years ago

Commit 96fa2b52 parents 7a797cd b8007ef28 files · +856 −518Browse files

Unified · Split

28 files
  1. Documentation/kernel-parameters.txt +7 −0
  2. Documentation/trace/ftrace-design.txt +11 −2
  3. Makefile +1 −0
  4. arch/s390/kernel/ftrace.c +2 −65
  5. arch/x86/kernel/entry_32.S +2 −5
  6. arch/x86/kernel/entry_64.S +3 −3
  7. arch/x86/kernel/ftrace.c +7 −77
  8. arch/x86/mm/testmmiotrace.c +14 −15
  9. include/linux/compiler-gcc.h +1 −0
  10. include/linux/compiler.h +4 −0
  11. include/linux/smp_lock.h +17 −4
  12. include/trace/events/bkl.h +61 −0
  13. include/trace/events/syscalls.h +2 −1
  14. include/trace/power.h +0 −32
  15. include/trace/syscall.h +1 −1
  16. kernel/kprobes.c +2 −2
  17. kernel/trace/ftrace.c +236 −139
  18. kernel/trace/ring_buffer.c +3 −6
  19. kernel/trace/ring_buffer_benchmark.c +76 −9
  20. kernel/trace/trace.c +2 −2
  21. kernel/trace/trace.h +29 −15
  22. kernel/trace/trace_clock.c +5 −3
  23. kernel/trace/trace_events.c +11 −12
  24. kernel/trace/trace_events_filter.c +137 −18
  25. kernel/trace/trace_export.c +2 −2
  26. kernel/trace/trace_syscalls.c +86 −0
  27. lib/kernel_lock.c +14 −6
  28. scripts/recordmcount.pl +120 −99
Documentation/kernel-parameters.txt+7−0
@@ -778,6 +778,13 @@ and is between 256 and 4096 characters. It is defined in the file · 777 unmodified lines
778 by the set_ftrace_notrace file in the debugfs778 by the set_ftrace_notrace file in the debugfs
779 tracing directory.779 tracing directory.
780 780
781 ftrace_graph_filter=[function-list]
782 [FTRACE] Limit the top level callers functions traced
783 by the function graph tracer at boot up.
784 function-list is a comma separated list of functions
785 that can be changed at run time by the
786 set_graph_function file in the debugfs tracing directory.
787
781 gamecon.map[2|3]=788 gamecon.map[2|3]=
782 [HW,JOY] Multisystem joystick and NES/SNES/PSX pad789 [HW,JOY] Multisystem joystick and NES/SNES/PSX pad
783 support via parallel port (up to 5 devices per port)790 support via parallel port (up to 5 devices per port)
Documentation/trace/ftrace-design.txt+11−2
@@ -213,10 +213,19 @@ If you can't trace NMI functions, then skip this option. · 212 unmodified lines
213<details to be filled>213<details to be filled>
214 214
215 215
216HAVE_FTRACE_SYSCALLS216HAVE_SYSCALL_TRACEPOINTS
217---------------------217---------------------
218 218
219<details to be filled>219You need very few things to get the syscalls tracing in an arch.
220
221- Have a NR_syscalls variable in <asm/unistd.h> that provides the number
222 of syscalls supported by the arch.
223- Implement arch_syscall_addr() that resolves a syscall address from a
224 syscall number.
225- Support the TIF_SYSCALL_TRACEPOINT thread flags
226- Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace
227 in the ptrace syscalls tracing path.
228- Tag this arch as HAVE_SYSCALL_TRACEPOINTS.
220 229
221 230
222HAVE_FTRACE_MCOUNT_RECORD231HAVE_FTRACE_MCOUNT_RECORD
Makefile+1−0
@@ -379,6 +379,7 @@ export RCS_TAR_IGNORE := --exclude SCCS --exclude BitKeeper --exclude .svn --exc · 378 unmodified lines
379PHONY += scripts_basic379PHONY += scripts_basic
380scripts_basic:380scripts_basic:
381 $(Q)$(MAKE) $(build)=scripts/basic381 $(Q)$(MAKE) $(build)=scripts/basic
382 $(Q)rm -f .tmp_quiet_recordmcount
382 383
383# To avoid any implicit rule to kick in, define an empty command.384# To avoid any implicit rule to kick in, define an empty command.
384scripts/basic/%: scripts_basic ;385scripts/basic/%: scripts_basic ;
arch/s390/kernel/ftrace.c+2−65
@@ -203,73 +203,10 @@ out: · 202 unmodified lines
203 203
204#ifdef CONFIG_FTRACE_SYSCALLS204#ifdef CONFIG_FTRACE_SYSCALLS
205 205
206extern unsigned long __start_syscalls_metadata[];
207extern unsigned long __stop_syscalls_metadata[];
208extern unsigned int sys_call_table[];206extern unsigned int sys_call_table[];
209 207
210static struct syscall_metadata **syscalls_metadata;208unsigned long __init arch_syscall_addr(int nr)
211
212struct syscall_metadata *syscall_nr_to_meta(int nr)
213{
214 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
215 return NULL;
216
217 return syscalls_metadata[nr];
218}
219
220int syscall_name_to_nr(char *name)
221{
222 int i;
223
224 if (!syscalls_metadata)
225 return -1;
226 for (i = 0; i < NR_syscalls; i++)
227 if (syscalls_metadata[i])
228 if (!strcmp(syscalls_metadata[i]->name, name))
229 return i;
230 return -1;
231}
232
233void set_syscall_enter_id(int num, int id)
234{
235 syscalls_metadata[num]->enter_id = id;
236}
237
238void set_syscall_exit_id(int num, int id)
239{209{
240 syscalls_metadata[num]->exit_id = id;210 return (unsigned long)sys_call_table[nr];
241}
242
243static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
244{
245 struct syscall_metadata *start;
246 struct syscall_metadata *stop;
247 char str[KSYM_SYMBOL_LEN];
248
249 start = (struct syscall_metadata *)__start_syscalls_metadata;
250 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
251 kallsyms_lookup(syscall, NULL, NULL, NULL, str);
252
253 for ( ; start < stop; start++) {
254 if (start->name && !strcmp(start->name + 3, str + 3))
255 return start;
256 }
257 return NULL;
258}
259
260static int __init arch_init_ftrace_syscalls(void)
261{
262 struct syscall_metadata *meta;
263 int i;
264 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
265 GFP_KERNEL);
266 if (!syscalls_metadata)
267 return -ENOMEM;
268 for (i = 0; i < NR_syscalls; i++) {
269 meta = find_syscall_meta((unsigned long)sys_call_table[i]);
270 syscalls_metadata[i] = meta;
271 }
272 return 0;
273}211}
274arch_initcall(arch_init_ftrace_syscalls);
275#endif212#endif
arch/x86/kernel/entry_32.S+2−5
@@ -1185,17 +1185,14 @@ END(ftrace_graph_caller) · 1184 unmodified lines
1185 1185
1186.globl return_to_handler1186.globl return_to_handler
1187return_to_handler:1187return_to_handler:
1188 pushl $0
1189 pushl %eax1188 pushl %eax
1190 pushl %ecx
1191 pushl %edx1189 pushl %edx
1192 movl %ebp, %eax1190 movl %ebp, %eax
1193 call ftrace_return_to_handler1191 call ftrace_return_to_handler
1194 movl %eax, 0xc(%esp)1192 movl %eax, %ecx
1195 popl %edx1193 popl %edx
1196 popl %ecx
1197 popl %eax1194 popl %eax
1198 ret1195 jmp *%ecx
1199#endif1196#endif
1200 1197
1201.section .rodata,"a"1198.section .rodata,"a"
arch/x86/kernel/entry_64.S+3−3
@@ -155,11 +155,11 @@ GLOBAL(return_to_handler) · 154 unmodified lines
155 155
156 call ftrace_return_to_handler156 call ftrace_return_to_handler
157 157
158 movq %rax, 16(%rsp)158 movq %rax, %rdi
159 movq 8(%rsp), %rdx159 movq 8(%rsp), %rdx
160 movq (%rsp), %rax160 movq (%rsp), %rax
161 addq $16, %rsp161 addq $24, %rsp
162 retq162 jmp *%rdi
163#endif163#endif
164 164
165 165
arch/x86/kernel/ftrace.c+7−77
@@ -9,6 +9,8 @@ · 8 unmodified lines
9 * the dangers of modifying code on the run.9 * the dangers of modifying code on the run.
10 */10 */
11 11
12#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13
12#include <linux/spinlock.h>14#include <linux/spinlock.h>
13#include <linux/hardirq.h>15#include <linux/hardirq.h>
14#include <linux/uaccess.h>16#include <linux/uaccess.h>
@@ -336,15 +338,15 @@ int __init ftrace_dyn_arch_init(void *data) · 321 unmodified lines
336 338
337 switch (faulted) {339 switch (faulted) {
338 case 0:340 case 0:
339 pr_info("ftrace: converting mcount calls to 0f 1f 44 00 00\n");341 pr_info("converting mcount calls to 0f 1f 44 00 00\n");
340 memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);342 memcpy(ftrace_nop, ftrace_test_p6nop, MCOUNT_INSN_SIZE);
341 break;343 break;
342 case 1:344 case 1:
343 pr_info("ftrace: converting mcount calls to 66 66 66 66 90\n");345 pr_info("converting mcount calls to 66 66 66 66 90\n");
344 memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);346 memcpy(ftrace_nop, ftrace_test_nop5, MCOUNT_INSN_SIZE);
345 break;347 break;
346 case 2:348 case 2:
347 pr_info("ftrace: converting mcount calls to jmp . + 5\n");349 pr_info("converting mcount calls to jmp . + 5\n");
348 memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);350 memcpy(ftrace_nop, ftrace_test_jmp, MCOUNT_INSN_SIZE);
349 break;351 break;
350 }352 }
@@ -468,82 +470,10 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr, · 117 unmodified lines
468 470
469#ifdef CONFIG_FTRACE_SYSCALLS471#ifdef CONFIG_FTRACE_SYSCALLS
470 472
471extern unsigned long __start_syscalls_metadata[];
472extern unsigned long __stop_syscalls_metadata[];
473extern unsigned long *sys_call_table;473extern unsigned long *sys_call_table;
474 474
475static struct syscall_metadata **syscalls_metadata;475unsigned long __init arch_syscall_addr(int nr)
476
477static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
478{
479 struct syscall_metadata *start;
480 struct syscall_metadata *stop;
481 char str[KSYM_SYMBOL_LEN];
482
483
484 start = (struct syscall_metadata *)__start_syscalls_metadata;
485 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
486 kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
487
488 for ( ; start < stop; start++) {
489 if (start->name && !strcmp(start->name, str))
490 return start;
491 }
492 return NULL;
493}
494
495struct syscall_metadata *syscall_nr_to_meta(int nr)
496{
497 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
498 return NULL;
499
500 return syscalls_metadata[nr];
501}
502
503int syscall_name_to_nr(char *name)
504{476{
505 int i;477 return (unsigned long)(&sys_call_table)[nr];
506
507 if (!syscalls_metadata)
508 return -1;
509
510 for (i = 0; i < NR_syscalls; i++) {
511 if (syscalls_metadata[i]) {
512 if (!strcmp(syscalls_metadata[i]->name, name))
513 return i;
514 }
515 }
516 return -1;
517}
518
519void set_syscall_enter_id(int num, int id)
520{
521 syscalls_metadata[num]->enter_id = id;
522}
523
524void set_syscall_exit_id(int num, int id)
525{
526 syscalls_metadata[num]->exit_id = id;
527}
528
529static int __init arch_init_ftrace_syscalls(void)
530{
531 int i;
532 struct syscall_metadata *meta;
533 unsigned long **psys_syscall_table = &sys_call_table;
534
535 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
536 NR_syscalls, GFP_KERNEL);
537 if (!syscalls_metadata) {
538 WARN_ON(1);
539 return -ENOMEM;
540 }
541
542 for (i = 0; i < NR_syscalls; i++) {
543 meta = find_syscall_meta(psys_syscall_table[i]);
544 syscalls_metadata[i] = meta;
545 }
546 return 0;
547}478}
548arch_initcall(arch_init_ftrace_syscalls);
549#endif479#endif
arch/x86/mm/testmmiotrace.c+14−15
@@ -1,12 +1,13 @@
1/*1/*
2 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>2 * Written by Pekka Paalanen, 2008-2009 <pq@iki.fi>
3 */3 */
4
5#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
6
4#include <linux/module.h>7#include <linux/module.h>
5#include <linux/io.h>8#include <linux/io.h>
6#include <linux/mmiotrace.h>9#include <linux/mmiotrace.h>
7 10
8#define MODULE_NAME "testmmiotrace"
9
10static unsigned long mmio_address;11static unsigned long mmio_address;
11module_param(mmio_address, ulong, 0);12module_param(mmio_address, ulong, 0);
12MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "13MODULE_PARM_DESC(mmio_address, " Start address of the mapping of 16 kB "
@@ -30,7 +31,7 @@ static unsigned v32(unsigned i) · 17 unmodified lines
30static void do_write_test(void __iomem *p)31static void do_write_test(void __iomem *p)
31{32{
32 unsigned int i;33 unsigned int i;
33 pr_info(MODULE_NAME ": write test.\n");34 pr_info("write test.\n");
34 mmiotrace_printk("Write test.\n");35 mmiotrace_printk("Write test.\n");
35 36
36 for (i = 0; i < 256; i++)37 for (i = 0; i < 256; i++)
@@ -47,7 +48,7 @@ static void do_read_test(void __iomem *p) · 10 unmodified lines
47{48{
48 unsigned int i;49 unsigned int i;
49 unsigned errs[3] = { 0 };50 unsigned errs[3] = { 0 };
50 pr_info(MODULE_NAME ": read test.\n");51 pr_info("read test.\n");
51 mmiotrace_printk("Read test.\n");52 mmiotrace_printk("Read test.\n");
52 53
53 for (i = 0; i < 256; i++)54 for (i = 0; i < 256; i++)
@@ -68,7 +69,7 @@ static void do_read_test(void __iomem *p) · 14 unmodified lines
68 69
69static void do_read_far_test(void __iomem *p)70static void do_read_far_test(void __iomem *p)
70{71{
71 pr_info(MODULE_NAME ": read far test.\n");72 pr_info("read far test.\n");
72 mmiotrace_printk("Read far test.\n");73 mmiotrace_printk("Read far test.\n");
73 74
74 ioread32(p + read_far);75 ioread32(p + read_far);
@@ -78,7 +79,7 @@ static void do_test(unsigned long size) · 3 unmodified lines
78{79{
79 void __iomem *p = ioremap_nocache(mmio_address, size);80 void __iomem *p = ioremap_nocache(mmio_address, size);
80 if (!p) {81 if (!p) {
81 pr_err(MODULE_NAME ": could not ioremap, aborting.\n");82 pr_err("could not ioremap, aborting.\n");
82 return;83 return;
83 }84 }
84 mmiotrace_printk("ioremap returned %p.\n", p);85 mmiotrace_printk("ioremap returned %p.\n", p);
@@ -94,24 +95,22 @@ static int __init init(void) · 9 unmodified lines
94 unsigned long size = (read_far) ? (8 << 20) : (16 << 10);95 unsigned long size = (read_far) ? (8 << 20) : (16 << 10);
95 96
96 if (mmio_address == 0) {97 if (mmio_address == 0) {
97 pr_err(MODULE_NAME ": you have to use the module argument "98 pr_err("you have to use the module argument mmio_address.\n");
98 "mmio_address.\n");99 pr_err("DO NOT LOAD THIS MODULE UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!\n");
99 pr_err(MODULE_NAME ": DO NOT LOAD THIS MODULE UNLESS"
100 " YOU REALLY KNOW WHAT YOU ARE DOING!\n");
101 return -ENXIO;100 return -ENXIO;
102 }101 }
103 102
104 pr_warning(MODULE_NAME ": WARNING: mapping %lu kB @ 0x%08lx in PCI "103 pr_warning("WARNING: mapping %lu kB @ 0x%08lx in PCI address space, "
105 "address space, and writing 16 kB of rubbish in there.\n",104 "and writing 16 kB of rubbish in there.\n",
106 size >> 10, mmio_address);105 size >> 10, mmio_address);
107 do_test(size);106 do_test(size);
108 pr_info(MODULE_NAME ": All done.\n");107 pr_info("All done.\n");
109 return 0;108 return 0;
110}109}
111 110
112static void __exit cleanup(void)111static void __exit cleanup(void)
113{112{
114 pr_debug(MODULE_NAME ": unloaded.\n");113 pr_debug("unloaded.\n");
115}114}
116 115
117module_init(init);116module_init(init);
include/linux/compiler-gcc.h+1−0
@@ -79,6 +79,7 @@ · 78 unmodified lines
79#define noinline __attribute__((noinline))79#define noinline __attribute__((noinline))
80#define __attribute_const__ __attribute__((__const__))80#define __attribute_const__ __attribute__((__const__))
81#define __maybe_unused __attribute__((unused))81#define __maybe_unused __attribute__((unused))
82#define __always_unused __attribute__((unused))
82 83
83#define __gcc_header(x) #x84#define __gcc_header(x) #x
84#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)85#define _gcc_header(x) __gcc_header(linux/compiler-gcc##x.h)
include/linux/compiler.h+4−0
@@ -218,6 +218,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect); · 217 unmodified lines
218# define __maybe_unused /* unimplemented */218# define __maybe_unused /* unimplemented */
219#endif219#endif
220 220
221#ifndef __always_unused
222# define __always_unused /* unimplemented */
223#endif
224
221#ifndef noinline225#ifndef noinline
222#define noinline226#define noinline
223#endif227#endif
include/linux/smp_lock.h+17−4
@@ -24,8 +24,21 @@ static inline int reacquire_kernel_lock(struct task_struct *task) · 23 unmodified lines
24 return 0;24 return 0;
25}25}
26 26
27extern void __lockfunc lock_kernel(void) __acquires(kernel_lock);27extern void __lockfunc
28extern void __lockfunc unlock_kernel(void) __releases(kernel_lock);28_lock_kernel(const char *func, const char *file, int line)
29__acquires(kernel_lock);
30
31extern void __lockfunc
32_unlock_kernel(const char *func, const char *file, int line)
33__releases(kernel_lock);
34
35#define lock_kernel() do { \
36 _lock_kernel(__func__, __FILE__, __LINE__); \
37} while (0)
38
39#define unlock_kernel() do { \
40 _unlock_kernel(__func__, __FILE__, __LINE__); \
41} while (0)
29 42
30/*43/*
31 * Various legacy drivers don't really need the BKL in a specific44 * Various legacy drivers don't really need the BKL in a specific
@@ -41,8 +54,8 @@ static inline void cycle_kernel_lock(void) · 9 unmodified lines
41 54
42#else55#else
43 56
44#define lock_kernel() do { } while(0)57#define lock_kernel()
45#define unlock_kernel() do { } while(0)58#define unlock_kernel()
46#define release_kernel_lock(task) do { } while(0)59#define release_kernel_lock(task) do { } while(0)
47#define cycle_kernel_lock() do { } while(0)60#define cycle_kernel_lock() do { } while(0)
48#define reacquire_kernel_lock(task) 061#define reacquire_kernel_lock(task) 0
include/trace/events/bkl.h+61−0
@@ -0,0 +1,61 @@
1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM bkl
3
4#if !defined(_TRACE_BKL_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_BKL_H
6
7#include <linux/tracepoint.h>
8
9TRACE_EVENT(lock_kernel,
10
11 TP_PROTO(const char *func, const char *file, int line),
12
13 TP_ARGS(func, file, line),
14
15 TP_STRUCT__entry(
16 __field( int, lock_depth )
17 __field_ext( const char *, func, FILTER_PTR_STRING )
18 __field_ext( const char *, file, FILTER_PTR_STRING )
19 __field( int, line )
20 ),
21
22 TP_fast_assign(
23 /* We want to record the lock_depth after lock is acquired */
24 __entry->lock_depth = current->lock_depth + 1;
25 __entry->func = func;
26 __entry->file = file;
27 __entry->line = line;
28 ),
29
30 TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth,
31 __entry->file, __entry->line, __entry->func)
32);
33
34TRACE_EVENT(unlock_kernel,
35
36 TP_PROTO(const char *func, const char *file, int line),
37
38 TP_ARGS(func, file, line),
39
40 TP_STRUCT__entry(
41 __field(int, lock_depth)
42 __field(const char *, func)
43 __field(const char *, file)
44 __field(int, line)
45 ),
46
47 TP_fast_assign(
48 __entry->lock_depth = current->lock_depth;
49 __entry->func = func;
50 __entry->file = file;
51 __entry->line = line;
52 ),
53
54 TP_printk("depth: %d, %s:%d %s()", __entry->lock_depth,
55 __entry->file, __entry->line, __entry->func)
56);
57
58#endif /* _TRACE_BKL_H */
59
60/* This part must be outside protection */
61#include <trace/define_trace.h>
include/trace/events/syscalls.h+2−1
@@ -1,5 +1,6 @@
1#undef TRACE_SYSTEM1#undef TRACE_SYSTEM
2#define TRACE_SYSTEM syscalls2#define TRACE_SYSTEM raw_syscalls
3#define TRACE_INCLUDE_FILE syscalls
3 4
4#if !defined(_TRACE_EVENTS_SYSCALLS_H) || defined(TRACE_HEADER_MULTI_READ)5#if !defined(_TRACE_EVENTS_SYSCALLS_H) || defined(TRACE_HEADER_MULTI_READ)
5#define _TRACE_EVENTS_SYSCALLS_H6#define _TRACE_EVENTS_SYSCALLS_H
include/trace/power.h+0−32
@@ -1,32 +0,0 @@
1#ifndef _TRACE_POWER_H
2#define _TRACE_POWER_H
3
4#include <linux/ktime.h>
5#include <linux/tracepoint.h>
6
7enum {
8 POWER_NONE = 0,
9 POWER_CSTATE = 1,
10 POWER_PSTATE = 2,
11};
12
13struct power_trace {
14 ktime_t stamp;
15 ktime_t end;
16 int type;
17 int state;
18};
19
20DECLARE_TRACE(power_start,
21 TP_PROTO(struct power_trace *it, unsigned int type, unsigned int state),
22 TP_ARGS(it, type, state));
23
24DECLARE_TRACE(power_mark,
25 TP_PROTO(struct power_trace *it, unsigned int type, unsigned int state),
26 TP_ARGS(it, type, state));
27
28DECLARE_TRACE(power_end,
29 TP_PROTO(struct power_trace *it),
30 TP_ARGS(it));
31
32#endif /* _TRACE_POWER_H */
include/trace/syscall.h+1−1
@@ -33,7 +33,7 @@ struct syscall_metadata { · 32 unmodified lines
33};33};
34 34
35#ifdef CONFIG_FTRACE_SYSCALLS35#ifdef CONFIG_FTRACE_SYSCALLS
36extern struct syscall_metadata *syscall_nr_to_meta(int nr);36extern unsigned long arch_syscall_addr(int nr);
37extern int syscall_name_to_nr(char *name);37extern int syscall_name_to_nr(char *name);
38void set_syscall_enter_id(int num, int id);38void set_syscall_enter_id(int num, int id);
39void set_syscall_exit_id(int num, int id);39void set_syscall_exit_id(int num, int id);
kernel/kprobes.c+2−2
@@ -1014,9 +1014,9 @@ int __kprobes register_kretprobe(struct kretprobe *rp) · 1013 unmodified lines
1014 /* Pre-allocate memory for max kretprobe instances */1014 /* Pre-allocate memory for max kretprobe instances */
1015 if (rp->maxactive <= 0) {1015 if (rp->maxactive <= 0) {
1016#ifdef CONFIG_PREEMPT1016#ifdef CONFIG_PREEMPT
1017 rp->maxactive = max(10, 2 * NR_CPUS);1017 rp->maxactive = max(10, 2 * num_possible_cpus());
1018#else1018#else
1019 rp->maxactive = NR_CPUS;1019 rp->maxactive = num_possible_cpus();
1020#endif1020#endif
1021 }1021 }
1022 spin_lock_init(&rp->lock);1022 spin_lock_init(&rp->lock);
kernel/trace/ftrace.c+236−139
@@ -60,6 +60,13 @@ static int last_ftrace_enabled; · 59 unmodified lines
60/* Quick disabling of function tracer. */60/* Quick disabling of function tracer. */
61int function_trace_stop;61int function_trace_stop;
62 62
63/* List for set_ftrace_pid's pids. */
64LIST_HEAD(ftrace_pids);
65struct ftrace_pid {
66 struct list_head list;
67 struct pid *pid;
68};
69
63/*70/*
64 * ftrace_disabled is set when an anomaly is discovered.71 * ftrace_disabled is set when an anomaly is discovered.
65 * ftrace_disabled is much stronger than ftrace_enabled.72 * ftrace_disabled is much stronger than ftrace_enabled.
@@ -78,6 +85,10 @@ ftrace_func_t ftrace_trace_function __read_mostly = ftrace_stub; · 12 unmodified lines
78ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;85ftrace_func_t __ftrace_trace_function __read_mostly = ftrace_stub;
79ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;86ftrace_func_t ftrace_pid_function __read_mostly = ftrace_stub;
80 87
88#ifdef CONFIG_FUNCTION_GRAPH_TRACER
89static int ftrace_set_func(unsigned long *array, int *idx, char *buffer);
90#endif
91
81static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)92static void ftrace_list_func(unsigned long ip, unsigned long parent_ip)
82{93{
83 struct ftrace_ops *op = ftrace_list;94 struct ftrace_ops *op = ftrace_list;
@@ -155,7 +166,7 @@ static int __register_ftrace_function(struct ftrace_ops *ops) · 71 unmodified lines
155 else166 else
156 func = ftrace_list_func;167 func = ftrace_list_func;
157 168
158 if (ftrace_pid_trace) {169 if (!list_empty(&ftrace_pids)) {
159 set_ftrace_pid_function(func);170 set_ftrace_pid_function(func);
160 func = ftrace_pid_func;171 func = ftrace_pid_func;
161 }172 }
@@ -203,7 +214,7 @@ static int __unregister_ftrace_function(struct ftrace_ops *ops) · 41 unmodified lines
203 if (ftrace_list->next == &ftrace_list_end) {214 if (ftrace_list->next == &ftrace_list_end) {
204 ftrace_func_t func = ftrace_list->func;215 ftrace_func_t func = ftrace_list->func;
205 216
206 if (ftrace_pid_trace) {217 if (!list_empty(&ftrace_pids)) {
207 set_ftrace_pid_function(func);218 set_ftrace_pid_function(func);
208 func = ftrace_pid_func;219 func = ftrace_pid_func;
209 }220 }
@@ -231,7 +242,7 @@ static void ftrace_update_pid_func(void) · 21 unmodified lines
231 func = __ftrace_trace_function;242 func = __ftrace_trace_function;
232#endif243#endif
233 244
234 if (ftrace_pid_trace) {245 if (!list_empty(&ftrace_pids)) {
235 set_ftrace_pid_function(func);246 set_ftrace_pid_function(func);
236 func = ftrace_pid_func;247 func = ftrace_pid_func;
237 } else {248 } else {
@@ -821,8 +832,6 @@ static __init void ftrace_profile_debugfs(struct dentry *d_tracer) · 583 unmodified lines
821}832}
822#endif /* CONFIG_FUNCTION_PROFILER */833#endif /* CONFIG_FUNCTION_PROFILER */
823 834
824/* set when tracing only a pid */
825struct pid *ftrace_pid_trace;
826static struct pid * const ftrace_swapper_pid = &init_struct_pid;835static struct pid * const ftrace_swapper_pid = &init_struct_pid;
827 836
828#ifdef CONFIG_DYNAMIC_FTRACE837#ifdef CONFIG_DYNAMIC_FTRACE
@@ -1261,12 +1270,34 @@ static int ftrace_update_code(struct module *mod) · 432 unmodified lines
1261 ftrace_new_addrs = p->newlist;1270 ftrace_new_addrs = p->newlist;
1262 p->flags = 0L;1271 p->flags = 0L;
1263 1272
1264 /* convert record (i.e, patch mcount-call with NOP) */1273 /*
1265 if (ftrace_code_disable(mod, p)) {1274 * Do the initial record convertion from mcount jump
1266 p->flags |= FTRACE_FL_CONVERTED;1275 * to the NOP instructions.
1267 ftrace_update_cnt++;1276 */
1268 } else1277 if (!ftrace_code_disable(mod, p)) {
1269 ftrace_free_rec(p);1278 ftrace_free_rec(p);
1279 continue;
1280 }
1281
1282 p->flags |= FTRACE_FL_CONVERTED;
1283 ftrace_update_cnt++;
1284
1285 /*
1286 * If the tracing is enabled, go ahead and enable the record.
1287 *
1288 * The reason not to enable the record immediatelly is the
1289 * inherent check of ftrace_make_nop/ftrace_make_call for
1290 * correct previous instructions. Making first the NOP
1291 * conversion puts the module to the correct state, thus
1292 * passing the ftrace_make_call check.
1293 */
1294 if (ftrace_start_up) {
1295 int failed = __ftrace_replace_code(p, 1);
1296 if (failed) {
1297 ftrace_bug(failed, p->ip);
1298 ftrace_free_rec(p);
1299 }
1300 }
1270 }1301 }
1271 1302
1272 stop = ftrace_now(raw_smp_processor_id());1303 stop = ftrace_now(raw_smp_processor_id());
@@ -1656,60 +1687,6 @@ ftrace_regex_lseek(struct file *file, loff_t offset, int origin) · 383 unmodified lines
1656 return ret;1687 return ret;
1657}1688}
1658 1689
1659enum {
1660 MATCH_FULL,
1661 MATCH_FRONT_ONLY,
1662 MATCH_MIDDLE_ONLY,
1663 MATCH_END_ONLY,
1664};
1665
1666/*
1667 * (static function - no need for kernel doc)
1668 *
1669 * Pass in a buffer containing a glob and this function will
1670 * set search to point to the search part of the buffer and
1671 * return the type of search it is (see enum above).
1672 * This does modify buff.
1673 *
1674 * Returns enum type.
1675 * search returns the pointer to use for comparison.
1676 * not returns 1 if buff started with a '!'
1677 * 0 otherwise.
1678 */
1679static int
1680ftrace_setup_glob(char *buff, int len, char **search, int *not)
1681{
1682 int type = MATCH_FULL;
1683 int i;
1684
1685 if (buff[0] == '!') {
1686 *not = 1;
1687 buff++;
1688 len--;
1689 } else
1690 *not = 0;
1691
1692 *search = buff;
1693
1694 for (i = 0; i < len; i++) {
1695 if (buff[i] == '*') {
1696 if (!i) {
1697 *search = buff + 1;
1698 type = MATCH_END_ONLY;
1699 } else {
1700 if (type == MATCH_END_ONLY)
1701 type = MATCH_MIDDLE_ONLY;
1702 else
1703 type = MATCH_FRONT_ONLY;
1704 buff[i] = 0;
1705 break;
1706 }
1707 }
1708 }
1709
1710 return type;
1711}
1712
1713static int ftrace_match(char *str, char *regex, int len, int type)1690static int ftrace_match(char *str, char *regex, int len, int type)
1714{1691{
1715 int matched = 0;1692 int matched = 0;
@@ -1758,7 +1735,7 @@ static void ftrace_match_records(char *buff, int len, int enable) · 42 unmodified lines
1758 int not;1735 int not;
1759 1736
1760 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;1737 flag = enable ? FTRACE_FL_FILTER : FTRACE_FL_NOTRACE;
1761 type = ftrace_setup_glob(buff, len, &search, &not);1738 type = filter_parse_regex(buff, len, &search, &not);
1762 1739
1763 search_len = strlen(search);1740 search_len = strlen(search);
1764 1741
@@ -1826,7 +1803,7 @@ static void ftrace_match_module_records(char *buff, char *mod, int enable) · 61 unmodified lines
1826 }1803 }
1827 1804
1828 if (strlen(buff)) {1805 if (strlen(buff)) {
1829 type = ftrace_setup_glob(buff, strlen(buff), &search, &not);1806 type = filter_parse_regex(buff, strlen(buff), &search, &not);
1830 search_len = strlen(search);1807 search_len = strlen(search);
1831 }1808 }
1832 1809
@@ -1991,7 +1968,7 @@ register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, · 158 unmodified lines
1991 int count = 0;1968 int count = 0;
1992 char *search;1969 char *search;
1993 1970
1994 type = ftrace_setup_glob(glob, strlen(glob), &search, &not);1971 type = filter_parse_regex(glob, strlen(glob), &search, &not);
1995 len = strlen(search);1972 len = strlen(search);
1996 1973
1997 /* we do not support '!' for function probes */1974 /* we do not support '!' for function probes */
@@ -2068,7 +2045,7 @@ __unregister_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops, · 70 unmodified lines
2068 else if (glob) {2045 else if (glob) {
2069 int not;2046 int not;
2070 2047
2071 type = ftrace_setup_glob(glob, strlen(glob), &search, &not);2048 type = filter_parse_regex(glob, strlen(glob), &search, &not);
2072 len = strlen(search);2049 len = strlen(search);
2073 2050
2074 /* we do not support '!' for function probes */2051 /* we do not support '!' for function probes */
@@ -2312,6 +2289,32 @@ static int __init set_ftrace_filter(char *str) · 237 unmodified lines
2312}2289}
2313__setup("ftrace_filter=", set_ftrace_filter);2290__setup("ftrace_filter=", set_ftrace_filter);
2314 2291
2292#ifdef CONFIG_FUNCTION_GRAPH_TRACER
2293static char ftrace_graph_buf[FTRACE_FILTER_SIZE] __initdata;
2294static int __init set_graph_function(char *str)
2295{
2296 strlcpy(ftrace_graph_buf, str, FTRACE_FILTER_SIZE);
2297 return 1;
2298}
2299__setup("ftrace_graph_filter=", set_graph_function);
2300
2301static void __init set_ftrace_early_graph(char *buf)
2302{
2303 int ret;
2304 char *func;
2305
2306 while (buf) {
2307 func = strsep(&buf, ",");
2308 /* we allow only one expression at a time */
2309 ret = ftrace_set_func(ftrace_graph_funcs, &ftrace_graph_count,
2310 func);
2311 if (ret)
2312 printk(KERN_DEBUG "ftrace: function %s not "
2313 "traceable\n", func);
2314 }
2315}
2316#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2317
2315static void __init set_ftrace_early_filter(char *buf, int enable)2318static void __init set_ftrace_early_filter(char *buf, int enable)
2316{2319{
2317 char *func;2320 char *func;
@@ -2328,6 +2331,10 @@ static void __init set_ftrace_early_filters(void) · 10 unmodified lines
2328 set_ftrace_early_filter(ftrace_filter_buf, 1);2331 set_ftrace_early_filter(ftrace_filter_buf, 1);
2329 if (ftrace_notrace_buf[0])2332 if (ftrace_notrace_buf[0])
2330 set_ftrace_early_filter(ftrace_notrace_buf, 0);2333 set_ftrace_early_filter(ftrace_notrace_buf, 0);
2334#ifdef CONFIG_FUNCTION_GRAPH_TRACER
2335 if (ftrace_graph_buf[0])
2336 set_ftrace_early_graph(ftrace_graph_buf);
2337#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
2331}2338}
2332 2339
2333static int2340static int
@@ -2513,7 +2520,7 @@ ftrace_set_func(unsigned long *array, int *idx, char *buffer) · 179 unmodified lines
2513 return -ENODEV;2520 return -ENODEV;
2514 2521
2515 /* decode regex */2522 /* decode regex */
2516 type = ftrace_setup_glob(buffer, strlen(buffer), &search, &not);2523 type = filter_parse_regex(buffer, strlen(buffer), &search, &not);
2517 if (not)2524 if (not)
2518 return -EINVAL;2525 return -EINVAL;
2519 2526
@@ -2624,7 +2631,7 @@ static __init int ftrace_init_dyn_debugfs(struct dentry *d_tracer) · 104 unmodified lines
2624 return 0;2631 return 0;
2625}2632}
2626 2633
2627static int ftrace_convert_nops(struct module *mod,2634static int ftrace_process_locs(struct module *mod,
2628 unsigned long *start,2635 unsigned long *start,
2629 unsigned long *end)2636 unsigned long *end)
2630{2637{
@@ -2684,7 +2691,7 @@ static void ftrace_init_module(struct module *mod, · 53 unmodified lines
2684{2691{
2685 if (ftrace_disabled || start == end)2692 if (ftrace_disabled || start == end)
2686 return;2693 return;
2687 ftrace_convert_nops(mod, start, end);2694 ftrace_process_locs(mod, start, end);
2688}2695}
2689 2696
2690static int ftrace_module_notify(struct notifier_block *self,2697static int ftrace_module_notify(struct notifier_block *self,
@@ -2745,7 +2752,7 @@ void __init ftrace_init(void) · 54 unmodified lines
2745 2752
2746 last_ftrace_enabled = ftrace_enabled = 1;2753 last_ftrace_enabled = ftrace_enabled = 1;
2747 2754
2748 ret = ftrace_convert_nops(NULL,2755 ret = ftrace_process_locs(NULL,
2749 __start_mcount_loc,2756 __start_mcount_loc,
2750 __stop_mcount_loc);2757 __stop_mcount_loc);
2751 2758
@@ -2778,23 +2785,6 @@ static inline void ftrace_startup_enable(int command) { } · 26 unmodified lines
2778# define ftrace_shutdown_sysctl() do { } while (0)2785# define ftrace_shutdown_sysctl() do { } while (0)
2779#endif /* CONFIG_DYNAMIC_FTRACE */2786#endif /* CONFIG_DYNAMIC_FTRACE */
2780 2787
2781static ssize_t
2782ftrace_pid_read(struct file *file, char __user *ubuf,
2783 size_t cnt, loff_t *ppos)
2784{
2785 char buf[64];
2786 int r;
2787
2788 if (ftrace_pid_trace == ftrace_swapper_pid)
2789 r = sprintf(buf, "swapper tasks\n");
2790 else if (ftrace_pid_trace)
2791 r = sprintf(buf, "%u\n", pid_vnr(ftrace_pid_trace));
2792 else
2793 r = sprintf(buf, "no pid\n");
2794
2795 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
2796}
2797
2798static void clear_ftrace_swapper(void)2788static void clear_ftrace_swapper(void)
2799{2789{
2800 struct task_struct *p;2790 struct task_struct *p;
@@ -2845,14 +2835,12 @@ static void set_ftrace_pid(struct pid *pid) · 44 unmodified lines
2845 rcu_read_unlock();2835 rcu_read_unlock();
2846}2836}
2847 2837
2848static void clear_ftrace_pid_task(struct pid **pid)2838static void clear_ftrace_pid_task(struct pid *pid)
2849{2839{
2850 if (*pid == ftrace_swapper_pid)2840 if (pid == ftrace_swapper_pid)
2851 clear_ftrace_swapper();2841 clear_ftrace_swapper();
2852 else2842 else
2853 clear_ftrace_pid(*pid);2843 clear_ftrace_pid(pid);
2854
2855 *pid = NULL;
2856}2844}
2857 2845
2858static void set_ftrace_pid_task(struct pid *pid)2846static void set_ftrace_pid_task(struct pid *pid)
@@ -2863,74 +2851,184 @@ static void set_ftrace_pid_task(struct pid *pid) · 4 unmodified lines
2863 set_ftrace_pid(pid);2851 set_ftrace_pid(pid);
2864}2852}
2865 2853
2866static ssize_t2854static int ftrace_pid_add(int p)
2867ftrace_pid_write(struct file *filp, const char __user *ubuf,
2868 size_t cnt, loff_t *ppos)
2869{2855{
2870 struct pid *pid;2856 struct pid *pid;
2871 char buf[64];2857 struct ftrace_pid *fpid;
2872 long val;2858 int ret = -EINVAL;
2873 int ret;
2874 2859
2875 if (cnt >= sizeof(buf))2860 mutex_lock(&ftrace_lock);
2876 return -EINVAL;
2877 2861
2878 if (copy_from_user(&buf, ubuf, cnt))2862 if (!p)
2879 return -EFAULT;2863 pid = ftrace_swapper_pid;
2864 else
2865 pid = find_get_pid(p);
2880 2866
2881 buf[cnt] = 0;2867 if (!pid)
2868 goto out;
2882 2869
2883 ret = strict_strtol(buf, 10, &val);2870 ret = 0;
2884 if (ret < 0)
2885 return ret;
2886 2871
2887 mutex_lock(&ftrace_lock);2872 list_for_each_entry(fpid, &ftrace_pids, list)
2888 if (val < 0) {2873 if (fpid->pid == pid)
2889 /* disable pid tracing */2874 goto out_put;
2890 if (!ftrace_pid_trace)
2891 goto out;
2892 2875
2893 clear_ftrace_pid_task(&ftrace_pid_trace);2876 ret = -ENOMEM;
2894 2877
2895 } else {2878 fpid = kmalloc(sizeof(*fpid), GFP_KERNEL);
2896 /* swapper task is special */2879 if (!fpid)
2897 if (!val) {2880 goto out_put;
2898 pid = ftrace_swapper_pid;
2899 if (pid == ftrace_pid_trace)
2900 goto out;
2901 } else {
2902 pid = find_get_pid(val);
2903 2881
2904 if (pid == ftrace_pid_trace) {2882 list_add(&fpid->list, &ftrace_pids);
2905 put_pid(pid);2883 fpid->pid = pid;
2906 goto out;
2907 }
2908 }
2909 2884
2910 if (ftrace_pid_trace)2885 set_ftrace_pid_task(pid);
2911 clear_ftrace_pid_task(&ftrace_pid_trace);
2912 2886
2913 if (!pid)2887 ftrace_update_pid_func();
2914 goto out;2888 ftrace_startup_enable(0);
2889
2890 mutex_unlock(&ftrace_lock);
2891 return 0;
2892
2893out_put:
2894 if (pid != ftrace_swapper_pid)
2895 put_pid(pid);
2915 2896
2916 ftrace_pid_trace = pid;2897out:
2898 mutex_unlock(&ftrace_lock);
2899 return ret;
2900}
2901
2902static void ftrace_pid_reset(void)
2903{
2904 struct ftrace_pid *fpid, *safe;
2917 2905
2918 set_ftrace_pid_task(ftrace_pid_trace);2906 mutex_lock(&ftrace_lock);
2907 list_for_each_entry_safe(fpid, safe, &ftrace_pids, list) {
2908 struct pid *pid = fpid->pid;
2909
2910 clear_ftrace_pid_task(pid);
2911
2912 list_del(&fpid->list);
2913 kfree(fpid);
2919 }2914 }
2920 2915
2921 /* update the function call */
2922 ftrace_update_pid_func();2916 ftrace_update_pid_func();
2923 ftrace_startup_enable(0);2917 ftrace_startup_enable(0);
2924 2918
2925 out:
2926 mutex_unlock(&ftrace_lock);2919 mutex_unlock(&ftrace_lock);
2920}
2927 2921
2928 return cnt;2922static void *fpid_start(struct seq_file *m, loff_t *pos)
2923{
2924 mutex_lock(&ftrace_lock);
2925
2926 if (list_empty(&ftrace_pids) && (!*pos))
2927 return (void *) 1;
2928
2929 return seq_list_start(&ftrace_pids, *pos);
2930}
2931
2932static void *fpid_next(struct seq_file *m, void *v, loff_t *pos)
2933{
2934 if (v == (void *)1)
2935 return NULL;
2936
2937 return seq_list_next(v, &ftrace_pids, pos);
2938}
2939
2940static void fpid_stop(struct seq_file *m, void *p)
2941{
2942 mutex_unlock(&ftrace_lock);
2943}
2944
2945static int fpid_show(struct seq_file *m, void *v)
2946{
2947 const struct ftrace_pid *fpid = list_entry(v, struct ftrace_pid, list);
2948
2949 if (v == (void *)1) {
2950 seq_printf(m, "no pid\n");
2951 return 0;
2952 }
2953
2954 if (fpid->pid == ftrace_swapper_pid)
2955 seq_printf(m, "swapper tasks\n");
2956 else
2957 seq_printf(m, "%u\n", pid_vnr(fpid->pid));
2958
2959 return 0;
2960}
2961
2962static const struct seq_operations ftrace_pid_sops = {
2963 .start = fpid_start,
2964 .next = fpid_next,
2965 .stop = fpid_stop,
2966 .show = fpid_show,
2967};
2968
2969static int
2970ftrace_pid_open(struct inode *inode, struct file *file)
2971{
2972 int ret = 0;
2973
2974 if ((file->f_mode & FMODE_WRITE) &&
2975 (file->f_flags & O_TRUNC))
2976 ftrace_pid_reset();
2977
2978 if (file->f_mode & FMODE_READ)
2979 ret = seq_open(file, &ftrace_pid_sops);
2980
2981 return ret;
2982}
2983
2984static ssize_t
2985ftrace_pid_write(struct file *filp, const char __user *ubuf,
2986 size_t cnt, loff_t *ppos)
2987{
2988 char buf[64], *tmp;
2989 long val;
2990 int ret;
2991
2992 if (cnt >= sizeof(buf))
2993 return -EINVAL;
2994
2995 if (copy_from_user(&buf, ubuf, cnt))
2996 return -EFAULT;
2997
2998 buf[cnt] = 0;
2999
3000 /*
3001 * Allow "echo > set_ftrace_pid" or "echo -n '' > set_ftrace_pid"
3002 * to clean the filter quietly.
3003 */
3004 tmp = strstrip(buf);
3005 if (strlen(tmp) == 0)
3006 return 1;
3007
3008 ret = strict_strtol(tmp, 10, &val);
3009 if (ret < 0)
3010 return ret;
3011
3012 ret = ftrace_pid_add(val);
3013
3014 return ret ? ret : cnt;
3015}
3016
3017static int
3018ftrace_pid_release(struct inode *inode, struct file *file)
3019{
3020 if (file->f_mode & FMODE_READ)
3021 seq_release(inode, file);
3022
3023 return 0;
2929}3024}
2930 3025
2931static const struct file_operations ftrace_pid_fops = {3026static const struct file_operations ftrace_pid_fops = {
2932 .read = ftrace_pid_read,3027 .open = ftrace_pid_open,
2933 .write = ftrace_pid_write,3028 .write = ftrace_pid_write,
3029 .read = seq_read,
3030 .llseek = seq_lseek,
3031 .release = ftrace_pid_release,
2934};3032};
2935 3033
2936static __init int ftrace_init_debugfs(void)3034static __init int ftrace_init_debugfs(void)
@@ -3293,4 +3391,3 @@ void ftrace_graph_stop(void) · 356 unmodified lines
3293 ftrace_stop();3391 ftrace_stop();
3294}3392}
3295#endif3393#endif
3296
kernel/trace/ring_buffer.c+3−6
@@ -1787,9 +1787,9 @@ rb_reset_tail(struct ring_buffer_per_cpu *cpu_buffer, · 1786 unmodified lines
1787static struct ring_buffer_event *1787static struct ring_buffer_event *
1788rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,1788rb_move_tail(struct ring_buffer_per_cpu *cpu_buffer,
1789 unsigned long length, unsigned long tail,1789 unsigned long length, unsigned long tail,
1790 struct buffer_page *commit_page,
1791 struct buffer_page *tail_page, u64 *ts)1790 struct buffer_page *tail_page, u64 *ts)
1792{1791{
1792 struct buffer_page *commit_page = cpu_buffer->commit_page;
1793 struct ring_buffer *buffer = cpu_buffer->buffer;1793 struct ring_buffer *buffer = cpu_buffer->buffer;
1794 struct buffer_page *next_page;1794 struct buffer_page *next_page;
1795 int ret;1795 int ret;
@@ -1892,13 +1892,10 @@ static struct ring_buffer_event * · 96 unmodified lines
1892__rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,1892__rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer,
1893 unsigned type, unsigned long length, u64 *ts)1893 unsigned type, unsigned long length, u64 *ts)
1894{1894{
1895 struct buffer_page *tail_page, *commit_page;1895 struct buffer_page *tail_page;
1896 struct ring_buffer_event *event;1896 struct ring_buffer_event *event;
1897 unsigned long tail, write;1897 unsigned long tail, write;
1898 1898
1899 commit_page = cpu_buffer->commit_page;
1900 /* we just need to protect against interrupts */
1901 barrier();
1902 tail_page = cpu_buffer->tail_page;1899 tail_page = cpu_buffer->tail_page;
1903 write = local_add_return(length, &tail_page->write);1900 write = local_add_return(length, &tail_page->write);
1904 1901
@@ -1909,7 +1906,7 @@ __rb_reserve_next(struct ring_buffer_per_cpu *cpu_buffer, · 4 unmodified lines
1909 /* See if we shot pass the end of this buffer page */1906 /* See if we shot pass the end of this buffer page */
1910 if (write > BUF_PAGE_SIZE)1907 if (write > BUF_PAGE_SIZE)
1911 return rb_move_tail(cpu_buffer, length, tail,1908 return rb_move_tail(cpu_buffer, length, tail,
1912 commit_page, tail_page, ts);1909 tail_page, ts);
1913 1910
1914 /* We reserved something on the buffer */1911 /* We reserved something on the buffer */
1915 1912
kernel/trace/ring_buffer_benchmark.c+76−9
@@ -35,6 +35,28 @@ static int disable_reader; · 34 unmodified lines
35module_param(disable_reader, uint, 0644);35module_param(disable_reader, uint, 0644);
36MODULE_PARM_DESC(disable_reader, "only run producer");36MODULE_PARM_DESC(disable_reader, "only run producer");
37 37
38static int write_iteration = 50;
39module_param(write_iteration, uint, 0644);
40MODULE_PARM_DESC(write_iteration, "# of writes between timestamp readings");
41
42static int producer_nice = 19;
43static int consumer_nice = 19;
44
45static int producer_fifo = -1;
46static int consumer_fifo = -1;
47
48module_param(producer_nice, uint, 0644);
49MODULE_PARM_DESC(producer_nice, "nice prio for producer");
50
51module_param(consumer_nice, uint, 0644);
52MODULE_PARM_DESC(consumer_nice, "nice prio for consumer");
53
54module_param(producer_fifo, uint, 0644);
55MODULE_PARM_DESC(producer_fifo, "fifo prio for producer");
56
57module_param(consumer_fifo, uint, 0644);
58MODULE_PARM_DESC(consumer_fifo, "fifo prio for consumer");
59
38static int read_events;60static int read_events;
39 61
40static int kill_test;62static int kill_test;
@@ -208,15 +230,18 @@ static void ring_buffer_producer(void) · 167 unmodified lines
208 do {230 do {
209 struct ring_buffer_event *event;231 struct ring_buffer_event *event;
210 int *entry;232 int *entry;
211 233 int i;
212 event = ring_buffer_lock_reserve(buffer, 10);234
213 if (!event) {235 for (i = 0; i < write_iteration; i++) {
214 missed++;236 event = ring_buffer_lock_reserve(buffer, 10);
215 } else {237 if (!event) {
216 hit++;238 missed++;
217 entry = ring_buffer_event_data(event);239 } else {
218 *entry = smp_processor_id();240 hit++;
219 ring_buffer_unlock_commit(buffer, event);241 entry = ring_buffer_event_data(event);
242 *entry = smp_processor_id();
243 ring_buffer_unlock_commit(buffer, event);
244 }
220 }245 }
221 do_gettimeofday(&end_tv);246 do_gettimeofday(&end_tv);
222 247
@@ -263,6 +288,27 @@ static void ring_buffer_producer(void) · 40 unmodified lines
263 288
264 if (kill_test)289 if (kill_test)
265 trace_printk("ERROR!\n");290 trace_printk("ERROR!\n");
291
292 if (!disable_reader) {
293 if (consumer_fifo < 0)
294 trace_printk("Running Consumer at nice: %d\n",
295 consumer_nice);
296 else
297 trace_printk("Running Consumer at SCHED_FIFO %d\n",
298 consumer_fifo);
299 }
300 if (producer_fifo < 0)
301 trace_printk("Running Producer at nice: %d\n",
302 producer_nice);
303 else
304 trace_printk("Running Producer at SCHED_FIFO %d\n",
305 producer_fifo);
306
307 /* Let the user know that the test is running at low priority */
308 if (producer_fifo < 0 && consumer_fifo < 0 &&
309 producer_nice == 19 && consumer_nice == 19)
310 trace_printk("WARNING!!! This test is running at lowest priority.\n");
311
266 trace_printk("Time: %lld (usecs)\n", time);312 trace_printk("Time: %lld (usecs)\n", time);
267 trace_printk("Overruns: %lld\n", overruns);313 trace_printk("Overruns: %lld\n", overruns);
268 if (disable_reader)314 if (disable_reader)
@@ -392,6 +438,27 @@ static int __init ring_buffer_benchmark_init(void) · 123 unmodified lines
392 if (IS_ERR(producer))438 if (IS_ERR(producer))
393 goto out_kill;439 goto out_kill;
394 440
441 /*
442 * Run them as low-prio background tasks by default:
443 */
444 if (!disable_reader) {
445 if (consumer_fifo >= 0) {
446 struct sched_param param = {
447 .sched_priority = consumer_fifo
448 };
449 sched_setscheduler(consumer, SCHED_FIFO, &param);
450 } else
451 set_user_nice(consumer, consumer_nice);
452 }
453
454 if (producer_fifo >= 0) {
455 struct sched_param param = {
456 .sched_priority = consumer_fifo
457 };
458 sched_setscheduler(producer, SCHED_FIFO, &param);
459 } else
460 set_user_nice(producer, producer_nice);
461
395 return 0;462 return 0;
396 463
397 out_kill:464 out_kill:
kernel/trace/trace.c+2−2
@@ -129,7 +129,7 @@ static int tracing_set_tracer(const char *buf); · 128 unmodified lines
129static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata;129static char bootup_tracer_buf[MAX_TRACER_SIZE] __initdata;
130static char *default_bootup_tracer;130static char *default_bootup_tracer;
131 131
132static int __init set_ftrace(char *str)132static int __init set_cmdline_ftrace(char *str)
133{133{
134 strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);134 strncpy(bootup_tracer_buf, str, MAX_TRACER_SIZE);
135 default_bootup_tracer = bootup_tracer_buf;135 default_bootup_tracer = bootup_tracer_buf;
@@ -137,7 +137,7 @@ static int __init set_ftrace(char *str) · 1 unmodified line
137 ring_buffer_expanded = 1;137 ring_buffer_expanded = 1;
138 return 1;138 return 1;
139}139}
140__setup("ftrace=", set_ftrace);140__setup("ftrace=", set_cmdline_ftrace);
141 141
142static int __init set_ftrace_dump_on_oops(char *str)142static int __init set_ftrace_dump_on_oops(char *str)
143{143{
kernel/trace/trace.h+29−15
@@ -483,10 +483,6 @@ static inline int ftrace_graph_addr(unsigned long addr) · 482 unmodified lines
483 return 0;483 return 0;
484}484}
485#else485#else
486static inline int ftrace_trace_addr(unsigned long addr)
487{
488 return 1;
489}
490static inline int ftrace_graph_addr(unsigned long addr)486static inline int ftrace_graph_addr(unsigned long addr)
491{487{
492 return 1;488 return 1;
@@ -500,12 +496,12 @@ print_graph_function(struct trace_iterator *iter) · 7 unmodified lines
500}496}
501#endif /* CONFIG_FUNCTION_GRAPH_TRACER */497#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
502 498
503extern struct pid *ftrace_pid_trace;499extern struct list_head ftrace_pids;
504 500
505#ifdef CONFIG_FUNCTION_TRACER501#ifdef CONFIG_FUNCTION_TRACER
506static inline int ftrace_trace_task(struct task_struct *task)502static inline int ftrace_trace_task(struct task_struct *task)
507{503{
508 if (!ftrace_pid_trace)504 if (list_empty(&ftrace_pids))
509 return 1;505 return 1;
510 506
511 return test_tsk_trace_trace(task);507 return test_tsk_trace_trace(task);
@@ -699,22 +695,40 @@ struct event_subsystem { · 187 unmodified lines
699};695};
700 696
701struct filter_pred;697struct filter_pred;
698struct regex;
702 699
703typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,700typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
704 int val1, int val2);701 int val1, int val2);
705 702
703typedef int (*regex_match_func)(char *str, struct regex *r, int len);
704
705enum regex_type {
706 MATCH_FULL,
707 MATCH_FRONT_ONLY,
708 MATCH_MIDDLE_ONLY,
709 MATCH_END_ONLY,
710};
711
712struct regex {
713 char pattern[MAX_FILTER_STR_VAL];
714 int len;
715 int field_len;
716 regex_match_func match;
717};
718
706struct filter_pred {719struct filter_pred {
707 filter_pred_fn_t fn;720 filter_pred_fn_t fn;
708 u64 val;721 u64 val;
709 char str_val[MAX_FILTER_STR_VAL];722 struct regex regex;
710 int str_len;723 char *field_name;
711 char *field_name;724 int offset;
712 int offset;725 int not;
713 int not;726 int op;
714 int op;727 int pop_n;
715 int pop_n;
716};728};
717 729
730extern enum regex_type
731filter_parse_regex(char *buff, int len, char **search, int *not);
718extern void print_event_filter(struct ftrace_event_call *call,732extern void print_event_filter(struct ftrace_event_call *call,
719 struct trace_seq *s);733 struct trace_seq *s);
720extern int apply_event_filter(struct ftrace_event_call *call,734extern int apply_event_filter(struct ftrace_event_call *call,
kernel/trace/trace_clock.c+5−3
@@ -20,6 +20,8 @@ · 19 unmodified lines
20#include <linux/ktime.h>20#include <linux/ktime.h>
21#include <linux/trace_clock.h>21#include <linux/trace_clock.h>
22 22
23#include "trace.h"
24
23/*25/*
24 * trace_clock_local(): the simplest and least coherent tracing clock.26 * trace_clock_local(): the simplest and least coherent tracing clock.
25 *27 *
@@ -28,17 +30,17 @@ · 2 unmodified lines
28 */30 */
29u64 notrace trace_clock_local(void)31u64 notrace trace_clock_local(void)
30{32{
31 unsigned long flags;
32 u64 clock;33 u64 clock;
34 int resched;
33 35
34 /*36 /*
35 * sched_clock() is an architecture implemented, fast, scalable,37 * sched_clock() is an architecture implemented, fast, scalable,
36 * lockless clock. It is not guaranteed to be coherent across38 * lockless clock. It is not guaranteed to be coherent across
37 * CPUs, nor across CPU idle events.39 * CPUs, nor across CPU idle events.
38 */40 */
39 raw_local_irq_save(flags);41 resched = ftrace_preempt_disable();
40 clock = sched_clock();42 clock = sched_clock();
41 raw_local_irq_restore(flags);43 ftrace_preempt_enable(resched);
42 44
43 return clock;45 return clock;
44}46}
kernel/trace/trace_events.c+11−12
@@ -878,9 +878,9 @@ event_subsystem_dir(const char *name, struct dentry *d_events) · 877 unmodified lines
878 "'%s/filter' entry\n", name);878 "'%s/filter' entry\n", name);
879 }879 }
880 880
881 entry = trace_create_file("enable", 0644, system->entry,881 trace_create_file("enable", 0644, system->entry,
882 (void *)system->name,882 (void *)system->name,
883 &ftrace_system_enable_fops);883 &ftrace_system_enable_fops);
884 884
885 return system->entry;885 return system->entry;
886}886}
@@ -892,7 +892,6 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, · 5 unmodified lines
892 const struct file_operations *filter,892 const struct file_operations *filter,
893 const struct file_operations *format)893 const struct file_operations *format)
894{894{
895 struct dentry *entry;
896 int ret;895 int ret;
897 896
898 /*897 /*
@@ -910,12 +909,12 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, · 11 unmodified lines
910 }909 }
911 910
912 if (call->regfunc)911 if (call->regfunc)
913 entry = trace_create_file("enable", 0644, call->dir, call,912 trace_create_file("enable", 0644, call->dir, call,
914 enable);913 enable);
915 914
916 if (call->id && call->profile_enable)915 if (call->id && call->profile_enable)
917 entry = trace_create_file("id", 0444, call->dir, call,916 trace_create_file("id", 0444, call->dir, call,
918 id);917 id);
919 918
920 if (call->define_fields) {919 if (call->define_fields) {
921 ret = call->define_fields(call);920 ret = call->define_fields(call);
@@ -924,16 +923,16 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, · 2 unmodified lines
924 " events/%s\n", call->name);923 " events/%s\n", call->name);
925 return ret;924 return ret;
926 }925 }
927 entry = trace_create_file("filter", 0644, call->dir, call,926 trace_create_file("filter", 0644, call->dir, call,
928 filter);927 filter);
929 }928 }
930 929
931 /* A trace may not want to export its format */930 /* A trace may not want to export its format */
932 if (!call->show_format)931 if (!call->show_format)
933 return 0;932 return 0;
934 933
935 entry = trace_create_file("format", 0444, call->dir, call,934 trace_create_file("format", 0444, call->dir, call,
936 format);935 format);
937 936
938 return 0;937 return 0;
939}938}
kernel/trace/trace_events_filter.c+137−18
@@ -18,8 +18,6 @@ · 17 unmodified lines
18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
19 */19 */
20 20
21#include <linux/debugfs.h>
22#include <linux/uaccess.h>
23#include <linux/module.h>21#include <linux/module.h>
24#include <linux/ctype.h>22#include <linux/ctype.h>
25#include <linux/mutex.h>23#include <linux/mutex.h>
@@ -197,9 +195,9 @@ static int filter_pred_string(struct filter_pred *pred, void *event, · 171 unmodified lines
197 char *addr = (char *)(event + pred->offset);195 char *addr = (char *)(event + pred->offset);
198 int cmp, match;196 int cmp, match;
199 197
200 cmp = strncmp(addr, pred->str_val, pred->str_len);198 cmp = pred->regex.match(addr, &pred->regex, pred->regex.field_len);
201 199
202 match = (!cmp) ^ pred->not;200 match = cmp ^ pred->not;
203 201
204 return match;202 return match;
205}203}
@@ -211,9 +209,9 @@ static int filter_pred_pchar(struct filter_pred *pred, void *event, · 5 unmodified lines
211 char **addr = (char **)(event + pred->offset);209 char **addr = (char **)(event + pred->offset);
212 int cmp, match;210 int cmp, match;
213 211
214 cmp = strncmp(*addr, pred->str_val, pred->str_len);212 cmp = pred->regex.match(*addr, &pred->regex, pred->regex.field_len);
215 213
216 match = (!cmp) ^ pred->not;214 match = cmp ^ pred->not;
217 215
218 return match;216 return match;
219}217}
@@ -237,9 +235,9 @@ static int filter_pred_strloc(struct filter_pred *pred, void *event, · 17 unmodified lines
237 char *addr = (char *)(event + str_loc);235 char *addr = (char *)(event + str_loc);
238 int cmp, match;236 int cmp, match;
239 237
240 cmp = strncmp(addr, pred->str_val, str_len);238 cmp = pred->regex.match(addr, &pred->regex, str_len);
241 239
242 match = (!cmp) ^ pred->not;240 match = cmp ^ pred->not;
243 241
244 return match;242 return match;
245}243}
@@ -250,6 +248,124 @@ static int filter_pred_none(struct filter_pred *pred, void *event, · 4 unmodified lines
250 return 0;248 return 0;
251}249}
252 250
251/* Basic regex callbacks */
252static int regex_match_full(char *str, struct regex *r, int len)
253{
254 if (strncmp(str, r->pattern, len) == 0)
255 return 1;
256 return 0;
257}
258
259static int regex_match_front(char *str, struct regex *r, int len)
260{
261 if (strncmp(str, r->pattern, len) == 0)
262 return 1;
263 return 0;
264}
265
266static int regex_match_middle(char *str, struct regex *r, int len)
267{
268 if (strstr(str, r->pattern))
269 return 1;
270 return 0;
271}
272
273static int regex_match_end(char *str, struct regex *r, int len)
274{
275 char *ptr = strstr(str, r->pattern);
276
277 if (ptr && (ptr[r->len] == 0))
278 return 1;
279 return 0;
280}
281
282/**
283 * filter_parse_regex - parse a basic regex
284 * @buff: the raw regex
285 * @len: length of the regex
286 * @search: will point to the beginning of the string to compare
287 * @not: tell whether the match will have to be inverted
288 *
289 * This passes in a buffer containing a regex and this function will
290 * set search to point to the search part of the buffer and
291 * return the type of search it is (see enum above).
292 * This does modify buff.
293 *
294 * Returns enum type.
295 * search returns the pointer to use for comparison.
296 * not returns 1 if buff started with a '!'
297 * 0 otherwise.
298 */
299enum regex_type filter_parse_regex(char *buff, int len, char **search, int *not)
300{
301 int type = MATCH_FULL;
302 int i;
303
304 if (buff[0] == '!') {
305 *not = 1;
306 buff++;
307 len--;
308 } else
309 *not = 0;
310
311 *search = buff;
312
313 for (i = 0; i < len; i++) {
314 if (buff[i] == '*') {
315 if (!i) {
316 *search = buff + 1;
317 type = MATCH_END_ONLY;
318 } else {
319 if (type == MATCH_END_ONLY)
320 type = MATCH_MIDDLE_ONLY;
321 else
322 type = MATCH_FRONT_ONLY;
323 buff[i] = 0;
324 break;
325 }
326 }
327 }
328
329 return type;
330}
331
332static int filter_build_regex(struct filter_pred *pred)
333{
334 struct regex *r = &pred->regex;
335 char *search, *dup;
336 enum regex_type type;
337 int not;
338
339 type = filter_parse_regex(r->pattern, r->len, &search, &not);
340 dup = kstrdup(search, GFP_KERNEL);
341 if (!dup)
342 return -ENOMEM;
343
344 strcpy(r->pattern, dup);
345 kfree(dup);
346
347 r->len = strlen(r->pattern);
348
349 switch (type) {
350 case MATCH_FULL:
351 r->match = regex_match_full;
352 break;
353 case MATCH_FRONT_ONLY:
354 r->match = regex_match_front;
355 break;
356 case MATCH_MIDDLE_ONLY:
357 r->match = regex_match_middle;
358 break;
359 case MATCH_END_ONLY:
360 r->match = regex_match_end;
361 break;
362 }
363
364 pred->not ^= not;
365
366 return 0;
367}
368
253/* return 1 if event matches, 0 otherwise (discard) */369/* return 1 if event matches, 0 otherwise (discard) */
254int filter_match_preds(struct ftrace_event_call *call, void *rec)370int filter_match_preds(struct ftrace_event_call *call, void *rec)
255{371{
@@ -396,7 +512,7 @@ static void filter_clear_pred(struct filter_pred *pred) · 140 unmodified lines
396{512{
397 kfree(pred->field_name);513 kfree(pred->field_name);
398 pred->field_name = NULL;514 pred->field_name = NULL;
399 pred->str_len = 0;515 pred->regex.len = 0;
400}516}
401 517
402static int filter_set_pred(struct filter_pred *dest,518static int filter_set_pred(struct filter_pred *dest,
@@ -660,21 +776,24 @@ static int filter_add_pred(struct filter_parse_state *ps, · 257 unmodified lines
660 }776 }
661 777
662 if (is_string_field(field)) {778 if (is_string_field(field)) {
663 pred->str_len = field->size;779 ret = filter_build_regex(pred);
780 if (ret)
781 return ret;
664 782
665 if (field->filter_type == FILTER_STATIC_STRING)783 if (field->filter_type == FILTER_STATIC_STRING) {
666 fn = filter_pred_string;784 fn = filter_pred_string;
667 else if (field->filter_type == FILTER_DYN_STRING)785 pred->regex.field_len = field->size;
668 fn = filter_pred_strloc;786 } else if (field->filter_type == FILTER_DYN_STRING)
787 fn = filter_pred_strloc;
669 else {788 else {
670 fn = filter_pred_pchar;789 fn = filter_pred_pchar;
671 pred->str_len = strlen(pred->str_val);790 pred->regex.field_len = strlen(pred->regex.pattern);
672 }791 }
673 } else {792 } else {
674 if (field->is_signed)793 if (field->is_signed)
675 ret = strict_strtoll(pred->str_val, 0, &val);794 ret = strict_strtoll(pred->regex.pattern, 0, &val);
676 else795 else
677 ret = strict_strtoull(pred->str_val, 0, &val);796 ret = strict_strtoull(pred->regex.pattern, 0, &val);
678 if (ret) {797 if (ret) {
679 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);798 parse_error(ps, FILT_ERR_ILLEGAL_INTVAL, 0);
680 return -EINVAL;799 return -EINVAL;
@@ -1045,8 +1164,8 @@ static struct filter_pred *create_pred(int op, char *operand1, char *operand2) · 364 unmodified lines
1045 return NULL;1164 return NULL;
1046 }1165 }
1047 1166
1048 strcpy(pred->str_val, operand2);1167 strcpy(pred->regex.pattern, operand2);
1049 pred->str_len = strlen(operand2);1168 pred->regex.len = strlen(pred->regex.pattern);
1050 1169
1051 pred->op = op;1170 pred->op = op;
1052 1171
kernel/trace/trace_export.c+2−2
@@ -48,11 +48,11 @@ · 47 unmodified lines
48struct ____ftrace_##name { \48struct ____ftrace_##name { \
49 tstruct \49 tstruct \
50}; \50}; \
51static void __used ____ftrace_check_##name(void) \51static void __always_unused ____ftrace_check_##name(void) \
52{ \52{ \
53 struct ____ftrace_##name *__entry = NULL; \53 struct ____ftrace_##name *__entry = NULL; \
54 \54 \
55 /* force cmpile-time check on F_printk() */ \55 /* force compile-time check on F_printk() */ \
56 printk(print); \56 printk(print); \
57}57}
58 58
kernel/trace/trace_syscalls.c+86−0
@@ -14,6 +14,69 @@ static int sys_refcount_exit; · 13 unmodified lines
14static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);14static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls);
15static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);15static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls);
16 16
17extern unsigned long __start_syscalls_metadata[];
18extern unsigned long __stop_syscalls_metadata[];
19
20static struct syscall_metadata **syscalls_metadata;
21
22static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
23{
24 struct syscall_metadata *start;
25 struct syscall_metadata *stop;
26 char str[KSYM_SYMBOL_LEN];
27
28
29 start = (struct syscall_metadata *)__start_syscalls_metadata;
30 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
31 kallsyms_lookup(syscall, NULL, NULL, NULL, str);
32
33 for ( ; start < stop; start++) {
34 /*
35 * Only compare after the "sys" prefix. Archs that use
36 * syscall wrappers may have syscalls symbols aliases prefixed
37 * with "SyS" instead of "sys", leading to an unwanted
38 * mismatch.
39 */
40 if (start->name && !strcmp(start->name + 3, str + 3))
41 return start;
42 }
43 return NULL;
44}
45
46static struct syscall_metadata *syscall_nr_to_meta(int nr)
47{
48 if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
49 return NULL;
50
51 return syscalls_metadata[nr];
52}
53
54int syscall_name_to_nr(char *name)
55{
56 int i;
57
58 if (!syscalls_metadata)
59 return -1;
60
61 for (i = 0; i < NR_syscalls; i++) {
62 if (syscalls_metadata[i]) {
63 if (!strcmp(syscalls_metadata[i]->name, name))
64 return i;
65 }
66 }
67 return -1;
68}
69
70void set_syscall_enter_id(int num, int id)
71{
72 syscalls_metadata[num]->enter_id = id;
73}
74
75void set_syscall_exit_id(int num, int id)
76{
77 syscalls_metadata[num]->exit_id = id;
78}
79
17enum print_line_t80enum print_line_t
18print_syscall_enter(struct trace_iterator *iter, int flags)81print_syscall_enter(struct trace_iterator *iter, int flags)
19{82{
@@ -375,6 +438,29 @@ struct trace_event event_syscall_exit = { · 355 unmodified lines
375 .trace = print_syscall_exit,438 .trace = print_syscall_exit,
376};439};
377 440
441int __init init_ftrace_syscalls(void)
442{
443 struct syscall_metadata *meta;
444 unsigned long addr;
445 int i;
446
447 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
448 NR_syscalls, GFP_KERNEL);
449 if (!syscalls_metadata) {
450 WARN_ON(1);
451 return -ENOMEM;
452 }
453
454 for (i = 0; i < NR_syscalls; i++) {
455 addr = arch_syscall_addr(i);
456 meta = find_syscall_meta(addr);
457 syscalls_metadata[i] = meta;
458 }
459
460 return 0;
461}
462core_initcall(init_ftrace_syscalls);
463
378#ifdef CONFIG_EVENT_PROFILE464#ifdef CONFIG_EVENT_PROFILE
379 465
380static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls);466static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls);
lib/kernel_lock.c+14−6
@@ -5,10 +5,13 @@ · 4 unmodified lines
5 * relegated to obsolescence, but used by various less5 * relegated to obsolescence, but used by various less
6 * important (or lazy) subsystems.6 * important (or lazy) subsystems.
7 */7 */
8#include <linux/smp_lock.h>
9#include <linux/module.h>8#include <linux/module.h>
10#include <linux/kallsyms.h>9#include <linux/kallsyms.h>
11#include <linux/semaphore.h>10#include <linux/semaphore.h>
11#include <linux/smp_lock.h>
12
13#define CREATE_TRACE_POINTS
14#include <trace/events/bkl.h>
12 15
13/*16/*
14 * The 'big kernel lock'17 * The 'big kernel lock'
@@ -113,21 +116,26 @@ static inline void __unlock_kernel(void) · 98 unmodified lines
113 * This cannot happen asynchronously, so we only need to116 * This cannot happen asynchronously, so we only need to
114 * worry about other CPU's.117 * worry about other CPU's.
115 */118 */
116void __lockfunc lock_kernel(void)119void __lockfunc _lock_kernel(const char *func, const char *file, int line)
117{120{
118 int depth = current->lock_depth+1;121 int depth = current->lock_depth + 1;
122
123 trace_lock_kernel(func, file, line);
124
119 if (likely(!depth))125 if (likely(!depth))
120 __lock_kernel();126 __lock_kernel();
121 current->lock_depth = depth;127 current->lock_depth = depth;
122}128}
123 129
124void __lockfunc unlock_kernel(void)130void __lockfunc _unlock_kernel(const char *func, const char *file, int line)
125{131{
126 BUG_ON(current->lock_depth < 0);132 BUG_ON(current->lock_depth < 0);
127 if (likely(--current->lock_depth < 0))133 if (likely(--current->lock_depth < 0))
128 __unlock_kernel();134 __unlock_kernel();
135
136 trace_unlock_kernel(func, file, line);
129}137}
130 138
131EXPORT_SYMBOL(lock_kernel);139EXPORT_SYMBOL(_lock_kernel);
132EXPORT_SYMBOL(unlock_kernel);140EXPORT_SYMBOL(_unlock_kernel);
133 141
scripts/recordmcount.pl+120−99
@@ -6,77 +6,93 @@ · 5 unmodified lines
6# all the offsets to the calls to mcount.6# all the offsets to the calls to mcount.
7#7#
8#8#
9# What we want to end up with is a section in vmlinux called9# What we want to end up with this is that each object file will have a
10# __mcount_loc that contains a list of pointers to all the10# section called __mcount_loc that will hold the list of pointers to mcount
11# call sites in the kernel that call mcount. Later on boot up, the kernel11# callers. After final linking, the vmlinux will have within .init.data the
12# will read this list, save the locations and turn them into nops.12# list of all callers to mcount between __start_mcount_loc and __stop_mcount_loc.
13# When tracing or profiling is later enabled, these locations will then13# Later on boot up, the kernel will read this list, save the locations and turn
14# be converted back to pointers to some function.14# them into nops. When tracing or profiling is later enabled, these locations
15# will then be converted back to pointers to some function.
15#16#
16# This is no easy feat. This script is called just after the original17# This is no easy feat. This script is called just after the original
17# object is compiled and before it is linked.18# object is compiled and before it is linked.
18#19#
19# The references to the call sites are offsets from the section of text20# When parse this object file using 'objdump', the references to the call
20# that the call site is in. Hence, all functions in a section that21# sites are offsets from the section that the call site is in. Hence, all
21# has a call site to mcount, will have the offset from the beginning of22# functions in a section that has a call site to mcount, will have the
22# the section and not the beginning of the function.23# offset from the beginning of the section and not the beginning of the
24# function.
25#
26# But where this section will reside finally in vmlinx is undetermined at
27# this point. So we can't use this kind of offsets to record the final
28# address of this call site.
29#
30# The trick is to change the call offset referring the start of a section to
31# referring a function symbol in this section. During the link step, 'ld' will
32# compute the final address according to the information we record.
23#33#
24# The trick is to find a way to record the beginning of the section.
25# The way we do this is to look at the first function in the section
26# which will also be the location of that section after final link.
27# e.g.34# e.g.
28#35#
29# .section ".sched.text", "ax"36# .section ".sched.text", "ax"
30# .globl my_func
31# my_func:
32# [...]37# [...]
33# call mcount (offset: 0x5)38# func1:
39# [...]
40# call mcount (offset: 0x10)
34# [...]41# [...]
35# ret42# ret
36# other_func:43# .globl fun2
44# func2: (offset: 0x20)
37# [...]45# [...]
38# call mcount (offset: 0x1b)46# [...]
47# ret
48# func3:
49# [...]
50# call mcount (offset: 0x30)
39# [...]51# [...]
40#52#
41# Both relocation offsets for the mcounts in the above example will be53# Both relocation offsets for the mcounts in the above example will be
42# offset from .sched.text. If we make another file called tmp.s with:54# offset from .sched.text. If we choose global symbol func2 as a reference and
55# make another file called tmp.s with the new offsets:
43#56#
44# .section __mcount_loc57# .section __mcount_loc
45# .quad my_func + 0x558# .quad func2 - 0x10
46# .quad my_func + 0x1b59# .quad func2 + 0x10
47#60#
48# We can then compile this tmp.s into tmp.o, and link it to the original61# We can then compile this tmp.s into tmp.o, and link it back to the original
49# object.62# object.
50#63#
51# But this gets hard if my_func is not globl (a static function).64# In our algorithm, we will choose the first global function we meet in this
52# In such a case we have:65# section as the reference. But this gets hard if there is no global functions
66# in this section. In such a case we have to select a local one. E.g. func1:
53#67#
54# .section ".sched.text", "ax"68# .section ".sched.text", "ax"
55# my_func:69# func1:
56# [...]70# [...]
57# call mcount (offset: 0x5)71# call mcount (offset: 0x10)
58# [...]72# [...]
59# ret73# ret
60# other_func:74# func2:
61# [...]75# [...]
62# call mcount (offset: 0x1b)76# call mcount (offset: 0x20)
63# [...]77# [...]
78# .section "other.section"
64#79#
65# If we make the tmp.s the same as above, when we link together with80# If we make the tmp.s the same as above, when we link together with
66# the original object, we will end up with two symbols for my_func:81# the original object, we will end up with two symbols for func1:
67# one local, one global. After final compile, we will end up with82# one local, one global. After final compile, we will end up with
68# an undefined reference to my_func.83# an undefined reference to func1 or a wrong reference to another global
84# func1 in other files.
69#85#
70# Since local objects can reference local variables, we need to find86# Since local objects can reference local variables, we need to find
71# a way to make tmp.o reference the local objects of the original object87# a way to make tmp.o reference the local objects of the original object
72# file after it is linked together. To do this, we convert the my_func88# file after it is linked together. To do this, we convert func1
73# into a global symbol before linking tmp.o. Then after we link tmp.o89# into a global symbol before linking tmp.o. Then after we link tmp.o
74# we will only have a single symbol for my_func that is global.90# we will only have a single symbol for func1 that is global.
75# We can convert my_func back into a local symbol and we are done.91# We can convert func1 back into a local symbol and we are done.
76#92#
77# Here are the steps we take:93# Here are the steps we take:
78#94#
79# 1) Record all the local symbols by using 'nm'95# 1) Record all the local and weak symbols by using 'nm'
80# 2) Use objdump to find all the call site offsets and sections for96# 2) Use objdump to find all the call site offsets and sections for
81# mcount.97# mcount.
82# 3) Compile the list into its own object.98# 3) Compile the list into its own object.
@@ -86,10 +102,8 @@ · 3 unmodified lines
86# 6) Link together this new object with the list object.102# 6) Link together this new object with the list object.
87# 7) Convert the local functions back to local symbols and rename103# 7) Convert the local functions back to local symbols and rename
88# the result as the original object.104# the result as the original object.
89# End.
90# 8) Link the object with the list object.105# 8) Link the object with the list object.
91# 9) Move the result back to the original object.106# 9) Move the result back to the original object.
92# End.
93#107#
94 108
95use strict;109use strict;
@@ -99,7 +113,7 @@ $P =~ s@.*/@@g; · 3 unmodified lines
99 113
100my $V = '0.1';114my $V = '0.1';
101 115
102if ($#ARGV < 7) {116if ($#ARGV != 10) {
103 print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";117 print "usage: $P arch bits objdump objcopy cc ld nm rm mv is_module inputfile\n";
104 print "version: $V\n";118 print "version: $V\n";
105 exit(1);119 exit(1);
@@ -109,7 +123,7 @@ my ($arch, $bits, $objdump, $objcopy, $cc, · 3 unmodified lines
109 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;123 $ld, $nm, $rm, $mv, $is_module, $inputfile) = @ARGV;
110 124
111# This file refers to mcount and shouldn't be ftraced, so lets' ignore it125# This file refers to mcount and shouldn't be ftraced, so lets' ignore it
112if ($inputfile eq "kernel/trace/ftrace.o") {126if ($inputfile =~ m,kernel/trace/ftrace\.o$,) {
113 exit(0);127 exit(0);
114}128}
115 129
@@ -119,6 +133,7 @@ my %text_sections = ( · 3 unmodified lines
119 ".sched.text" => 1,133 ".sched.text" => 1,
120 ".spinlock.text" => 1,134 ".spinlock.text" => 1,
121 ".irqentry.text" => 1,135 ".irqentry.text" => 1,
136 ".text.unlikely" => 1,
122);137);
123 138
124$objdump = "objdump" if ((length $objdump) == 0);139$objdump = "objdump" if ((length $objdump) == 0);
@@ -137,13 +152,47 @@ my %weak; # List of weak functions · 12 unmodified lines
137my %convert; # List of local functions used that needs conversion152my %convert; # List of local functions used that needs conversion
138 153
139my $type;154my $type;
140my $nm_regex; # Find the local functions (return function)155my $local_regex; # Match a local function (return function)
156my $weak_regex; # Match a weak function (return function)
141my $section_regex; # Find the start of a section157my $section_regex; # Find the start of a section
142my $function_regex; # Find the name of a function158my $function_regex; # Find the name of a function
143 # (return offset and func name)159 # (return offset and func name)
144my $mcount_regex; # Find the call site to mcount (return offset)160my $mcount_regex; # Find the call site to mcount (return offset)
145my $alignment; # The .align value to use for $mcount_section161my $alignment; # The .align value to use for $mcount_section
146my $section_type; # Section header plus possible alignment command162my $section_type; # Section header plus possible alignment command
163my $can_use_local = 0; # If we can use local function references
164
165# Shut up recordmcount if user has older objcopy
166my $quiet_recordmcount = ".tmp_quiet_recordmcount";
167my $print_warning = 1;
168$print_warning = 0 if ( -f $quiet_recordmcount);
169
170##
171# check_objcopy - whether objcopy supports --globalize-symbols
172#
173# --globalize-symbols came out in 2.17, we must test the version
174# of objcopy, and if it is less than 2.17, then we can not
175# record local functions.
176sub check_objcopy
177{
178 open (IN, "$objcopy --version |") or die "error running $objcopy";
179 while (<IN>) {
180 if (/objcopy.*\s(\d+)\.(\d+)/) {
181 $can_use_local = 1 if ($1 > 2 || ($1 == 2 && $2 >= 17));
182 last;
183 }
184 }
185 close (IN);
186
187 if (!$can_use_local && $print_warning) {
188 print STDERR "WARNING: could not find objcopy version or version " .
189 "is less than 2.17.\n" .
190 "\tLocal function references are disabled.\n";
191 open (QUIET, ">$quiet_recordmcount");
192 printf QUIET "Disables the warning from recordmcount.pl\n";
193 close QUIET;
194 }
195}
147 196
148if ($arch eq "x86") {197if ($arch eq "x86") {
149 if ($bits == 64) {198 if ($bits == 64) {
@@ -157,7 +206,8 @@ if ($arch eq "x86") { · 7 unmodified lines
157# We base the defaults off of i386, the other archs may206# We base the defaults off of i386, the other archs may
158# feel free to change them in the below if statements.207# feel free to change them in the below if statements.
159#208#
160$nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)";209$local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\S+)";
210$weak_regex = "^[0-9a-fA-F]+\\s+([wW])\\s+(\\S+)";
161$section_regex = "Disassembly of section\\s+(\\S+):";211$section_regex = "Disassembly of section\\s+(\\S+):";
162$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";212$function_regex = "^([0-9a-fA-F]+)\\s+<(.*?)>:";
163$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";213$mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\smcount\$";
@@ -206,7 +256,7 @@ if ($arch eq "x86_64") { · 42 unmodified lines
206 $cc .= " -m32";256 $cc .= " -m32";
207 257
208} elsif ($arch eq "powerpc") {258} elsif ($arch eq "powerpc") {
209 $nm_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";259 $local_regex = "^[0-9a-fA-F]+\\s+t\\s+(\\.?\\S+)";
210 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";260 $function_regex = "^([0-9a-fA-F]+)\\s+<(\\.?.*?)>:";
211 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";261 $mcount_regex = "^\\s*([0-9a-fA-F]+):.*\\s\\.?_mcount\$";
212 262
@@ -278,44 +328,17 @@ if ($filename =~ m,^(.*)(\.\S),) { · 65 unmodified lines
278my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";328my $mcount_s = $dirname . "/.tmp_mc_" . $prefix . ".s";
279my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";329my $mcount_o = $dirname . "/.tmp_mc_" . $prefix . ".o";
280 330
281#331check_objcopy();
282# --globalize-symbols came out in 2.17, we must test the version
283# of objcopy, and if it is less than 2.17, then we can not
284# record local functions.
285my $use_locals = 01;
286my $local_warn_once = 0;
287my $found_version = 0;
288
289open (IN, "$objcopy --version |") || die "error running $objcopy";
290while (<IN>) {
291 if (/objcopy.*\s(\d+)\.(\d+)/) {
292 my $major = $1;
293 my $minor = $2;
294
295 $found_version = 1;
296 if ($major < 2 ||
297 ($major == 2 && $minor < 17)) {
298 $use_locals = 0;
299 }
300 last;
301 }
302}
303close (IN);
304
305if (!$found_version) {
306 print STDERR "WARNING: could not find objcopy version.\n" .
307 "\tDisabling local function references.\n";
308}
309 332
310#333#
311# Step 1: find all the local (static functions) and weak symbols.334# Step 1: find all the local (static functions) and weak symbols.
312# 't' is local, 'w/W' is weak (we never use a weak function)335# 't' is local, 'w/W' is weak
313#336#
314open (IN, "$nm $inputfile|") || die "error running $nm";337open (IN, "$nm $inputfile|") || die "error running $nm";
315while (<IN>) {338while (<IN>) {
316 if (/$nm_regex/) {339 if (/$local_regex/) {
317 $locals{$1} = 1;340 $locals{$1} = 1;
318 } elsif (/^[0-9a-fA-F]+\s+([wW])\s+(\S+)/) {341 } elsif (/$weak_regex/) {
319 $weak{$2} = $1;342 $weak{$2} = $1;
320 }343 }
321}344}
@@ -333,26 +356,20 @@ my $offset = 0; # offset of ref_func to section beginning · 11 unmodified lines
333#356#
334sub update_funcs357sub update_funcs
335{358{
336 return if ($#offsets < 0);359 return unless ($ref_func and @offsets);
337
338 defined($ref_func) || die "No function to reference";
339 360
340 # A section only had a weak function, to represent it.361 # Sanity check on weak function. A weak function may be overwritten by
341 # Unfortunately, a weak function may be overwritten by another362 # another function of the same name, making all these offsets incorrect.
342 # function of the same name, making all these offsets incorrect.
343 # To be safe, we simply print a warning and bail.
344 if (defined $weak{$ref_func}) {363 if (defined $weak{$ref_func}) {
345 print STDERR364 die "$inputfile: ERROR: referencing weak function" .
346 "$inputfile: WARNING: referencing weak function" .
347 " $ref_func for mcount\n";365 " $ref_func for mcount\n";
348 return;
349 }366 }
350 367
351 # is this function static? If so, note this fact.368 # is this function static? If so, note this fact.
352 if (defined $locals{$ref_func}) {369 if (defined $locals{$ref_func}) {
353 370
354 # only use locals if objcopy supports globalize-symbols371 # only use locals if objcopy supports globalize-symbols
355 if (!$use_locals) {372 if (!$can_use_local) {
356 return;373 return;
357 }374 }
358 $convert{$ref_func} = 1;375 $convert{$ref_func} = 1;
@@ -378,9 +395,27 @@ open(IN, "$objdump -hdr $inputfile|") || die "error running $objdump"; · 19 unmodified lines
378 395
379my $text;396my $text;
380 397
398
399# read headers first
381my $read_headers = 1;400my $read_headers = 1;
382 401
383while (<IN>) {402while (<IN>) {
403
404 if ($read_headers && /$mcount_section/) {
405 #
406 # Somehow the make process can execute this script on an
407 # object twice. If it does, we would duplicate the mcount
408 # section and it will cause the function tracer self test
409 # to fail. Check if the mcount section exists, and if it does,
410 # warn and exit.
411 #
412 print STDERR "ERROR: $mcount_section already in $inputfile\n" .
413 "\tThis may be an indication that your build is corrupted.\n" .
414 "\tDelete $inputfile and try again. If the same object file\n" .
415 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
416 exit(-1);
417 }
418
384 # is it a section?419 # is it a section?
385 if (/$section_regex/) {420 if (/$section_regex/) {
386 $read_headers = 0;421 $read_headers = 0;
@@ -392,7 +427,7 @@ while (<IN>) { · 5 unmodified lines
392 $read_function = 0;427 $read_function = 0;
393 }428 }
394 # print out any recorded offsets429 # print out any recorded offsets
395 update_funcs() if (defined($ref_func));430 update_funcs();
396 431
397 # reset all markers and arrays432 # reset all markers and arrays
398 $text_found = 0;433 $text_found = 0;
@@ -421,21 +456,7 @@ while (<IN>) { · 22 unmodified lines
421 $offset = hex $1;456 $offset = hex $1;
422 }457 }
423 }458 }
424 } elsif ($read_headers && /$mcount_section/) {
425 #
426 # Somehow the make process can execute this script on an
427 # object twice. If it does, we would duplicate the mcount
428 # section and it will cause the function tracer self test
429 # to fail. Check if the mcount section exists, and if it does,
430 # warn and exit.
431 #
432 print STDERR "ERROR: $mcount_section already in $inputfile\n" .
433 "\tThis may be an indication that your build is corrupted.\n" .
434 "\tDelete $inputfile and try again. If the same object file\n" .
435 "\tstill causes an issue, then disable CONFIG_DYNAMIC_FTRACE.\n";
436 exit(-1);
437 }459 }
438
439 # is this a call site to mcount? If so, record it to print later460 # is this a call site to mcount? If so, record it to print later
440 if ($text_found && /$mcount_regex/) {461 if ($text_found && /$mcount_regex/) {
441 $offsets[$#offsets + 1] = hex $1;462 $offsets[$#offsets + 1] = hex $1;
@@ -443,7 +464,7 @@ while (<IN>) { · 1 unmodified line
443}464}
444 465
445# dump out anymore offsets that may have been found466# dump out anymore offsets that may have been found
446update_funcs() if (defined($ref_func));467update_funcs();
447 468
448# If we did not find any mcount callers, we are done (do nothing).469# If we did not find any mcount callers, we are done (do nothing).
449if (!$opened) {470if (!$opened) {