aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/Kconfig9
-rw-r--r--kernel/trace/Makefile1
-rw-r--r--kernel/trace/trace.c3
-rw-r--r--kernel/trace/trace.h3
-rw-r--r--kernel/trace/trace_selftest.c32
-rw-r--r--kernel/trace/trace_sysprof.c330
6 files changed, 0 insertions, 378 deletions
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig
index f5306cb0afb1..c7683fd8a03a 100644
--- a/kernel/trace/Kconfig
+++ b/kernel/trace/Kconfig
@@ -194,15 +194,6 @@ config PREEMPT_TRACER
194 enabled. This option and the irqs-off timing option can be 194 enabled. This option and the irqs-off timing option can be
195 used together or separately.) 195 used together or separately.)
196 196
197config SYSPROF_TRACER
198 bool "Sysprof Tracer"
199 depends on X86
200 select GENERIC_TRACER
201 select CONTEXT_SWITCH_TRACER
202 help
203 This tracer provides the trace needed by the 'Sysprof' userspace
204 tool.
205
206config SCHED_TRACER 197config SCHED_TRACER
207 bool "Scheduling Latency Tracer" 198 bool "Scheduling Latency Tracer"
208 select GENERIC_TRACER 199 select GENERIC_TRACER
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile
index 84b2c9908dae..438e84a56ab3 100644
--- a/kernel/trace/Makefile
+++ b/kernel/trace/Makefile
@@ -30,7 +30,6 @@ obj-$(CONFIG_TRACING) += trace_output.o
30obj-$(CONFIG_TRACING) += trace_stat.o 30obj-$(CONFIG_TRACING) += trace_stat.o
31obj-$(CONFIG_TRACING) += trace_printk.o 31obj-$(CONFIG_TRACING) += trace_printk.o
32obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o 32obj-$(CONFIG_CONTEXT_SWITCH_TRACER) += trace_sched_switch.o
33obj-$(CONFIG_SYSPROF_TRACER) += trace_sysprof.o
34obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o 33obj-$(CONFIG_FUNCTION_TRACER) += trace_functions.o
35obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o 34obj-$(CONFIG_IRQSOFF_TRACER) += trace_irqsoff.o
36obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o 35obj-$(CONFIG_PREEMPT_TRACER) += trace_irqsoff.o
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 8683dec6946b..78a49e67f7db 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -4354,9 +4354,6 @@ static __init int tracer_init_debugfs(void)
4354 trace_create_file("dyn_ftrace_total_info", 0444, d_tracer, 4354 trace_create_file("dyn_ftrace_total_info", 0444, d_tracer,
4355 &ftrace_update_tot_cnt, &tracing_dyn_info_fops); 4355 &ftrace_update_tot_cnt, &tracing_dyn_info_fops);
4356#endif 4356#endif
4357#ifdef CONFIG_SYSPROF_TRACER
4358 init_tracer_sysprof_debugfs(d_tracer);
4359#endif
4360 4357
4361 create_trace_options_dir(); 4358 create_trace_options_dir();
4362 4359
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 84d3f123e86f..2114b4c1150f 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -296,7 +296,6 @@ struct dentry *trace_create_file(const char *name,
296 const struct file_operations *fops); 296 const struct file_operations *fops);
297 297
298struct dentry *tracing_init_dentry(void); 298struct dentry *tracing_init_dentry(void);
299void init_tracer_sysprof_debugfs(struct dentry *d_tracer);
300 299
301struct ring_buffer_event; 300struct ring_buffer_event;
302 301
@@ -428,8 +427,6 @@ extern int trace_selftest_startup_nop(struct tracer *trace,
428 struct trace_array *tr); 427 struct trace_array *tr);
429extern int trace_selftest_startup_sched_switch(struct tracer *trace, 428extern int trace_selftest_startup_sched_switch(struct tracer *trace,
430 struct trace_array *tr); 429 struct trace_array *tr);
431extern int trace_selftest_startup_sysprof(struct tracer *trace,
432 struct trace_array *tr);
433extern int trace_selftest_startup_branch(struct tracer *trace, 430extern int trace_selftest_startup_branch(struct tracer *trace,
434 struct trace_array *tr); 431 struct trace_array *tr);
435#endif /* CONFIG_FTRACE_STARTUP_TEST */ 432#endif /* CONFIG_FTRACE_STARTUP_TEST */
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c
index 39a5ca4cf15b..6ed05ee6cbc7 100644
--- a/kernel/trace/trace_selftest.c
+++ b/kernel/trace/trace_selftest.c
@@ -690,38 +690,6 @@ trace_selftest_startup_sched_switch(struct tracer *trace, struct trace_array *tr
690} 690}
691#endif /* CONFIG_CONTEXT_SWITCH_TRACER */ 691#endif /* CONFIG_CONTEXT_SWITCH_TRACER */
692 692
693#ifdef CONFIG_SYSPROF_TRACER
694int
695trace_selftest_startup_sysprof(struct tracer *trace, struct trace_array *tr)
696{
697 unsigned long count;
698 int ret;
699
700 /* start the tracing */
701 ret = tracer_init(trace, tr);
702 if (ret) {
703 warn_failed_init_tracer(trace, ret);
704 return ret;
705 }
706
707 /* Sleep for a 1/10 of a second */
708 msleep(100);
709 /* stop the tracing. */
710 tracing_stop();
711 /* check the trace buffer */
712 ret = trace_test_buffer(tr, &count);
713 trace->reset(tr);
714 tracing_start();
715
716 if (!ret && !count) {
717 printk(KERN_CONT ".. no entries found ..");
718 ret = -1;
719 }
720
721 return ret;
722}
723#endif /* CONFIG_SYSPROF_TRACER */
724
725#ifdef CONFIG_BRANCH_TRACER 693#ifdef CONFIG_BRANCH_TRACER
726int 694int
727trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr) 695trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr)
diff --git a/kernel/trace/trace_sysprof.c b/kernel/trace/trace_sysprof.c
deleted file mode 100644
index c080956f4d8e..000000000000
--- a/kernel/trace/trace_sysprof.c
+++ /dev/null
@@ -1,330 +0,0 @@
1/*
2 * trace stack traces
3 *
4 * Copyright (C) 2004-2008, Soeren Sandmann
5 * Copyright (C) 2007 Steven Rostedt <srostedt@redhat.com>
6 * Copyright (C) 2008 Ingo Molnar <mingo@redhat.com>
7 */
8#include <linux/kallsyms.h>
9#include <linux/debugfs.h>
10#include <linux/hrtimer.h>
11#include <linux/uaccess.h>
12#include <linux/ftrace.h>
13#include <linux/module.h>
14#include <linux/irq.h>
15#include <linux/fs.h>
16
17#include <asm/stacktrace.h>
18
19#include "trace.h"
20
21static struct trace_array *sysprof_trace;
22static int __read_mostly tracer_enabled;
23
24/*
25 * 1 msec sample interval by default:
26 */
27static unsigned long sample_period = 1000000;
28static const unsigned int sample_max_depth = 512;
29
30static DEFINE_MUTEX(sample_timer_lock);
31/*
32 * Per CPU hrtimers that do the profiling:
33 */
34static DEFINE_PER_CPU(struct hrtimer, stack_trace_hrtimer);
35
36struct stack_frame_user {
37 const void __user *next_fp;
38 unsigned long return_address;
39};
40
41static int
42copy_stack_frame(const void __user *fp, struct stack_frame_user *frame)
43{
44 int ret;
45
46 if (!access_ok(VERIFY_READ, fp, sizeof(*frame)))
47 return 0;
48
49 ret = 1;
50 pagefault_disable();
51 if (__copy_from_user_inatomic(frame, fp, sizeof(*frame)))
52 ret = 0;
53 pagefault_enable();
54
55 return ret;
56}
57
58struct backtrace_info {
59 struct trace_array_cpu *data;
60 struct trace_array *tr;
61 int pos;
62};
63
64static void
65backtrace_warning_symbol(void *data, char *msg, unsigned long symbol)
66{
67 /* Ignore warnings */
68}
69
70static void backtrace_warning(void *data, char *msg)
71{
72 /* Ignore warnings */
73}
74
75static int backtrace_stack(void *data, char *name)
76{
77 /* Don't bother with IRQ stacks for now */
78 return -1;
79}
80
81static void backtrace_address(void *data, unsigned long addr, int reliable)
82{
83 struct backtrace_info *info = data;
84
85 if (info->pos < sample_max_depth && reliable) {
86 __trace_special(info->tr, info->data, 1, addr, 0);
87
88 info->pos++;
89 }
90}
91
92static const struct stacktrace_ops backtrace_ops = {
93 .warning = backtrace_warning,
94 .warning_symbol = backtrace_warning_symbol,
95 .stack = backtrace_stack,
96 .address = backtrace_address,
97 .walk_stack = print_context_stack,
98};
99
100static int
101trace_kernel(struct pt_regs *regs, struct trace_array *tr,
102 struct trace_array_cpu *data)
103{
104 struct backtrace_info info;
105 unsigned long bp;
106 char *stack;
107
108 info.tr = tr;
109 info.data = data;
110 info.pos = 1;
111
112 __trace_special(info.tr, info.data, 1, regs->ip, 0);
113
114 stack = ((char *)regs + sizeof(struct pt_regs));
115#ifdef CONFIG_FRAME_POINTER
116 bp = regs->bp;
117#else
118 bp = 0;
119#endif
120
121 dump_trace(NULL, regs, (void *)stack, bp, &backtrace_ops, &info);
122
123 return info.pos;
124}
125
126static void timer_notify(struct pt_regs *regs, int cpu)
127{
128 struct trace_array_cpu *data;
129 struct stack_frame_user frame;
130 struct trace_array *tr;
131 const void __user *fp;
132 int is_user;
133 int i;
134
135 if (!regs)
136 return;
137
138 tr = sysprof_trace;
139 data = tr->data[cpu];
140 is_user = user_mode(regs);
141
142 if (!current || current->pid == 0)
143 return;
144
145 if (is_user && current->state != TASK_RUNNING)
146 return;
147
148 __trace_special(tr, data, 0, 0, current->pid);
149
150 if (!is_user)
151 i = trace_kernel(regs, tr, data);
152 else
153 i = 0;
154
155 /*
156 * Trace user stack if we are not a kernel thread
157 */
158 if (current->mm && i < sample_max_depth) {
159 regs = (struct pt_regs *)current->thread.sp0 - 1;
160
161 fp = (void __user *)regs->bp;
162
163 __trace_special(tr, data, 2, regs->ip, 0);
164
165 while (i < sample_max_depth) {
166 frame.next_fp = NULL;
167 frame.return_address = 0;
168 if (!copy_stack_frame(fp, &frame))
169 break;
170 if ((unsigned long)fp < regs->sp)
171 break;
172
173 __trace_special(tr, data, 2, frame.return_address,
174 (unsigned long)fp);
175 fp = frame.next_fp;
176
177 i++;
178 }
179
180 }
181
182 /*
183 * Special trace entry if we overflow the max depth:
184 */
185 if (i == sample_max_depth)
186 __trace_special(tr, data, -1, -1, -1);
187
188 __trace_special(tr, data, 3, current->pid, i);
189}
190
191static enum hrtimer_restart stack_trace_timer_fn(struct hrtimer *hrtimer)
192{
193 /* trace here */
194 timer_notify(get_irq_regs(), smp_processor_id());
195
196 hrtimer_forward_now(hrtimer, ns_to_ktime(sample_period));
197
198 return HRTIMER_RESTART;
199}
200
201static void start_stack_timer(void *unused)
202{
203 struct hrtimer *hrtimer = &__get_cpu_var(stack_trace_hrtimer);
204
205 hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
206 hrtimer->function = stack_trace_timer_fn;
207
208 hrtimer_start(hrtimer, ns_to_ktime(sample_period),
209 HRTIMER_MODE_REL_PINNED);
210}
211
212static void start_stack_timers(void)
213{
214 on_each_cpu(start_stack_timer, NULL, 1);
215}
216
217static void stop_stack_timer(int cpu)
218{
219 struct hrtimer *hrtimer = &per_cpu(stack_trace_hrtimer, cpu);
220
221 hrtimer_cancel(hrtimer);
222}
223
224static void stop_stack_timers(void)
225{
226 int cpu;
227
228 for_each_online_cpu(cpu)
229 stop_stack_timer(cpu);
230}
231
232static void stop_stack_trace(struct trace_array *tr)
233{
234 mutex_lock(&sample_timer_lock);
235 stop_stack_timers();
236 tracer_enabled = 0;
237 mutex_unlock(&sample_timer_lock);
238}
239
240static int stack_trace_init(struct trace_array *tr)
241{
242 sysprof_trace = tr;
243
244 tracing_start_cmdline_record();
245
246 mutex_lock(&sample_timer_lock);
247 start_stack_timers();
248 tracer_enabled = 1;
249 mutex_unlock(&sample_timer_lock);
250 return 0;
251}
252
253static void stack_trace_reset(struct trace_array *tr)
254{
255 tracing_stop_cmdline_record();
256 stop_stack_trace(tr);
257}
258
259static struct tracer stack_trace __read_mostly =
260{
261 .name = "sysprof",
262 .init = stack_trace_init,
263 .reset = stack_trace_reset,
264#ifdef CONFIG_FTRACE_SELFTEST
265 .selftest = trace_selftest_startup_sysprof,
266#endif
267};
268
269__init static int init_stack_trace(void)
270{
271 return register_tracer(&stack_trace);
272}
273device_initcall(init_stack_trace);
274
275#define MAX_LONG_DIGITS 22
276
277static ssize_t
278sysprof_sample_read(struct file *filp, char __user *ubuf,
279 size_t cnt, loff_t *ppos)
280{
281 char buf[MAX_LONG_DIGITS];
282 int r;
283
284 r = sprintf(buf, "%ld\n", nsecs_to_usecs(sample_period));
285
286 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
287}
288
289static ssize_t
290sysprof_sample_write(struct file *filp, const char __user *ubuf,
291 size_t cnt, loff_t *ppos)
292{
293 char buf[MAX_LONG_DIGITS];
294 unsigned long val;
295
296 if (cnt > MAX_LONG_DIGITS-1)
297 cnt = MAX_LONG_DIGITS-1;
298
299 if (copy_from_user(&buf, ubuf, cnt))
300 return -EFAULT;
301
302 buf[cnt] = 0;
303
304 val = simple_strtoul(buf, NULL, 10);
305 /*
306 * Enforce a minimum sample period of 100 usecs:
307 */
308 if (val < 100)
309 val = 100;
310
311 mutex_lock(&sample_timer_lock);
312 stop_stack_timers();
313 sample_period = val * 1000;
314 start_stack_timers();
315 mutex_unlock(&sample_timer_lock);
316
317 return cnt;
318}
319
320static const struct file_operations sysprof_sample_fops = {
321 .read = sysprof_sample_read,
322 .write = sysprof_sample_write,
323};
324
325void init_tracer_sysprof_debugfs(struct dentry *d_tracer)
326{
327
328 trace_create_file("sysprof_sample_period", 0644,
329 d_tracer, NULL, &sysprof_sample_fops);
330}