aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_hw_branches.c
diff options
context:
space:
mode:
authorMarkus Metzger <markus.t.metzger@intel.com>2009-01-19 04:31:01 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-20 07:03:48 -0500
commitb1818748b0cf9427e48acf9713295e829a0d715f (patch)
tree49e8f8dc4328799fa69eae635f4b69ee97228445 /kernel/trace/trace_hw_branches.c
parent5c5317de147e9b38ea9c4cbdc2d15bed7648d036 (diff)
x86, ftrace, hw-branch-tracer: dump trace on oops
Dump the branch trace on an oops (based on ftrace_dump_on_oops). Signed-off-by: Markus Metzger <markus.t.metzger@intel.com> Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace_hw_branches.c')
-rw-r--r--kernel/trace/trace_hw_branches.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/kernel/trace/trace_hw_branches.c b/kernel/trace/trace_hw_branches.c
index 398195397c75..e56df2c7d679 100644
--- a/kernel/trace/trace_hw_branches.c
+++ b/kernel/trace/trace_hw_branches.c
@@ -40,6 +40,7 @@ static DEFINE_PER_CPU(unsigned char[SIZEOF_BTS], buffer);
40#define this_buffer per_cpu(buffer, smp_processor_id()) 40#define this_buffer per_cpu(buffer, smp_processor_id())
41 41
42static int __read_mostly trace_hw_branches_enabled; 42static int __read_mostly trace_hw_branches_enabled;
43static struct trace_array *hw_branch_trace __read_mostly;
43 44
44 45
45/* 46/*
@@ -128,6 +129,8 @@ static struct notifier_block bts_hotcpu_notifier __cpuinitdata = {
128 129
129static int bts_trace_init(struct trace_array *tr) 130static int bts_trace_init(struct trace_array *tr)
130{ 131{
132 hw_branch_trace = tr;
133
131 register_hotcpu_notifier(&bts_hotcpu_notifier); 134 register_hotcpu_notifier(&bts_hotcpu_notifier);
132 tracing_reset_online_cpus(tr); 135 tracing_reset_online_cpus(tr);
133 bts_trace_start(tr); 136 bts_trace_start(tr);
@@ -170,8 +173,9 @@ static enum print_line_t bts_trace_print_line(struct trace_iterator *iter)
170 return TRACE_TYPE_UNHANDLED; 173 return TRACE_TYPE_UNHANDLED;
171} 174}
172 175
173void trace_hw_branch(struct trace_array *tr, u64 from, u64 to) 176void trace_hw_branch(u64 from, u64 to)
174{ 177{
178 struct trace_array *tr = hw_branch_trace;
175 struct ring_buffer_event *event; 179 struct ring_buffer_event *event;
176 struct hw_branch_entry *entry; 180 struct hw_branch_entry *entry;
177 unsigned long irq1, irq2; 181 unsigned long irq1, irq2;
@@ -204,8 +208,7 @@ void trace_hw_branch(struct trace_array *tr, u64 from, u64 to)
204 local_irq_restore(irq1); 208 local_irq_restore(irq1);
205} 209}
206 210
207static void trace_bts_at(struct trace_array *tr, 211static void trace_bts_at(const struct bts_trace *trace, void *at)
208 const struct bts_trace *trace, void *at)
209{ 212{
210 struct bts_struct bts; 213 struct bts_struct bts;
211 int err = 0; 214 int err = 0;
@@ -220,7 +223,7 @@ static void trace_bts_at(struct trace_array *tr,
220 223
221 switch (bts.qualifier) { 224 switch (bts.qualifier) {
222 case BTS_BRANCH: 225 case BTS_BRANCH:
223 trace_hw_branch(tr, bts.variant.lbr.from, bts.variant.lbr.to); 226 trace_hw_branch(bts.variant.lbr.from, bts.variant.lbr.to);
224 break; 227 break;
225 } 228 }
226} 229}
@@ -236,12 +239,15 @@ static void trace_bts_cpu(void *arg)
236 const struct bts_trace *trace; 239 const struct bts_trace *trace;
237 unsigned char *at; 240 unsigned char *at;
238 241
239 if (!this_tracer) 242 if (unlikely(!tr))
240 return; 243 return;
241 244
242 if (unlikely(atomic_read(&tr->data[raw_smp_processor_id()]->disabled))) 245 if (unlikely(atomic_read(&tr->data[raw_smp_processor_id()]->disabled)))
243 return; 246 return;
244 247
248 if (unlikely(!this_tracer))
249 return;
250
245 ds_suspend_bts(this_tracer); 251 ds_suspend_bts(this_tracer);
246 trace = ds_read_bts(this_tracer); 252 trace = ds_read_bts(this_tracer);
247 if (!trace) 253 if (!trace)
@@ -249,11 +255,11 @@ static void trace_bts_cpu(void *arg)
249 255
250 for (at = trace->ds.top; (void *)at < trace->ds.end; 256 for (at = trace->ds.top; (void *)at < trace->ds.end;
251 at += trace->ds.size) 257 at += trace->ds.size)
252 trace_bts_at(tr, trace, at); 258 trace_bts_at(trace, at);
253 259
254 for (at = trace->ds.begin; (void *)at < trace->ds.top; 260 for (at = trace->ds.begin; (void *)at < trace->ds.top;
255 at += trace->ds.size) 261 at += trace->ds.size)
256 trace_bts_at(tr, trace, at); 262 trace_bts_at(trace, at);
257 263
258out: 264out:
259 ds_resume_bts(this_tracer); 265 ds_resume_bts(this_tracer);
@@ -268,6 +274,15 @@ static void trace_bts_prepare(struct trace_iterator *iter)
268 mutex_unlock(&bts_tracer_mutex); 274 mutex_unlock(&bts_tracer_mutex);
269} 275}
270 276
277void trace_hw_branch_oops(void)
278{
279 mutex_lock(&bts_tracer_mutex);
280
281 trace_bts_cpu(hw_branch_trace);
282
283 mutex_unlock(&bts_tracer_mutex);
284}
285
271struct tracer bts_tracer __read_mostly = 286struct tracer bts_tracer __read_mostly =
272{ 287{
273 .name = "hw-branch-tracer", 288 .name = "hw-branch-tracer",