diff options
author | Peter Zijlstra <a.p.zijlstra@chello.nl> | 2010-03-25 09:51:50 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-03-26 06:33:55 -0400 |
commit | faa4602e47690fb11221e00f9b9697c8dc0d4b19 (patch) | |
tree | af667d1cdff7dc63b6893ee3f27a1f2503229ed1 /kernel | |
parent | 7c5ecaf7666617889f337296c610815b519abfa9 (diff) |
x86, perf, bts, mm: Delete the never used BTS-ptrace code
Support for the PMU's BTS features has been upstreamed in
v2.6.32, but we still have the old and disabled ptrace-BTS,
as Linus noticed it not so long ago.
It's buggy: TIF_DEBUGCTLMSR is trampling all over that MSR without
regard for other uses (perf) and doesn't provide the flexibility
needed for perf either.
Its users are ptrace-block-step and ptrace-bts, since ptrace-bts
was never used and ptrace-block-step can be implemented using a
much simpler approach.
So axe all 3000 lines of it. That includes the *locked_memory*()
APIs in mm/mlock.c as well.
Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Roland McGrath <roland@redhat.com>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Markus Metzger <markus.t.metzger@intel.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
LKML-Reference: <20100325135413.938004390@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/fork.c | 3 | ||||
-rw-r--r-- | kernel/ptrace.c | 1 | ||||
-rw-r--r-- | kernel/sched.c | 43 | ||||
-rw-r--r-- | kernel/trace/Kconfig | 11 | ||||
-rw-r--r-- | kernel/trace/Makefile | 1 | ||||
-rw-r--r-- | kernel/trace/trace.h | 4 | ||||
-rw-r--r-- | kernel/trace/trace_entries.h | 12 | ||||
-rw-r--r-- | kernel/trace/trace_hw_branches.c | 312 | ||||
-rw-r--r-- | kernel/trace/trace_selftest.c | 57 |
9 files changed, 0 insertions, 444 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index 4799c5f0e6d0..d67f1dbfbe03 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -1108,9 +1108,6 @@ static struct task_struct *copy_process(unsigned long clone_flags, | |||
1108 | p->memcg_batch.do_batch = 0; | 1108 | p->memcg_batch.do_batch = 0; |
1109 | p->memcg_batch.memcg = NULL; | 1109 | p->memcg_batch.memcg = NULL; |
1110 | #endif | 1110 | #endif |
1111 | |||
1112 | p->bts = NULL; | ||
1113 | |||
1114 | p->stack_start = stack_start; | 1111 | p->stack_start = stack_start; |
1115 | 1112 | ||
1116 | /* Perform scheduler related setup. Assign this task to a CPU. */ | 1113 | /* Perform scheduler related setup. Assign this task to a CPU. */ |
diff --git a/kernel/ptrace.c b/kernel/ptrace.c index 42ad8ae729a0..9fb51237b18c 100644 --- a/kernel/ptrace.c +++ b/kernel/ptrace.c | |||
@@ -76,7 +76,6 @@ void __ptrace_unlink(struct task_struct *child) | |||
76 | child->parent = child->real_parent; | 76 | child->parent = child->real_parent; |
77 | list_del_init(&child->ptrace_entry); | 77 | list_del_init(&child->ptrace_entry); |
78 | 78 | ||
79 | arch_ptrace_untrace(child); | ||
80 | if (task_is_traced(child)) | 79 | if (task_is_traced(child)) |
81 | ptrace_untrace(child); | 80 | ptrace_untrace(child); |
82 | } | 81 | } |
diff --git a/kernel/sched.c b/kernel/sched.c index 9ab3cd7858d3..117b7cad31b3 100644 --- a/kernel/sched.c +++ b/kernel/sched.c | |||
@@ -2077,49 +2077,6 @@ migrate_task(struct task_struct *p, int dest_cpu, struct migration_req *req) | |||
2077 | } | 2077 | } |
2078 | 2078 | ||
2079 | /* | 2079 | /* |
2080 | * wait_task_context_switch - wait for a thread to complete at least one | ||
2081 | * context switch. | ||
2082 | * | ||
2083 | * @p must not be current. | ||
2084 | */ | ||
2085 | void wait_task_context_switch(struct task_struct *p) | ||
2086 | { | ||
2087 | unsigned long nvcsw, nivcsw, flags; | ||
2088 | int running; | ||
2089 | struct rq *rq; | ||
2090 | |||
2091 | nvcsw = p->nvcsw; | ||
2092 | nivcsw = p->nivcsw; | ||
2093 | for (;;) { | ||
2094 | /* | ||
2095 | * The runqueue is assigned before the actual context | ||
2096 | * switch. We need to take the runqueue lock. | ||
2097 | * | ||
2098 | * We could check initially without the lock but it is | ||
2099 | * very likely that we need to take the lock in every | ||
2100 | * iteration. | ||
2101 | */ | ||
2102 | rq = task_rq_lock(p, &flags); | ||
2103 | running = task_running(rq, p); | ||
2104 | task_rq_unlock(rq, &flags); | ||
2105 | |||
2106 | if (likely(!running)) | ||
2107 | break; | ||
2108 | /* | ||
2109 | * The switch count is incremented before the actual | ||
2110 | * context switch. We thus wait for two switches to be | ||
2111 | * sure at least one completed. | ||
2112 | */ | ||
2113 | if ((p->nvcsw - nvcsw) > 1) | ||
2114 | break; | ||
2115 | if ((p->nivcsw - nivcsw) > 1) | ||
2116 | break; | ||
2117 | |||
2118 | cpu_relax(); | ||
2119 | } | ||
2120 | } | ||
2121 | |||
2122 | /* | ||
2123 | * wait_task_inactive - wait for a thread to unschedule. | 2080 | * wait_task_inactive - wait for a thread to unschedule. |
2124 | * | 2081 | * |
2125 | * If @match_state is nonzero, it's the @p->state value just checked and | 2082 | * If @match_state is nonzero, it's the @p->state value just checked and |
diff --git a/kernel/trace/Kconfig b/kernel/trace/Kconfig index 13e13d428cd3..8b1797c4545b 100644 --- a/kernel/trace/Kconfig +++ b/kernel/trace/Kconfig | |||
@@ -44,9 +44,6 @@ config HAVE_FTRACE_MCOUNT_RECORD | |||
44 | help | 44 | help |
45 | See Documentation/trace/ftrace-design.txt | 45 | See Documentation/trace/ftrace-design.txt |
46 | 46 | ||
47 | config HAVE_HW_BRANCH_TRACER | ||
48 | bool | ||
49 | |||
50 | config HAVE_SYSCALL_TRACEPOINTS | 47 | config HAVE_SYSCALL_TRACEPOINTS |
51 | bool | 48 | bool |
52 | help | 49 | help |
@@ -374,14 +371,6 @@ config STACK_TRACER | |||
374 | 371 | ||
375 | Say N if unsure. | 372 | Say N if unsure. |
376 | 373 | ||
377 | config HW_BRANCH_TRACER | ||
378 | depends on HAVE_HW_BRANCH_TRACER | ||
379 | bool "Trace hw branches" | ||
380 | select GENERIC_TRACER | ||
381 | help | ||
382 | This tracer records all branches on the system in a circular | ||
383 | buffer, giving access to the last N branches for each cpu. | ||
384 | |||
385 | config KMEMTRACE | 374 | config KMEMTRACE |
386 | bool "Trace SLAB allocations" | 375 | bool "Trace SLAB allocations" |
387 | select GENERIC_TRACER | 376 | select GENERIC_TRACER |
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index 78edc6490038..ffb1a5b0550e 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile | |||
@@ -41,7 +41,6 @@ obj-$(CONFIG_MMIOTRACE) += trace_mmiotrace.o | |||
41 | obj-$(CONFIG_BOOT_TRACER) += trace_boot.o | 41 | obj-$(CONFIG_BOOT_TRACER) += trace_boot.o |
42 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o | 42 | obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += trace_functions_graph.o |
43 | obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o | 43 | obj-$(CONFIG_TRACE_BRANCH_PROFILING) += trace_branch.o |
44 | obj-$(CONFIG_HW_BRANCH_TRACER) += trace_hw_branches.o | ||
45 | obj-$(CONFIG_KMEMTRACE) += kmemtrace.o | 44 | obj-$(CONFIG_KMEMTRACE) += kmemtrace.o |
46 | obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o | 45 | obj-$(CONFIG_WORKQUEUE_TRACER) += trace_workqueue.o |
47 | obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o | 46 | obj-$(CONFIG_BLK_DEV_IO_TRACE) += blktrace.o |
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 2825ef2c0b15..bec2c973ff0c 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -34,7 +34,6 @@ enum trace_type { | |||
34 | TRACE_GRAPH_RET, | 34 | TRACE_GRAPH_RET, |
35 | TRACE_GRAPH_ENT, | 35 | TRACE_GRAPH_ENT, |
36 | TRACE_USER_STACK, | 36 | TRACE_USER_STACK, |
37 | TRACE_HW_BRANCHES, | ||
38 | TRACE_KMEM_ALLOC, | 37 | TRACE_KMEM_ALLOC, |
39 | TRACE_KMEM_FREE, | 38 | TRACE_KMEM_FREE, |
40 | TRACE_BLK, | 39 | TRACE_BLK, |
@@ -229,7 +228,6 @@ extern void __ftrace_bad_type(void); | |||
229 | TRACE_GRAPH_ENT); \ | 228 | TRACE_GRAPH_ENT); \ |
230 | IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \ | 229 | IF_ASSIGN(var, ent, struct ftrace_graph_ret_entry, \ |
231 | TRACE_GRAPH_RET); \ | 230 | TRACE_GRAPH_RET); \ |
232 | IF_ASSIGN(var, ent, struct hw_branch_entry, TRACE_HW_BRANCHES);\ | ||
233 | IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \ | 231 | IF_ASSIGN(var, ent, struct kmemtrace_alloc_entry, \ |
234 | TRACE_KMEM_ALLOC); \ | 232 | TRACE_KMEM_ALLOC); \ |
235 | IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ | 233 | IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ |
@@ -467,8 +465,6 @@ extern int trace_selftest_startup_sysprof(struct tracer *trace, | |||
467 | struct trace_array *tr); | 465 | struct trace_array *tr); |
468 | extern int trace_selftest_startup_branch(struct tracer *trace, | 466 | extern int trace_selftest_startup_branch(struct tracer *trace, |
469 | struct trace_array *tr); | 467 | struct trace_array *tr); |
470 | extern int trace_selftest_startup_hw_branches(struct tracer *trace, | ||
471 | struct trace_array *tr); | ||
472 | extern int trace_selftest_startup_ksym(struct tracer *trace, | 468 | extern int trace_selftest_startup_ksym(struct tracer *trace, |
473 | struct trace_array *tr); | 469 | struct trace_array *tr); |
474 | #endif /* CONFIG_FTRACE_STARTUP_TEST */ | 470 | #endif /* CONFIG_FTRACE_STARTUP_TEST */ |
diff --git a/kernel/trace/trace_entries.h b/kernel/trace/trace_entries.h index c16a08f399df..dc008c1240da 100644 --- a/kernel/trace/trace_entries.h +++ b/kernel/trace/trace_entries.h | |||
@@ -318,18 +318,6 @@ FTRACE_ENTRY(branch, trace_branch, | |||
318 | __entry->func, __entry->file, __entry->correct) | 318 | __entry->func, __entry->file, __entry->correct) |
319 | ); | 319 | ); |
320 | 320 | ||
321 | FTRACE_ENTRY(hw_branch, hw_branch_entry, | ||
322 | |||
323 | TRACE_HW_BRANCHES, | ||
324 | |||
325 | F_STRUCT( | ||
326 | __field( u64, from ) | ||
327 | __field( u64, to ) | ||
328 | ), | ||
329 | |||
330 | F_printk("from: %llx to: %llx", __entry->from, __entry->to) | ||
331 | ); | ||
332 | |||
333 | FTRACE_ENTRY(kmem_alloc, kmemtrace_alloc_entry, | 321 | FTRACE_ENTRY(kmem_alloc, kmemtrace_alloc_entry, |
334 | 322 | ||
335 | TRACE_KMEM_ALLOC, | 323 | TRACE_KMEM_ALLOC, |
diff --git a/kernel/trace/trace_hw_branches.c b/kernel/trace/trace_hw_branches.c deleted file mode 100644 index 7b97000745f5..000000000000 --- a/kernel/trace/trace_hw_branches.c +++ /dev/null | |||
@@ -1,312 +0,0 @@ | |||
1 | /* | ||
2 | * h/w branch tracer for x86 based on BTS | ||
3 | * | ||
4 | * Copyright (C) 2008-2009 Intel Corporation. | ||
5 | * Markus Metzger <markus.t.metzger@gmail.com>, 2008-2009 | ||
6 | */ | ||
7 | #include <linux/kallsyms.h> | ||
8 | #include <linux/debugfs.h> | ||
9 | #include <linux/ftrace.h> | ||
10 | #include <linux/module.h> | ||
11 | #include <linux/cpu.h> | ||
12 | #include <linux/smp.h> | ||
13 | #include <linux/fs.h> | ||
14 | |||
15 | #include <asm/ds.h> | ||
16 | |||
17 | #include "trace_output.h" | ||
18 | #include "trace.h" | ||
19 | |||
20 | |||
21 | #define BTS_BUFFER_SIZE (1 << 13) | ||
22 | |||
23 | static DEFINE_PER_CPU(struct bts_tracer *, hwb_tracer); | ||
24 | static DEFINE_PER_CPU(unsigned char[BTS_BUFFER_SIZE], hwb_buffer); | ||
25 | |||
26 | #define this_tracer per_cpu(hwb_tracer, smp_processor_id()) | ||
27 | |||
28 | static int trace_hw_branches_enabled __read_mostly; | ||
29 | static int trace_hw_branches_suspended __read_mostly; | ||
30 | static struct trace_array *hw_branch_trace __read_mostly; | ||
31 | |||
32 | |||
33 | static void bts_trace_init_cpu(int cpu) | ||
34 | { | ||
35 | per_cpu(hwb_tracer, cpu) = | ||
36 | ds_request_bts_cpu(cpu, per_cpu(hwb_buffer, cpu), | ||
37 | BTS_BUFFER_SIZE, NULL, (size_t)-1, | ||
38 | BTS_KERNEL); | ||
39 | |||
40 | if (IS_ERR(per_cpu(hwb_tracer, cpu))) | ||
41 | per_cpu(hwb_tracer, cpu) = NULL; | ||
42 | } | ||
43 | |||
44 | static int bts_trace_init(struct trace_array *tr) | ||
45 | { | ||
46 | int cpu; | ||
47 | |||
48 | hw_branch_trace = tr; | ||
49 | trace_hw_branches_enabled = 0; | ||
50 | |||
51 | get_online_cpus(); | ||
52 | for_each_online_cpu(cpu) { | ||
53 | bts_trace_init_cpu(cpu); | ||
54 | |||
55 | if (likely(per_cpu(hwb_tracer, cpu))) | ||
56 | trace_hw_branches_enabled = 1; | ||
57 | } | ||
58 | trace_hw_branches_suspended = 0; | ||
59 | put_online_cpus(); | ||
60 | |||
61 | /* If we could not enable tracing on a single cpu, we fail. */ | ||
62 | return trace_hw_branches_enabled ? 0 : -EOPNOTSUPP; | ||
63 | } | ||
64 | |||
65 | static void bts_trace_reset(struct trace_array *tr) | ||
66 | { | ||
67 | int cpu; | ||
68 | |||
69 | get_online_cpus(); | ||
70 | for_each_online_cpu(cpu) { | ||
71 | if (likely(per_cpu(hwb_tracer, cpu))) { | ||
72 | ds_release_bts(per_cpu(hwb_tracer, cpu)); | ||
73 | per_cpu(hwb_tracer, cpu) = NULL; | ||
74 | } | ||
75 | } | ||
76 | trace_hw_branches_enabled = 0; | ||
77 | trace_hw_branches_suspended = 0; | ||
78 | put_online_cpus(); | ||
79 | } | ||
80 | |||
81 | static void bts_trace_start(struct trace_array *tr) | ||
82 | { | ||
83 | int cpu; | ||
84 | |||
85 | get_online_cpus(); | ||
86 | for_each_online_cpu(cpu) | ||
87 | if (likely(per_cpu(hwb_tracer, cpu))) | ||
88 | ds_resume_bts(per_cpu(hwb_tracer, cpu)); | ||
89 | trace_hw_branches_suspended = 0; | ||
90 | put_online_cpus(); | ||
91 | } | ||
92 | |||
93 | static void bts_trace_stop(struct trace_array *tr) | ||
94 | { | ||
95 | int cpu; | ||
96 | |||
97 | get_online_cpus(); | ||
98 | for_each_online_cpu(cpu) | ||
99 | if (likely(per_cpu(hwb_tracer, cpu))) | ||
100 | ds_suspend_bts(per_cpu(hwb_tracer, cpu)); | ||
101 | trace_hw_branches_suspended = 1; | ||
102 | put_online_cpus(); | ||
103 | } | ||
104 | |||
105 | static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb, | ||
106 | unsigned long action, void *hcpu) | ||
107 | { | ||
108 | int cpu = (long)hcpu; | ||
109 | |||
110 | switch (action) { | ||
111 | case CPU_ONLINE: | ||
112 | case CPU_DOWN_FAILED: | ||
113 | /* The notification is sent with interrupts enabled. */ | ||
114 | if (trace_hw_branches_enabled) { | ||
115 | bts_trace_init_cpu(cpu); | ||
116 | |||
117 | if (trace_hw_branches_suspended && | ||
118 | likely(per_cpu(hwb_tracer, cpu))) | ||
119 | ds_suspend_bts(per_cpu(hwb_tracer, cpu)); | ||
120 | } | ||
121 | break; | ||
122 | |||
123 | case CPU_DOWN_PREPARE: | ||
124 | /* The notification is sent with interrupts enabled. */ | ||
125 | if (likely(per_cpu(hwb_tracer, cpu))) { | ||
126 | ds_release_bts(per_cpu(hwb_tracer, cpu)); | ||
127 | per_cpu(hwb_tracer, cpu) = NULL; | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return NOTIFY_DONE; | ||
132 | } | ||
133 | |||
134 | static struct notifier_block bts_hotcpu_notifier __cpuinitdata = { | ||
135 | .notifier_call = bts_hotcpu_handler | ||
136 | }; | ||
137 | |||
138 | static void bts_trace_print_header(struct seq_file *m) | ||
139 | { | ||
140 | seq_puts(m, "# CPU# TO <- FROM\n"); | ||
141 | } | ||
142 | |||
143 | static enum print_line_t bts_trace_print_line(struct trace_iterator *iter) | ||
144 | { | ||
145 | unsigned long symflags = TRACE_ITER_SYM_OFFSET; | ||
146 | struct trace_entry *entry = iter->ent; | ||
147 | struct trace_seq *seq = &iter->seq; | ||
148 | struct hw_branch_entry *it; | ||
149 | |||
150 | trace_assign_type(it, entry); | ||
151 | |||
152 | if (entry->type == TRACE_HW_BRANCHES) { | ||
153 | if (trace_seq_printf(seq, "%4d ", iter->cpu) && | ||
154 | seq_print_ip_sym(seq, it->to, symflags) && | ||
155 | trace_seq_printf(seq, "\t <- ") && | ||
156 | seq_print_ip_sym(seq, it->from, symflags) && | ||
157 | trace_seq_printf(seq, "\n")) | ||
158 | return TRACE_TYPE_HANDLED; | ||
159 | return TRACE_TYPE_PARTIAL_LINE; | ||
160 | } | ||
161 | return TRACE_TYPE_UNHANDLED; | ||
162 | } | ||
163 | |||
164 | void trace_hw_branch(u64 from, u64 to) | ||
165 | { | ||
166 | struct ftrace_event_call *call = &event_hw_branch; | ||
167 | struct trace_array *tr = hw_branch_trace; | ||
168 | struct ring_buffer_event *event; | ||
169 | struct ring_buffer *buf; | ||
170 | struct hw_branch_entry *entry; | ||
171 | unsigned long irq1; | ||
172 | int cpu; | ||
173 | |||
174 | if (unlikely(!tr)) | ||
175 | return; | ||
176 | |||
177 | if (unlikely(!trace_hw_branches_enabled)) | ||
178 | return; | ||
179 | |||
180 | local_irq_save(irq1); | ||
181 | cpu = raw_smp_processor_id(); | ||
182 | if (atomic_inc_return(&tr->data[cpu]->disabled) != 1) | ||
183 | goto out; | ||
184 | |||
185 | buf = tr->buffer; | ||
186 | event = trace_buffer_lock_reserve(buf, TRACE_HW_BRANCHES, | ||
187 | sizeof(*entry), 0, 0); | ||
188 | if (!event) | ||
189 | goto out; | ||
190 | entry = ring_buffer_event_data(event); | ||
191 | tracing_generic_entry_update(&entry->ent, 0, from); | ||
192 | entry->ent.type = TRACE_HW_BRANCHES; | ||
193 | entry->from = from; | ||
194 | entry->to = to; | ||
195 | if (!filter_check_discard(call, entry, buf, event)) | ||
196 | trace_buffer_unlock_commit(buf, event, 0, 0); | ||
197 | |||
198 | out: | ||
199 | atomic_dec(&tr->data[cpu]->disabled); | ||
200 | local_irq_restore(irq1); | ||
201 | } | ||
202 | |||
203 | static void trace_bts_at(const struct bts_trace *trace, void *at) | ||
204 | { | ||
205 | struct bts_struct bts; | ||
206 | int err = 0; | ||
207 | |||
208 | WARN_ON_ONCE(!trace->read); | ||
209 | if (!trace->read) | ||
210 | return; | ||
211 | |||
212 | err = trace->read(this_tracer, at, &bts); | ||
213 | if (err < 0) | ||
214 | return; | ||
215 | |||
216 | switch (bts.qualifier) { | ||
217 | case BTS_BRANCH: | ||
218 | trace_hw_branch(bts.variant.lbr.from, bts.variant.lbr.to); | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * Collect the trace on the current cpu and write it into the ftrace buffer. | ||
225 | * | ||
226 | * pre: tracing must be suspended on the current cpu | ||
227 | */ | ||
228 | static void trace_bts_cpu(void *arg) | ||
229 | { | ||
230 | struct trace_array *tr = (struct trace_array *)arg; | ||
231 | const struct bts_trace *trace; | ||
232 | unsigned char *at; | ||
233 | |||
234 | if (unlikely(!tr)) | ||
235 | return; | ||
236 | |||
237 | if (unlikely(atomic_read(&tr->data[raw_smp_processor_id()]->disabled))) | ||
238 | return; | ||
239 | |||
240 | if (unlikely(!this_tracer)) | ||
241 | return; | ||
242 | |||
243 | trace = ds_read_bts(this_tracer); | ||
244 | if (!trace) | ||
245 | return; | ||
246 | |||
247 | for (at = trace->ds.top; (void *)at < trace->ds.end; | ||
248 | at += trace->ds.size) | ||
249 | trace_bts_at(trace, at); | ||
250 | |||
251 | for (at = trace->ds.begin; (void *)at < trace->ds.top; | ||
252 | at += trace->ds.size) | ||
253 | trace_bts_at(trace, at); | ||
254 | } | ||
255 | |||
256 | static void trace_bts_prepare(struct trace_iterator *iter) | ||
257 | { | ||
258 | int cpu; | ||
259 | |||
260 | get_online_cpus(); | ||
261 | for_each_online_cpu(cpu) | ||
262 | if (likely(per_cpu(hwb_tracer, cpu))) | ||
263 | ds_suspend_bts(per_cpu(hwb_tracer, cpu)); | ||
264 | /* | ||
265 | * We need to collect the trace on the respective cpu since ftrace | ||
266 | * implicitly adds the record for the current cpu. | ||
267 | * Once that is more flexible, we could collect the data from any cpu. | ||
268 | */ | ||
269 | on_each_cpu(trace_bts_cpu, iter->tr, 1); | ||
270 | |||
271 | for_each_online_cpu(cpu) | ||
272 | if (likely(per_cpu(hwb_tracer, cpu))) | ||
273 | ds_resume_bts(per_cpu(hwb_tracer, cpu)); | ||
274 | put_online_cpus(); | ||
275 | } | ||
276 | |||
277 | static void trace_bts_close(struct trace_iterator *iter) | ||
278 | { | ||
279 | tracing_reset_online_cpus(iter->tr); | ||
280 | } | ||
281 | |||
282 | void trace_hw_branch_oops(void) | ||
283 | { | ||
284 | if (this_tracer) { | ||
285 | ds_suspend_bts_noirq(this_tracer); | ||
286 | trace_bts_cpu(hw_branch_trace); | ||
287 | ds_resume_bts_noirq(this_tracer); | ||
288 | } | ||
289 | } | ||
290 | |||
291 | struct tracer bts_tracer __read_mostly = | ||
292 | { | ||
293 | .name = "hw-branch-tracer", | ||
294 | .init = bts_trace_init, | ||
295 | .reset = bts_trace_reset, | ||
296 | .print_header = bts_trace_print_header, | ||
297 | .print_line = bts_trace_print_line, | ||
298 | .start = bts_trace_start, | ||
299 | .stop = bts_trace_stop, | ||
300 | .open = trace_bts_prepare, | ||
301 | .close = trace_bts_close, | ||
302 | #ifdef CONFIG_FTRACE_SELFTEST | ||
303 | .selftest = trace_selftest_startup_hw_branches, | ||
304 | #endif /* CONFIG_FTRACE_SELFTEST */ | ||
305 | }; | ||
306 | |||
307 | __init static int init_bts_trace(void) | ||
308 | { | ||
309 | register_hotcpu_notifier(&bts_hotcpu_notifier); | ||
310 | return register_tracer(&bts_tracer); | ||
311 | } | ||
312 | device_initcall(init_bts_trace); | ||
diff --git a/kernel/trace/trace_selftest.c b/kernel/trace/trace_selftest.c index 280fea470d67..a7084e7c0427 100644 --- a/kernel/trace/trace_selftest.c +++ b/kernel/trace/trace_selftest.c | |||
@@ -16,7 +16,6 @@ static inline int trace_valid_entry(struct trace_entry *entry) | |||
16 | case TRACE_BRANCH: | 16 | case TRACE_BRANCH: |
17 | case TRACE_GRAPH_ENT: | 17 | case TRACE_GRAPH_ENT: |
18 | case TRACE_GRAPH_RET: | 18 | case TRACE_GRAPH_RET: |
19 | case TRACE_HW_BRANCHES: | ||
20 | case TRACE_KSYM: | 19 | case TRACE_KSYM: |
21 | return 1; | 20 | return 1; |
22 | } | 21 | } |
@@ -754,62 +753,6 @@ trace_selftest_startup_branch(struct tracer *trace, struct trace_array *tr) | |||
754 | } | 753 | } |
755 | #endif /* CONFIG_BRANCH_TRACER */ | 754 | #endif /* CONFIG_BRANCH_TRACER */ |
756 | 755 | ||
757 | #ifdef CONFIG_HW_BRANCH_TRACER | ||
758 | int | ||
759 | trace_selftest_startup_hw_branches(struct tracer *trace, | ||
760 | struct trace_array *tr) | ||
761 | { | ||
762 | struct trace_iterator *iter; | ||
763 | struct tracer tracer; | ||
764 | unsigned long count; | ||
765 | int ret; | ||
766 | |||
767 | if (!trace->open) { | ||
768 | printk(KERN_CONT "missing open function..."); | ||
769 | return -1; | ||
770 | } | ||
771 | |||
772 | ret = tracer_init(trace, tr); | ||
773 | if (ret) { | ||
774 | warn_failed_init_tracer(trace, ret); | ||
775 | return ret; | ||
776 | } | ||
777 | |||
778 | /* | ||
779 | * The hw-branch tracer needs to collect the trace from the various | ||
780 | * cpu trace buffers - before tracing is stopped. | ||
781 | */ | ||
782 | iter = kzalloc(sizeof(*iter), GFP_KERNEL); | ||
783 | if (!iter) | ||
784 | return -ENOMEM; | ||
785 | |||
786 | memcpy(&tracer, trace, sizeof(tracer)); | ||
787 | |||
788 | iter->trace = &tracer; | ||
789 | iter->tr = tr; | ||
790 | iter->pos = -1; | ||
791 | mutex_init(&iter->mutex); | ||
792 | |||
793 | trace->open(iter); | ||
794 | |||
795 | mutex_destroy(&iter->mutex); | ||
796 | kfree(iter); | ||
797 | |||
798 | tracing_stop(); | ||
799 | |||
800 | ret = trace_test_buffer(tr, &count); | ||
801 | trace->reset(tr); | ||
802 | tracing_start(); | ||
803 | |||
804 | if (!ret && !count) { | ||
805 | printk(KERN_CONT "no entries found.."); | ||
806 | ret = -1; | ||
807 | } | ||
808 | |||
809 | return ret; | ||
810 | } | ||
811 | #endif /* CONFIG_HW_BRANCH_TRACER */ | ||
812 | |||
813 | #ifdef CONFIG_KSYM_TRACER | 756 | #ifdef CONFIG_KSYM_TRACER |
814 | static int ksym_selftest_dummy; | 757 | static int ksym_selftest_dummy; |
815 | 758 | ||