diff options
-rw-r--r-- | arch/Kconfig | 4 | ||||
-rw-r--r-- | arch/x86/Kconfig | 2 | ||||
-rw-r--r-- | arch/x86/include/asm/stacktrace.h | 24 | ||||
-rw-r--r-- | arch/x86/kernel/cpu/perf_event.c | 1 | ||||
-rw-r--r-- | arch/x86/kernel/dumpstack.c | 33 | ||||
-rw-r--r-- | arch/x86/kernel/dumpstack.h | 6 | ||||
-rw-r--r-- | arch/x86/kernel/dumpstack_32.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/dumpstack_64.c | 4 | ||||
-rw-r--r-- | arch/x86/kernel/stacktrace.c | 18 | ||||
-rw-r--r-- | arch/x86/oprofile/backtrace.c | 9 | ||||
-rw-r--r-- | include/linux/perf_counter.h | 444 | ||||
-rw-r--r-- | kernel/perf_event.c | 32 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 31 | ||||
-rw-r--r-- | kernel/trace/trace_sysprof.c | 1 | ||||
-rw-r--r-- | tools/perf/Makefile | 3 | ||||
-rw-r--r-- | tools/perf/builtin-probe.c | 4 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 2 | ||||
-rw-r--r-- | tools/perf/util/event.h | 4 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 15 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.h | 59 |
20 files changed, 175 insertions, 523 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index d82875820a15..9d055b4f0585 100644 --- a/arch/Kconfig +++ b/arch/Kconfig | |||
@@ -135,9 +135,7 @@ config HAVE_DEFAULT_NO_SPIN_MUTEXES | |||
135 | 135 | ||
136 | config HAVE_HW_BREAKPOINT | 136 | config HAVE_HW_BREAKPOINT |
137 | bool | 137 | bool |
138 | depends on HAVE_PERF_EVENTS | 138 | depends on PERF_EVENTS |
139 | select ANON_INODES | ||
140 | select PERF_EVENTS | ||
141 | 139 | ||
142 | config HAVE_USER_RETURN_NOTIFIER | 140 | config HAVE_USER_RETURN_NOTIFIER |
143 | bool | 141 | bool |
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 3b2a5aca4edb..55298e891571 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig | |||
@@ -50,6 +50,8 @@ config X86 | |||
50 | select HAVE_KERNEL_BZIP2 | 50 | select HAVE_KERNEL_BZIP2 |
51 | select HAVE_KERNEL_LZMA | 51 | select HAVE_KERNEL_LZMA |
52 | select HAVE_HW_BREAKPOINT | 52 | select HAVE_HW_BREAKPOINT |
53 | select PERF_EVENTS | ||
54 | select ANON_INODES | ||
53 | select HAVE_ARCH_KMEMCHECK | 55 | select HAVE_ARCH_KMEMCHECK |
54 | select HAVE_USER_RETURN_NOTIFIER | 56 | select HAVE_USER_RETURN_NOTIFIER |
55 | 57 | ||
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h index cf86a5e73815..35e89122a42f 100644 --- a/arch/x86/include/asm/stacktrace.h +++ b/arch/x86/include/asm/stacktrace.h | |||
@@ -5,6 +5,29 @@ extern int kstack_depth_to_print; | |||
5 | 5 | ||
6 | int x86_is_stack_id(int id, char *name); | 6 | int x86_is_stack_id(int id, char *name); |
7 | 7 | ||
8 | struct thread_info; | ||
9 | struct stacktrace_ops; | ||
10 | |||
11 | typedef unsigned long (*walk_stack_t)(struct thread_info *tinfo, | ||
12 | unsigned long *stack, | ||
13 | unsigned long bp, | ||
14 | const struct stacktrace_ops *ops, | ||
15 | void *data, | ||
16 | unsigned long *end, | ||
17 | int *graph); | ||
18 | |||
19 | extern unsigned long | ||
20 | print_context_stack(struct thread_info *tinfo, | ||
21 | unsigned long *stack, unsigned long bp, | ||
22 | const struct stacktrace_ops *ops, void *data, | ||
23 | unsigned long *end, int *graph); | ||
24 | |||
25 | extern unsigned long | ||
26 | print_context_stack_bp(struct thread_info *tinfo, | ||
27 | unsigned long *stack, unsigned long bp, | ||
28 | const struct stacktrace_ops *ops, void *data, | ||
29 | unsigned long *end, int *graph); | ||
30 | |||
8 | /* Generic stack tracer with callbacks */ | 31 | /* Generic stack tracer with callbacks */ |
9 | 32 | ||
10 | struct stacktrace_ops { | 33 | struct stacktrace_ops { |
@@ -14,6 +37,7 @@ struct stacktrace_ops { | |||
14 | void (*address)(void *data, unsigned long address, int reliable); | 37 | void (*address)(void *data, unsigned long address, int reliable); |
15 | /* On negative return stop dumping */ | 38 | /* On negative return stop dumping */ |
16 | int (*stack)(void *data, char *name); | 39 | int (*stack)(void *data, char *name); |
40 | walk_stack_t walk_stack; | ||
17 | }; | 41 | }; |
18 | 42 | ||
19 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, | 43 | void dump_trace(struct task_struct *tsk, struct pt_regs *regs, |
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index 45506d5dd8df..c223b7e895d9 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -2336,6 +2336,7 @@ static const struct stacktrace_ops backtrace_ops = { | |||
2336 | .warning_symbol = backtrace_warning_symbol, | 2336 | .warning_symbol = backtrace_warning_symbol, |
2337 | .stack = backtrace_stack, | 2337 | .stack = backtrace_stack, |
2338 | .address = backtrace_address, | 2338 | .address = backtrace_address, |
2339 | .walk_stack = print_context_stack_bp, | ||
2339 | }; | 2340 | }; |
2340 | 2341 | ||
2341 | #include "../dumpstack.h" | 2342 | #include "../dumpstack.h" |
diff --git a/arch/x86/kernel/dumpstack.c b/arch/x86/kernel/dumpstack.c index 0a0aa1cec8f1..c56bc2873030 100644 --- a/arch/x86/kernel/dumpstack.c +++ b/arch/x86/kernel/dumpstack.c | |||
@@ -109,6 +109,30 @@ print_context_stack(struct thread_info *tinfo, | |||
109 | } | 109 | } |
110 | return bp; | 110 | return bp; |
111 | } | 111 | } |
112 | EXPORT_SYMBOL_GPL(print_context_stack); | ||
113 | |||
114 | unsigned long | ||
115 | print_context_stack_bp(struct thread_info *tinfo, | ||
116 | unsigned long *stack, unsigned long bp, | ||
117 | const struct stacktrace_ops *ops, void *data, | ||
118 | unsigned long *end, int *graph) | ||
119 | { | ||
120 | struct stack_frame *frame = (struct stack_frame *)bp; | ||
121 | unsigned long *ret_addr = &frame->return_address; | ||
122 | |||
123 | while (valid_stack_ptr(tinfo, ret_addr, sizeof(*ret_addr), end)) { | ||
124 | unsigned long addr = *ret_addr; | ||
125 | |||
126 | if (__kernel_text_address(addr)) { | ||
127 | ops->address(data, addr, 1); | ||
128 | frame = frame->next_frame; | ||
129 | ret_addr = &frame->return_address; | ||
130 | print_ftrace_graph_addr(addr, data, ops, tinfo, graph); | ||
131 | } | ||
132 | } | ||
133 | return (unsigned long)frame; | ||
134 | } | ||
135 | EXPORT_SYMBOL_GPL(print_context_stack_bp); | ||
112 | 136 | ||
113 | 137 | ||
114 | static void | 138 | static void |
@@ -141,10 +165,11 @@ static void print_trace_address(void *data, unsigned long addr, int reliable) | |||
141 | } | 165 | } |
142 | 166 | ||
143 | static const struct stacktrace_ops print_trace_ops = { | 167 | static const struct stacktrace_ops print_trace_ops = { |
144 | .warning = print_trace_warning, | 168 | .warning = print_trace_warning, |
145 | .warning_symbol = print_trace_warning_symbol, | 169 | .warning_symbol = print_trace_warning_symbol, |
146 | .stack = print_trace_stack, | 170 | .stack = print_trace_stack, |
147 | .address = print_trace_address, | 171 | .address = print_trace_address, |
172 | .walk_stack = print_context_stack, | ||
148 | }; | 173 | }; |
149 | 174 | ||
150 | void | 175 | void |
diff --git a/arch/x86/kernel/dumpstack.h b/arch/x86/kernel/dumpstack.h index 81086c227ab7..4fd1420faffa 100644 --- a/arch/x86/kernel/dumpstack.h +++ b/arch/x86/kernel/dumpstack.h | |||
@@ -14,12 +14,6 @@ | |||
14 | #define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :) | 14 | #define get_bp(bp) asm("movq %%rbp, %0" : "=r" (bp) :) |
15 | #endif | 15 | #endif |
16 | 16 | ||
17 | extern unsigned long | ||
18 | print_context_stack(struct thread_info *tinfo, | ||
19 | unsigned long *stack, unsigned long bp, | ||
20 | const struct stacktrace_ops *ops, void *data, | ||
21 | unsigned long *end, int *graph); | ||
22 | |||
23 | extern void | 17 | extern void |
24 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, | 18 | show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs, |
25 | unsigned long *stack, unsigned long bp, char *log_lvl); | 19 | unsigned long *stack, unsigned long bp, char *log_lvl); |
diff --git a/arch/x86/kernel/dumpstack_32.c b/arch/x86/kernel/dumpstack_32.c index e0ed4c7abb62..ae775ca47b25 100644 --- a/arch/x86/kernel/dumpstack_32.c +++ b/arch/x86/kernel/dumpstack_32.c | |||
@@ -58,7 +58,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
58 | 58 | ||
59 | context = (struct thread_info *) | 59 | context = (struct thread_info *) |
60 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); | 60 | ((unsigned long)stack & (~(THREAD_SIZE - 1))); |
61 | bp = print_context_stack(context, stack, bp, ops, data, NULL, &graph); | 61 | bp = ops->walk_stack(context, stack, bp, ops, data, NULL, &graph); |
62 | 62 | ||
63 | stack = (unsigned long *)context->previous_esp; | 63 | stack = (unsigned long *)context->previous_esp; |
64 | if (!stack) | 64 | if (!stack) |
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index b13af53883aa..0ad9597073f5 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -188,8 +188,8 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
188 | if (ops->stack(data, id) < 0) | 188 | if (ops->stack(data, id) < 0) |
189 | break; | 189 | break; |
190 | 190 | ||
191 | bp = print_context_stack(tinfo, stack, bp, ops, | 191 | bp = ops->walk_stack(tinfo, stack, bp, ops, |
192 | data, estack_end, &graph); | 192 | data, estack_end, &graph); |
193 | ops->stack(data, "<EOE>"); | 193 | ops->stack(data, "<EOE>"); |
194 | /* | 194 | /* |
195 | * We link to the next stack via the | 195 | * We link to the next stack via the |
diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c index c3eb207181fe..922eefbb3f6c 100644 --- a/arch/x86/kernel/stacktrace.c +++ b/arch/x86/kernel/stacktrace.c | |||
@@ -53,17 +53,19 @@ save_stack_address_nosched(void *data, unsigned long addr, int reliable) | |||
53 | } | 53 | } |
54 | 54 | ||
55 | static const struct stacktrace_ops save_stack_ops = { | 55 | static const struct stacktrace_ops save_stack_ops = { |
56 | .warning = save_stack_warning, | 56 | .warning = save_stack_warning, |
57 | .warning_symbol = save_stack_warning_symbol, | 57 | .warning_symbol = save_stack_warning_symbol, |
58 | .stack = save_stack_stack, | 58 | .stack = save_stack_stack, |
59 | .address = save_stack_address, | 59 | .address = save_stack_address, |
60 | .walk_stack = print_context_stack, | ||
60 | }; | 61 | }; |
61 | 62 | ||
62 | static const struct stacktrace_ops save_stack_ops_nosched = { | 63 | static const struct stacktrace_ops save_stack_ops_nosched = { |
63 | .warning = save_stack_warning, | 64 | .warning = save_stack_warning, |
64 | .warning_symbol = save_stack_warning_symbol, | 65 | .warning_symbol = save_stack_warning_symbol, |
65 | .stack = save_stack_stack, | 66 | .stack = save_stack_stack, |
66 | .address = save_stack_address_nosched, | 67 | .address = save_stack_address_nosched, |
68 | .walk_stack = print_context_stack, | ||
67 | }; | 69 | }; |
68 | 70 | ||
69 | /* | 71 | /* |
diff --git a/arch/x86/oprofile/backtrace.c b/arch/x86/oprofile/backtrace.c index 044897be021f..3855096c59b8 100644 --- a/arch/x86/oprofile/backtrace.c +++ b/arch/x86/oprofile/backtrace.c | |||
@@ -41,10 +41,11 @@ static void backtrace_address(void *data, unsigned long addr, int reliable) | |||
41 | } | 41 | } |
42 | 42 | ||
43 | static struct stacktrace_ops backtrace_ops = { | 43 | static struct stacktrace_ops backtrace_ops = { |
44 | .warning = backtrace_warning, | 44 | .warning = backtrace_warning, |
45 | .warning_symbol = backtrace_warning_symbol, | 45 | .warning_symbol = backtrace_warning_symbol, |
46 | .stack = backtrace_stack, | 46 | .stack = backtrace_stack, |
47 | .address = backtrace_address, | 47 | .address = backtrace_address, |
48 | .walk_stack = print_context_stack, | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | struct frame_head { | 51 | struct frame_head { |
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h deleted file mode 100644 index e3fb25606706..000000000000 --- a/include/linux/perf_counter.h +++ /dev/null | |||
@@ -1,444 +0,0 @@ | |||
1 | /* | ||
2 | * NOTE: this file will be removed in a future kernel release, it is | ||
3 | * provided as a courtesy copy of user-space code that relies on the | ||
4 | * old (pre-rename) symbols and constants. | ||
5 | * | ||
6 | * Performance events: | ||
7 | * | ||
8 | * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de> | ||
9 | * Copyright (C) 2008-2009, Red Hat, Inc., Ingo Molnar | ||
10 | * Copyright (C) 2008-2009, Red Hat, Inc., Peter Zijlstra | ||
11 | * | ||
12 | * Data type definitions, declarations, prototypes. | ||
13 | * | ||
14 | * Started by: Thomas Gleixner and Ingo Molnar | ||
15 | * | ||
16 | * For licencing details see kernel-base/COPYING | ||
17 | */ | ||
18 | #ifndef _LINUX_PERF_COUNTER_H | ||
19 | #define _LINUX_PERF_COUNTER_H | ||
20 | |||
21 | #include <linux/types.h> | ||
22 | #include <linux/ioctl.h> | ||
23 | #include <asm/byteorder.h> | ||
24 | |||
25 | /* | ||
26 | * User-space ABI bits: | ||
27 | */ | ||
28 | |||
29 | /* | ||
30 | * attr.type | ||
31 | */ | ||
32 | enum perf_type_id { | ||
33 | PERF_TYPE_HARDWARE = 0, | ||
34 | PERF_TYPE_SOFTWARE = 1, | ||
35 | PERF_TYPE_TRACEPOINT = 2, | ||
36 | PERF_TYPE_HW_CACHE = 3, | ||
37 | PERF_TYPE_RAW = 4, | ||
38 | |||
39 | PERF_TYPE_MAX, /* non-ABI */ | ||
40 | }; | ||
41 | |||
42 | /* | ||
43 | * Generalized performance counter event types, used by the | ||
44 | * attr.event_id parameter of the sys_perf_counter_open() | ||
45 | * syscall: | ||
46 | */ | ||
47 | enum perf_hw_id { | ||
48 | /* | ||
49 | * Common hardware events, generalized by the kernel: | ||
50 | */ | ||
51 | PERF_COUNT_HW_CPU_CYCLES = 0, | ||
52 | PERF_COUNT_HW_INSTRUCTIONS = 1, | ||
53 | PERF_COUNT_HW_CACHE_REFERENCES = 2, | ||
54 | PERF_COUNT_HW_CACHE_MISSES = 3, | ||
55 | PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4, | ||
56 | PERF_COUNT_HW_BRANCH_MISSES = 5, | ||
57 | PERF_COUNT_HW_BUS_CYCLES = 6, | ||
58 | |||
59 | PERF_COUNT_HW_MAX, /* non-ABI */ | ||
60 | }; | ||
61 | |||
62 | /* | ||
63 | * Generalized hardware cache counters: | ||
64 | * | ||
65 | * { L1-D, L1-I, LLC, ITLB, DTLB, BPU } x | ||
66 | * { read, write, prefetch } x | ||
67 | * { accesses, misses } | ||
68 | */ | ||
69 | enum perf_hw_cache_id { | ||
70 | PERF_COUNT_HW_CACHE_L1D = 0, | ||
71 | PERF_COUNT_HW_CACHE_L1I = 1, | ||
72 | PERF_COUNT_HW_CACHE_LL = 2, | ||
73 | PERF_COUNT_HW_CACHE_DTLB = 3, | ||
74 | PERF_COUNT_HW_CACHE_ITLB = 4, | ||
75 | PERF_COUNT_HW_CACHE_BPU = 5, | ||
76 | |||
77 | PERF_COUNT_HW_CACHE_MAX, /* non-ABI */ | ||
78 | }; | ||
79 | |||
80 | enum perf_hw_cache_op_id { | ||
81 | PERF_COUNT_HW_CACHE_OP_READ = 0, | ||
82 | PERF_COUNT_HW_CACHE_OP_WRITE = 1, | ||
83 | PERF_COUNT_HW_CACHE_OP_PREFETCH = 2, | ||
84 | |||
85 | PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */ | ||
86 | }; | ||
87 | |||
88 | enum perf_hw_cache_op_result_id { | ||
89 | PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0, | ||
90 | PERF_COUNT_HW_CACHE_RESULT_MISS = 1, | ||
91 | |||
92 | PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */ | ||
93 | }; | ||
94 | |||
95 | /* | ||
96 | * Special "software" counters provided by the kernel, even if the hardware | ||
97 | * does not support performance counters. These counters measure various | ||
98 | * physical and sw events of the kernel (and allow the profiling of them as | ||
99 | * well): | ||
100 | */ | ||
101 | enum perf_sw_ids { | ||
102 | PERF_COUNT_SW_CPU_CLOCK = 0, | ||
103 | PERF_COUNT_SW_TASK_CLOCK = 1, | ||
104 | PERF_COUNT_SW_PAGE_FAULTS = 2, | ||
105 | PERF_COUNT_SW_CONTEXT_SWITCHES = 3, | ||
106 | PERF_COUNT_SW_CPU_MIGRATIONS = 4, | ||
107 | PERF_COUNT_SW_PAGE_FAULTS_MIN = 5, | ||
108 | PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6, | ||
109 | PERF_COUNT_SW_ALIGNMENT_FAULTS = 7, | ||
110 | PERF_COUNT_SW_EMULATION_FAULTS = 8, | ||
111 | |||
112 | PERF_COUNT_SW_MAX, /* non-ABI */ | ||
113 | }; | ||
114 | |||
115 | /* | ||
116 | * Bits that can be set in attr.sample_type to request information | ||
117 | * in the overflow packets. | ||
118 | */ | ||
119 | enum perf_counter_sample_format { | ||
120 | PERF_SAMPLE_IP = 1U << 0, | ||
121 | PERF_SAMPLE_TID = 1U << 1, | ||
122 | PERF_SAMPLE_TIME = 1U << 2, | ||
123 | PERF_SAMPLE_ADDR = 1U << 3, | ||
124 | PERF_SAMPLE_READ = 1U << 4, | ||
125 | PERF_SAMPLE_CALLCHAIN = 1U << 5, | ||
126 | PERF_SAMPLE_ID = 1U << 6, | ||
127 | PERF_SAMPLE_CPU = 1U << 7, | ||
128 | PERF_SAMPLE_PERIOD = 1U << 8, | ||
129 | PERF_SAMPLE_STREAM_ID = 1U << 9, | ||
130 | PERF_SAMPLE_RAW = 1U << 10, | ||
131 | |||
132 | PERF_SAMPLE_MAX = 1U << 11, /* non-ABI */ | ||
133 | }; | ||
134 | |||
135 | /* | ||
136 | * The format of the data returned by read() on a perf counter fd, | ||
137 | * as specified by attr.read_format: | ||
138 | * | ||
139 | * struct read_format { | ||
140 | * { u64 value; | ||
141 | * { u64 time_enabled; } && PERF_FORMAT_ENABLED | ||
142 | * { u64 time_running; } && PERF_FORMAT_RUNNING | ||
143 | * { u64 id; } && PERF_FORMAT_ID | ||
144 | * } && !PERF_FORMAT_GROUP | ||
145 | * | ||
146 | * { u64 nr; | ||
147 | * { u64 time_enabled; } && PERF_FORMAT_ENABLED | ||
148 | * { u64 time_running; } && PERF_FORMAT_RUNNING | ||
149 | * { u64 value; | ||
150 | * { u64 id; } && PERF_FORMAT_ID | ||
151 | * } cntr[nr]; | ||
152 | * } && PERF_FORMAT_GROUP | ||
153 | * }; | ||
154 | */ | ||
155 | enum perf_counter_read_format { | ||
156 | PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0, | ||
157 | PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1, | ||
158 | PERF_FORMAT_ID = 1U << 2, | ||
159 | PERF_FORMAT_GROUP = 1U << 3, | ||
160 | |||
161 | PERF_FORMAT_MAX = 1U << 4, /* non-ABI */ | ||
162 | }; | ||
163 | |||
164 | #define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */ | ||
165 | |||
166 | /* | ||
167 | * Hardware event to monitor via a performance monitoring counter: | ||
168 | */ | ||
169 | struct perf_counter_attr { | ||
170 | |||
171 | /* | ||
172 | * Major type: hardware/software/tracepoint/etc. | ||
173 | */ | ||
174 | __u32 type; | ||
175 | |||
176 | /* | ||
177 | * Size of the attr structure, for fwd/bwd compat. | ||
178 | */ | ||
179 | __u32 size; | ||
180 | |||
181 | /* | ||
182 | * Type specific configuration information. | ||
183 | */ | ||
184 | __u64 config; | ||
185 | |||
186 | union { | ||
187 | __u64 sample_period; | ||
188 | __u64 sample_freq; | ||
189 | }; | ||
190 | |||
191 | __u64 sample_type; | ||
192 | __u64 read_format; | ||
193 | |||
194 | __u64 disabled : 1, /* off by default */ | ||
195 | inherit : 1, /* children inherit it */ | ||
196 | pinned : 1, /* must always be on PMU */ | ||
197 | exclusive : 1, /* only group on PMU */ | ||
198 | exclude_user : 1, /* don't count user */ | ||
199 | exclude_kernel : 1, /* ditto kernel */ | ||
200 | exclude_hv : 1, /* ditto hypervisor */ | ||
201 | exclude_idle : 1, /* don't count when idle */ | ||
202 | mmap : 1, /* include mmap data */ | ||
203 | comm : 1, /* include comm data */ | ||
204 | freq : 1, /* use freq, not period */ | ||
205 | inherit_stat : 1, /* per task counts */ | ||
206 | enable_on_exec : 1, /* next exec enables */ | ||
207 | task : 1, /* trace fork/exit */ | ||
208 | watermark : 1, /* wakeup_watermark */ | ||
209 | |||
210 | __reserved_1 : 49; | ||
211 | |||
212 | union { | ||
213 | __u32 wakeup_events; /* wakeup every n events */ | ||
214 | __u32 wakeup_watermark; /* bytes before wakeup */ | ||
215 | }; | ||
216 | __u32 __reserved_2; | ||
217 | |||
218 | __u64 __reserved_3; | ||
219 | }; | ||
220 | |||
221 | /* | ||
222 | * Ioctls that can be done on a perf counter fd: | ||
223 | */ | ||
224 | #define PERF_COUNTER_IOC_ENABLE _IO ('$', 0) | ||
225 | #define PERF_COUNTER_IOC_DISABLE _IO ('$', 1) | ||
226 | #define PERF_COUNTER_IOC_REFRESH _IO ('$', 2) | ||
227 | #define PERF_COUNTER_IOC_RESET _IO ('$', 3) | ||
228 | #define PERF_COUNTER_IOC_PERIOD _IOW('$', 4, u64) | ||
229 | #define PERF_COUNTER_IOC_SET_OUTPUT _IO ('$', 5) | ||
230 | #define PERF_COUNTER_IOC_SET_FILTER _IOW('$', 6, char *) | ||
231 | |||
232 | enum perf_counter_ioc_flags { | ||
233 | PERF_IOC_FLAG_GROUP = 1U << 0, | ||
234 | }; | ||
235 | |||
236 | /* | ||
237 | * Structure of the page that can be mapped via mmap | ||
238 | */ | ||
239 | struct perf_counter_mmap_page { | ||
240 | __u32 version; /* version number of this structure */ | ||
241 | __u32 compat_version; /* lowest version this is compat with */ | ||
242 | |||
243 | /* | ||
244 | * Bits needed to read the hw counters in user-space. | ||
245 | * | ||
246 | * u32 seq; | ||
247 | * s64 count; | ||
248 | * | ||
249 | * do { | ||
250 | * seq = pc->lock; | ||
251 | * | ||
252 | * barrier() | ||
253 | * if (pc->index) { | ||
254 | * count = pmc_read(pc->index - 1); | ||
255 | * count += pc->offset; | ||
256 | * } else | ||
257 | * goto regular_read; | ||
258 | * | ||
259 | * barrier(); | ||
260 | * } while (pc->lock != seq); | ||
261 | * | ||
262 | * NOTE: for obvious reason this only works on self-monitoring | ||
263 | * processes. | ||
264 | */ | ||
265 | __u32 lock; /* seqlock for synchronization */ | ||
266 | __u32 index; /* hardware counter identifier */ | ||
267 | __s64 offset; /* add to hardware counter value */ | ||
268 | __u64 time_enabled; /* time counter active */ | ||
269 | __u64 time_running; /* time counter on cpu */ | ||
270 | |||
271 | /* | ||
272 | * Hole for extension of the self monitor capabilities | ||
273 | */ | ||
274 | |||
275 | __u64 __reserved[123]; /* align to 1k */ | ||
276 | |||
277 | /* | ||
278 | * Control data for the mmap() data buffer. | ||
279 | * | ||
280 | * User-space reading the @data_head value should issue an rmb(), on | ||
281 | * SMP capable platforms, after reading this value -- see | ||
282 | * perf_counter_wakeup(). | ||
283 | * | ||
284 | * When the mapping is PROT_WRITE the @data_tail value should be | ||
285 | * written by userspace to reflect the last read data. In this case | ||
286 | * the kernel will not over-write unread data. | ||
287 | */ | ||
288 | __u64 data_head; /* head in the data section */ | ||
289 | __u64 data_tail; /* user-space written tail */ | ||
290 | }; | ||
291 | |||
292 | #define PERF_EVENT_MISC_CPUMODE_MASK (3 << 0) | ||
293 | #define PERF_EVENT_MISC_CPUMODE_UNKNOWN (0 << 0) | ||
294 | #define PERF_EVENT_MISC_KERNEL (1 << 0) | ||
295 | #define PERF_EVENT_MISC_USER (2 << 0) | ||
296 | #define PERF_EVENT_MISC_HYPERVISOR (3 << 0) | ||
297 | |||
298 | struct perf_event_header { | ||
299 | __u32 type; | ||
300 | __u16 misc; | ||
301 | __u16 size; | ||
302 | }; | ||
303 | |||
304 | enum perf_event_type { | ||
305 | |||
306 | /* | ||
307 | * The MMAP events record the PROT_EXEC mappings so that we can | ||
308 | * correlate userspace IPs to code. They have the following structure: | ||
309 | * | ||
310 | * struct { | ||
311 | * struct perf_event_header header; | ||
312 | * | ||
313 | * u32 pid, tid; | ||
314 | * u64 addr; | ||
315 | * u64 len; | ||
316 | * u64 pgoff; | ||
317 | * char filename[]; | ||
318 | * }; | ||
319 | */ | ||
320 | PERF_EVENT_MMAP = 1, | ||
321 | |||
322 | /* | ||
323 | * struct { | ||
324 | * struct perf_event_header header; | ||
325 | * u64 id; | ||
326 | * u64 lost; | ||
327 | * }; | ||
328 | */ | ||
329 | PERF_EVENT_LOST = 2, | ||
330 | |||
331 | /* | ||
332 | * struct { | ||
333 | * struct perf_event_header header; | ||
334 | * | ||
335 | * u32 pid, tid; | ||
336 | * char comm[]; | ||
337 | * }; | ||
338 | */ | ||
339 | PERF_EVENT_COMM = 3, | ||
340 | |||
341 | /* | ||
342 | * struct { | ||
343 | * struct perf_event_header header; | ||
344 | * u32 pid, ppid; | ||
345 | * u32 tid, ptid; | ||
346 | * u64 time; | ||
347 | * }; | ||
348 | */ | ||
349 | PERF_EVENT_EXIT = 4, | ||
350 | |||
351 | /* | ||
352 | * struct { | ||
353 | * struct perf_event_header header; | ||
354 | * u64 time; | ||
355 | * u64 id; | ||
356 | * u64 stream_id; | ||
357 | * }; | ||
358 | */ | ||
359 | PERF_EVENT_THROTTLE = 5, | ||
360 | PERF_EVENT_UNTHROTTLE = 6, | ||
361 | |||
362 | /* | ||
363 | * struct { | ||
364 | * struct perf_event_header header; | ||
365 | * u32 pid, ppid; | ||
366 | * u32 tid, ptid; | ||
367 | * u64 time; | ||
368 | * }; | ||
369 | */ | ||
370 | PERF_EVENT_FORK = 7, | ||
371 | |||
372 | /* | ||
373 | * struct { | ||
374 | * struct perf_event_header header; | ||
375 | * u32 pid, tid; | ||
376 | * | ||
377 | * struct read_format values; | ||
378 | * }; | ||
379 | */ | ||
380 | PERF_EVENT_READ = 8, | ||
381 | |||
382 | /* | ||
383 | * struct { | ||
384 | * struct perf_event_header header; | ||
385 | * | ||
386 | * { u64 ip; } && PERF_SAMPLE_IP | ||
387 | * { u32 pid, tid; } && PERF_SAMPLE_TID | ||
388 | * { u64 time; } && PERF_SAMPLE_TIME | ||
389 | * { u64 addr; } && PERF_SAMPLE_ADDR | ||
390 | * { u64 id; } && PERF_SAMPLE_ID | ||
391 | * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID | ||
392 | * { u32 cpu, res; } && PERF_SAMPLE_CPU | ||
393 | * { u64 period; } && PERF_SAMPLE_PERIOD | ||
394 | * | ||
395 | * { struct read_format values; } && PERF_SAMPLE_READ | ||
396 | * | ||
397 | * { u64 nr, | ||
398 | * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN | ||
399 | * | ||
400 | * # | ||
401 | * # The RAW record below is opaque data wrt the ABI | ||
402 | * # | ||
403 | * # That is, the ABI doesn't make any promises wrt to | ||
404 | * # the stability of its content, it may vary depending | ||
405 | * # on event, hardware, kernel version and phase of | ||
406 | * # the moon. | ||
407 | * # | ||
408 | * # In other words, PERF_SAMPLE_RAW contents are not an ABI. | ||
409 | * # | ||
410 | * | ||
411 | * { u32 size; | ||
412 | * char data[size];}&& PERF_SAMPLE_RAW | ||
413 | * }; | ||
414 | */ | ||
415 | PERF_EVENT_SAMPLE = 9, | ||
416 | |||
417 | PERF_EVENT_MAX, /* non-ABI */ | ||
418 | }; | ||
419 | |||
420 | enum perf_callchain_context { | ||
421 | PERF_CONTEXT_HV = (__u64)-32, | ||
422 | PERF_CONTEXT_KERNEL = (__u64)-128, | ||
423 | PERF_CONTEXT_USER = (__u64)-512, | ||
424 | |||
425 | PERF_CONTEXT_GUEST = (__u64)-2048, | ||
426 | PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176, | ||
427 | PERF_CONTEXT_GUEST_USER = (__u64)-2560, | ||
428 | |||
429 | PERF_CONTEXT_MAX = (__u64)-4095, | ||
430 | }; | ||
431 | |||
432 | #define PERF_FLAG_FD_NO_GROUP (1U << 0) | ||
433 | #define PERF_FLAG_FD_OUTPUT (1U << 1) | ||
434 | |||
435 | /* | ||
436 | * In case some app still references the old symbols: | ||
437 | */ | ||
438 | |||
439 | #define __NR_perf_counter_open __NR_perf_event_open | ||
440 | |||
441 | #define PR_TASK_PERF_COUNTERS_DISABLE PR_TASK_PERF_EVENTS_DISABLE | ||
442 | #define PR_TASK_PERF_COUNTERS_ENABLE PR_TASK_PERF_EVENTS_ENABLE | ||
443 | |||
444 | #endif /* _LINUX_PERF_COUNTER_H */ | ||
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 97d1a3dd7a59..e0eb4a2fe183 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -1381,6 +1381,9 @@ static void perf_ctx_adjust_freq(struct perf_event_context *ctx) | |||
1381 | if (event->state != PERF_EVENT_STATE_ACTIVE) | 1381 | if (event->state != PERF_EVENT_STATE_ACTIVE) |
1382 | continue; | 1382 | continue; |
1383 | 1383 | ||
1384 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
1385 | continue; | ||
1386 | |||
1384 | hwc = &event->hw; | 1387 | hwc = &event->hw; |
1385 | 1388 | ||
1386 | interrupts = hwc->interrupts; | 1389 | interrupts = hwc->interrupts; |
@@ -3265,6 +3268,9 @@ static void perf_event_task_output(struct perf_event *event, | |||
3265 | 3268 | ||
3266 | static int perf_event_task_match(struct perf_event *event) | 3269 | static int perf_event_task_match(struct perf_event *event) |
3267 | { | 3270 | { |
3271 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3272 | return 0; | ||
3273 | |||
3268 | if (event->attr.comm || event->attr.mmap || event->attr.task) | 3274 | if (event->attr.comm || event->attr.mmap || event->attr.task) |
3269 | return 1; | 3275 | return 1; |
3270 | 3276 | ||
@@ -3290,12 +3296,11 @@ static void perf_event_task_event(struct perf_task_event *task_event) | |||
3290 | rcu_read_lock(); | 3296 | rcu_read_lock(); |
3291 | cpuctx = &get_cpu_var(perf_cpu_context); | 3297 | cpuctx = &get_cpu_var(perf_cpu_context); |
3292 | perf_event_task_ctx(&cpuctx->ctx, task_event); | 3298 | perf_event_task_ctx(&cpuctx->ctx, task_event); |
3293 | put_cpu_var(perf_cpu_context); | ||
3294 | |||
3295 | if (!ctx) | 3299 | if (!ctx) |
3296 | ctx = rcu_dereference(task_event->task->perf_event_ctxp); | 3300 | ctx = rcu_dereference(task_event->task->perf_event_ctxp); |
3297 | if (ctx) | 3301 | if (ctx) |
3298 | perf_event_task_ctx(ctx, task_event); | 3302 | perf_event_task_ctx(ctx, task_event); |
3303 | put_cpu_var(perf_cpu_context); | ||
3299 | rcu_read_unlock(); | 3304 | rcu_read_unlock(); |
3300 | } | 3305 | } |
3301 | 3306 | ||
@@ -3372,6 +3377,9 @@ static void perf_event_comm_output(struct perf_event *event, | |||
3372 | 3377 | ||
3373 | static int perf_event_comm_match(struct perf_event *event) | 3378 | static int perf_event_comm_match(struct perf_event *event) |
3374 | { | 3379 | { |
3380 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3381 | return 0; | ||
3382 | |||
3375 | if (event->attr.comm) | 3383 | if (event->attr.comm) |
3376 | return 1; | 3384 | return 1; |
3377 | 3385 | ||
@@ -3408,15 +3416,10 @@ static void perf_event_comm_event(struct perf_comm_event *comm_event) | |||
3408 | rcu_read_lock(); | 3416 | rcu_read_lock(); |
3409 | cpuctx = &get_cpu_var(perf_cpu_context); | 3417 | cpuctx = &get_cpu_var(perf_cpu_context); |
3410 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); | 3418 | perf_event_comm_ctx(&cpuctx->ctx, comm_event); |
3411 | put_cpu_var(perf_cpu_context); | ||
3412 | |||
3413 | /* | ||
3414 | * doesn't really matter which of the child contexts the | ||
3415 | * events ends up in. | ||
3416 | */ | ||
3417 | ctx = rcu_dereference(current->perf_event_ctxp); | 3419 | ctx = rcu_dereference(current->perf_event_ctxp); |
3418 | if (ctx) | 3420 | if (ctx) |
3419 | perf_event_comm_ctx(ctx, comm_event); | 3421 | perf_event_comm_ctx(ctx, comm_event); |
3422 | put_cpu_var(perf_cpu_context); | ||
3420 | rcu_read_unlock(); | 3423 | rcu_read_unlock(); |
3421 | } | 3424 | } |
3422 | 3425 | ||
@@ -3491,6 +3494,9 @@ static void perf_event_mmap_output(struct perf_event *event, | |||
3491 | static int perf_event_mmap_match(struct perf_event *event, | 3494 | static int perf_event_mmap_match(struct perf_event *event, |
3492 | struct perf_mmap_event *mmap_event) | 3495 | struct perf_mmap_event *mmap_event) |
3493 | { | 3496 | { |
3497 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3498 | return 0; | ||
3499 | |||
3494 | if (event->attr.mmap) | 3500 | if (event->attr.mmap) |
3495 | return 1; | 3501 | return 1; |
3496 | 3502 | ||
@@ -3564,15 +3570,10 @@ got_name: | |||
3564 | rcu_read_lock(); | 3570 | rcu_read_lock(); |
3565 | cpuctx = &get_cpu_var(perf_cpu_context); | 3571 | cpuctx = &get_cpu_var(perf_cpu_context); |
3566 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event); | 3572 | perf_event_mmap_ctx(&cpuctx->ctx, mmap_event); |
3567 | put_cpu_var(perf_cpu_context); | ||
3568 | |||
3569 | /* | ||
3570 | * doesn't really matter which of the child contexts the | ||
3571 | * events ends up in. | ||
3572 | */ | ||
3573 | ctx = rcu_dereference(current->perf_event_ctxp); | 3573 | ctx = rcu_dereference(current->perf_event_ctxp); |
3574 | if (ctx) | 3574 | if (ctx) |
3575 | perf_event_mmap_ctx(ctx, mmap_event); | 3575 | perf_event_mmap_ctx(ctx, mmap_event); |
3576 | put_cpu_var(perf_cpu_context); | ||
3576 | rcu_read_unlock(); | 3577 | rcu_read_unlock(); |
3577 | 3578 | ||
3578 | kfree(buf); | 3579 | kfree(buf); |
@@ -3863,6 +3864,9 @@ static int perf_swevent_match(struct perf_event *event, | |||
3863 | struct perf_sample_data *data, | 3864 | struct perf_sample_data *data, |
3864 | struct pt_regs *regs) | 3865 | struct pt_regs *regs) |
3865 | { | 3866 | { |
3867 | if (event->cpu != -1 && event->cpu != smp_processor_id()) | ||
3868 | return 0; | ||
3869 | |||
3866 | if (!perf_swevent_is_counting(event)) | 3870 | if (!perf_swevent_is_counting(event)) |
3867 | return 0; | 3871 | return 0; |
3868 | 3872 | ||
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 7ecab06547a5..375f81a568dc 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -282,6 +282,18 @@ static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); | |||
282 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, | 282 | static int kretprobe_dispatcher(struct kretprobe_instance *ri, |
283 | struct pt_regs *regs); | 283 | struct pt_regs *regs); |
284 | 284 | ||
285 | /* Check the name is good for event/group */ | ||
286 | static int check_event_name(const char *name) | ||
287 | { | ||
288 | if (!isalpha(*name) && *name != '_') | ||
289 | return 0; | ||
290 | while (*++name != '\0') { | ||
291 | if (!isalpha(*name) && !isdigit(*name) && *name != '_') | ||
292 | return 0; | ||
293 | } | ||
294 | return 1; | ||
295 | } | ||
296 | |||
285 | /* | 297 | /* |
286 | * Allocate new trace_probe and initialize it (including kprobes). | 298 | * Allocate new trace_probe and initialize it (including kprobes). |
287 | */ | 299 | */ |
@@ -293,10 +305,11 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
293 | int nargs, int is_return) | 305 | int nargs, int is_return) |
294 | { | 306 | { |
295 | struct trace_probe *tp; | 307 | struct trace_probe *tp; |
308 | int ret = -ENOMEM; | ||
296 | 309 | ||
297 | tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL); | 310 | tp = kzalloc(SIZEOF_TRACE_PROBE(nargs), GFP_KERNEL); |
298 | if (!tp) | 311 | if (!tp) |
299 | return ERR_PTR(-ENOMEM); | 312 | return ERR_PTR(ret); |
300 | 313 | ||
301 | if (symbol) { | 314 | if (symbol) { |
302 | tp->symbol = kstrdup(symbol, GFP_KERNEL); | 315 | tp->symbol = kstrdup(symbol, GFP_KERNEL); |
@@ -312,14 +325,20 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
312 | else | 325 | else |
313 | tp->rp.kp.pre_handler = kprobe_dispatcher; | 326 | tp->rp.kp.pre_handler = kprobe_dispatcher; |
314 | 327 | ||
315 | if (!event) | 328 | if (!event || !check_event_name(event)) { |
329 | ret = -EINVAL; | ||
316 | goto error; | 330 | goto error; |
331 | } | ||
332 | |||
317 | tp->call.name = kstrdup(event, GFP_KERNEL); | 333 | tp->call.name = kstrdup(event, GFP_KERNEL); |
318 | if (!tp->call.name) | 334 | if (!tp->call.name) |
319 | goto error; | 335 | goto error; |
320 | 336 | ||
321 | if (!group) | 337 | if (!group || !check_event_name(group)) { |
338 | ret = -EINVAL; | ||
322 | goto error; | 339 | goto error; |
340 | } | ||
341 | |||
323 | tp->call.system = kstrdup(group, GFP_KERNEL); | 342 | tp->call.system = kstrdup(group, GFP_KERNEL); |
324 | if (!tp->call.system) | 343 | if (!tp->call.system) |
325 | goto error; | 344 | goto error; |
@@ -330,7 +349,7 @@ error: | |||
330 | kfree(tp->call.name); | 349 | kfree(tp->call.name); |
331 | kfree(tp->symbol); | 350 | kfree(tp->symbol); |
332 | kfree(tp); | 351 | kfree(tp); |
333 | return ERR_PTR(-ENOMEM); | 352 | return ERR_PTR(ret); |
334 | } | 353 | } |
335 | 354 | ||
336 | static void free_probe_arg(struct probe_arg *arg) | 355 | static void free_probe_arg(struct probe_arg *arg) |
@@ -695,10 +714,10 @@ static int create_trace_probe(int argc, char **argv) | |||
695 | if (!event) { | 714 | if (!event) { |
696 | /* Make a new event name */ | 715 | /* Make a new event name */ |
697 | if (symbol) | 716 | if (symbol) |
698 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@%s%+ld", | 717 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c_%s_%ld", |
699 | is_return ? 'r' : 'p', symbol, offset); | 718 | is_return ? 'r' : 'p', symbol, offset); |
700 | else | 719 | else |
701 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c@0x%p", | 720 | snprintf(buf, MAX_EVENT_NAME_LEN, "%c_0x%p", |
702 | is_return ? 'r' : 'p', addr); | 721 | is_return ? 'r' : 'p', addr); |
703 | event = buf; | 722 | event = buf; |
704 | } | 723 | } |
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c index f6693969287d..a7974a552ca9 100644 --- a/kernel/trace/trace_sysprof.c +++ b/kernel/trace/trace_sysprof.c | |||
@@ -93,6 +93,7 @@ static const struct stacktrace_ops backtrace_ops = { | |||
93 | .warning_symbol = backtrace_warning_symbol, | 93 | .warning_symbol = backtrace_warning_symbol, |
94 | .stack = backtrace_stack, | 94 | .stack = backtrace_stack, |
95 | .address = backtrace_address, | 95 | .address = backtrace_address, |
96 | .walk_stack = print_context_stack, | ||
96 | }; | 97 | }; |
97 | 98 | ||
98 | static int | 99 | static int |
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 7814dbbd401d..4390d225686d 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -487,10 +487,11 @@ else | |||
487 | msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); | 487 | msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]); |
488 | endif | 488 | endif |
489 | 489 | ||
490 | ifneq ($(shell sh -c "(echo '\#include <libdwarf/dwarf.h>'; echo '\#include <libdwarf/libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) | 490 | ifneq ($(shell sh -c "(echo '\#ifndef _MIPS_SZLONG'; echo '\#define _MIPS_SZLONG 0'; echo '\#endif'; echo '\#include <dwarf.h>'; echo '\#include <libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/libdwarf -ldwarf -lelf -o /dev/null $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y) |
491 | msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231); | 491 | msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231); |
492 | BASIC_CFLAGS += -DNO_LIBDWARF | 492 | BASIC_CFLAGS += -DNO_LIBDWARF |
493 | else | 493 | else |
494 | BASIC_CFLAGS += -I/usr/include/libdwarf | ||
494 | EXTLIBS += -lelf -ldwarf | 495 | EXTLIBS += -lelf -ldwarf |
495 | LIB_OBJS += util/probe-finder.o | 496 | LIB_OBJS += util/probe-finder.o |
496 | endif | 497 | endif |
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c index 7e741f54d798..c1e6774fd3ed 100644 --- a/tools/perf/builtin-probe.c +++ b/tools/perf/builtin-probe.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include "util/strlist.h" | 38 | #include "util/strlist.h" |
39 | #include "util/event.h" | 39 | #include "util/event.h" |
40 | #include "util/debug.h" | 40 | #include "util/debug.h" |
41 | #include "util/debugfs.h" | ||
41 | #include "util/symbol.h" | 42 | #include "util/symbol.h" |
42 | #include "util/thread.h" | 43 | #include "util/thread.h" |
43 | #include "util/session.h" | 44 | #include "util/session.h" |
@@ -205,6 +206,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used) | |||
205 | if ((!session.nr_probe && !session.dellist && !session.list_events)) | 206 | if ((!session.nr_probe && !session.dellist && !session.list_events)) |
206 | usage_with_options(probe_usage, options); | 207 | usage_with_options(probe_usage, options); |
207 | 208 | ||
209 | if (debugfs_valid_mountpoint(debugfs_path) < 0) | ||
210 | die("Failed to find debugfs path."); | ||
211 | |||
208 | if (session.list_events) { | 212 | if (session.list_events) { |
209 | if (session.nr_probe != 0 || session.dellist) { | 213 | if (session.nr_probe != 0 || session.dellist) { |
210 | pr_warning(" Error: Don't use --list with" | 214 | pr_warning(" Error: Don't use --list with" |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index e50a6b10ee6f..5c2ab5357ec6 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -224,7 +224,7 @@ static int __cmd_report(void) | |||
224 | 224 | ||
225 | perf_session__collapse_resort(session); | 225 | perf_session__collapse_resort(session); |
226 | perf_session__output_resort(session, session->events_stats.total); | 226 | perf_session__output_resort(session, session->events_stats.total); |
227 | fprintf(stdout, "# Samples: %ld\n#\n", session->events_stats.total); | 227 | fprintf(stdout, "# Samples: %Ld\n#\n", session->events_stats.total); |
228 | perf_session__fprintf_hists(session, NULL, false, stdout); | 228 | perf_session__fprintf_hists(session, NULL, false, stdout); |
229 | if (sort_order == default_sort_order && | 229 | if (sort_order == default_sort_order && |
230 | parent_pattern == default_parent_pattern) | 230 | parent_pattern == default_parent_pattern) |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 8027309b0422..690a96d0467c 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -95,8 +95,8 @@ typedef union event_union { | |||
95 | } event_t; | 95 | } event_t; |
96 | 96 | ||
97 | struct events_stats { | 97 | struct events_stats { |
98 | unsigned long total; | 98 | u64 total; |
99 | unsigned long lost; | 99 | u64 lost; |
100 | }; | 100 | }; |
101 | 101 | ||
102 | void event__print_totals(void); | 102 | void event__print_totals(void); |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 2ca62154f79b..29465d440043 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -62,6 +62,18 @@ static int e_snprintf(char *str, size_t size, const char *format, ...) | |||
62 | return ret; | 62 | return ret; |
63 | } | 63 | } |
64 | 64 | ||
65 | /* Check the name is good for event/group */ | ||
66 | static bool check_event_name(const char *name) | ||
67 | { | ||
68 | if (!isalpha(*name) && *name != '_') | ||
69 | return false; | ||
70 | while (*++name != '\0') { | ||
71 | if (!isalpha(*name) && !isdigit(*name) && *name != '_') | ||
72 | return false; | ||
73 | } | ||
74 | return true; | ||
75 | } | ||
76 | |||
65 | /* Parse probepoint definition. */ | 77 | /* Parse probepoint definition. */ |
66 | static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) | 78 | static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) |
67 | { | 79 | { |
@@ -82,6 +94,9 @@ static void parse_perf_probe_probepoint(char *arg, struct probe_point *pp) | |||
82 | ptr = strchr(arg, ':'); | 94 | ptr = strchr(arg, ':'); |
83 | if (ptr) /* Group name is not supported yet. */ | 95 | if (ptr) /* Group name is not supported yet. */ |
84 | semantic_error("Group name is not supported yet."); | 96 | semantic_error("Group name is not supported yet."); |
97 | if (!check_event_name(arg)) | ||
98 | semantic_error("%s is bad for event name -it must " | ||
99 | "follow C symbol-naming rule.", arg); | ||
85 | pp->event = strdup(arg); | 100 | pp->event = strdup(arg); |
86 | arg = tmp; | 101 | arg = tmp; |
87 | } | 102 | } |
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h index 5e4050ce2963..a4086aaddb73 100644 --- a/tools/perf/util/probe-finder.h +++ b/tools/perf/util/probe-finder.h | |||
@@ -1,9 +1,9 @@ | |||
1 | #ifndef _PROBE_FINDER_H | 1 | #ifndef _PROBE_FINDER_H |
2 | #define _PROBE_FINDER_H | 2 | #define _PROBE_FINDER_H |
3 | 3 | ||
4 | #define MAX_PATH_LEN 256 | 4 | #define MAX_PATH_LEN 256 |
5 | #define MAX_PROBE_BUFFER 1024 | 5 | #define MAX_PROBE_BUFFER 1024 |
6 | #define MAX_PROBES 128 | 6 | #define MAX_PROBES 128 |
7 | 7 | ||
8 | static inline int is_c_varname(const char *name) | 8 | static inline int is_c_varname(const char *name) |
9 | { | 9 | { |
@@ -12,48 +12,53 @@ static inline int is_c_varname(const char *name) | |||
12 | } | 12 | } |
13 | 13 | ||
14 | struct probe_point { | 14 | struct probe_point { |
15 | char *event; /* Event name */ | 15 | char *event; /* Event name */ |
16 | char *group; /* Event group */ | 16 | char *group; /* Event group */ |
17 | 17 | ||
18 | /* Inputs */ | 18 | /* Inputs */ |
19 | char *file; /* File name */ | 19 | char *file; /* File name */ |
20 | int line; /* Line number */ | 20 | int line; /* Line number */ |
21 | 21 | ||
22 | char *function; /* Function name */ | 22 | char *function; /* Function name */ |
23 | int offset; /* Offset bytes */ | 23 | int offset; /* Offset bytes */ |
24 | 24 | ||
25 | int nr_args; /* Number of arguments */ | 25 | int nr_args; /* Number of arguments */ |
26 | char **args; /* Arguments */ | 26 | char **args; /* Arguments */ |
27 | 27 | ||
28 | int retprobe; /* Return probe */ | 28 | int retprobe; /* Return probe */ |
29 | 29 | ||
30 | /* Output */ | 30 | /* Output */ |
31 | int found; /* Number of found probe points */ | 31 | int found; /* Number of found probe points */ |
32 | char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/ | 32 | char *probes[MAX_PROBES]; /* Output buffers (will be allocated)*/ |
33 | }; | 33 | }; |
34 | 34 | ||
35 | #ifndef NO_LIBDWARF | 35 | #ifndef NO_LIBDWARF |
36 | extern int find_probepoint(int fd, struct probe_point *pp); | 36 | extern int find_probepoint(int fd, struct probe_point *pp); |
37 | 37 | ||
38 | #include <libdwarf/dwarf.h> | 38 | /* Workaround for undefined _MIPS_SZLONG bug in libdwarf.h: */ |
39 | #include <libdwarf/libdwarf.h> | 39 | #ifndef _MIPS_SZLONG |
40 | # define _MIPS_SZLONG 0 | ||
41 | #endif | ||
42 | |||
43 | #include <dwarf.h> | ||
44 | #include <libdwarf.h> | ||
40 | 45 | ||
41 | struct probe_finder { | 46 | struct probe_finder { |
42 | struct probe_point *pp; /* Target probe point */ | 47 | struct probe_point *pp; /* Target probe point */ |
43 | 48 | ||
44 | /* For function searching */ | 49 | /* For function searching */ |
45 | Dwarf_Addr addr; /* Address */ | 50 | Dwarf_Addr addr; /* Address */ |
46 | Dwarf_Unsigned fno; /* File number */ | 51 | Dwarf_Unsigned fno; /* File number */ |
47 | Dwarf_Unsigned lno; /* Line number */ | 52 | Dwarf_Unsigned lno; /* Line number */ |
48 | Dwarf_Off inl_offs; /* Inline offset */ | 53 | Dwarf_Off inl_offs; /* Inline offset */ |
49 | Dwarf_Die cu_die; /* Current CU */ | 54 | Dwarf_Die cu_die; /* Current CU */ |
50 | 55 | ||
51 | /* For variable searching */ | 56 | /* For variable searching */ |
52 | Dwarf_Addr cu_base; /* Current CU base address */ | 57 | Dwarf_Addr cu_base; /* Current CU base address */ |
53 | Dwarf_Locdesc fbloc; /* Location of Current Frame Base */ | 58 | Dwarf_Locdesc fbloc; /* Location of Current Frame Base */ |
54 | const char *var; /* Current variable name */ | 59 | const char *var; /* Current variable name */ |
55 | char *buf; /* Current output buffer */ | 60 | char *buf; /* Current output buffer */ |
56 | int len; /* Length of output buffer */ | 61 | int len; /* Length of output buffer */ |
57 | }; | 62 | }; |
58 | #endif /* NO_LIBDWARF */ | 63 | #endif /* NO_LIBDWARF */ |
59 | 64 | ||