aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-04-30 19:00:46 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-06-11 18:38:48 -0400
commit90e3c03c3a09a7b176b3fe59d78f5d9755ac8e37 (patch)
treea37db37999a01fb1f425a19f5a9615faf1059b73 /kernel
parentad71d889b88055e61e3970a6744a271a51a94f42 (diff)
tracing: Add function probe to trigger a ftrace dump of current CPU trace
Add the "cpudump" command to have the current CPU ftrace buffer dumped to console if a function is hit. This is useful when debugging a tripple fault, where you have an idea of a function that is called just before the tripple fault occurs, and can tell ftrace to dump its content out to the console before it continues. This differs from the "dump" command as it only dumps the content of the ring buffer for the currently executing CPU, and does not show the contents of the other CPUs. Format is: <function>:cpudump echo 'bad_address:cpudump' > /debug/tracing/set_ftrace_filter To remove this: echo '!bad_address:cpudump' > /debug/tracing/set_ftrace_filter Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_functions.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index d7c8719734b8..b863f93b30f3 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -297,6 +297,14 @@ ftrace_dump_probe(unsigned long ip, unsigned long parent_ip, void **data)
297 ftrace_dump(DUMP_ALL); 297 ftrace_dump(DUMP_ALL);
298} 298}
299 299
300/* Only dump the current CPU buffer. */
301static void
302ftrace_cpudump_probe(unsigned long ip, unsigned long parent_ip, void **data)
303{
304 if (update_count(data))
305 ftrace_dump(DUMP_ORIG);
306}
307
300static int 308static int
301ftrace_probe_print(const char *name, struct seq_file *m, 309ftrace_probe_print(const char *name, struct seq_file *m,
302 unsigned long ip, void *data) 310 unsigned long ip, void *data)
@@ -341,6 +349,13 @@ ftrace_dump_print(struct seq_file *m, unsigned long ip,
341 return ftrace_probe_print("dump", m, ip, data); 349 return ftrace_probe_print("dump", m, ip, data);
342} 350}
343 351
352static int
353ftrace_cpudump_print(struct seq_file *m, unsigned long ip,
354 struct ftrace_probe_ops *ops, void *data)
355{
356 return ftrace_probe_print("cpudump", m, ip, data);
357}
358
344static struct ftrace_probe_ops traceon_count_probe_ops = { 359static struct ftrace_probe_ops traceon_count_probe_ops = {
345 .func = ftrace_traceon_count, 360 .func = ftrace_traceon_count,
346 .print = ftrace_traceon_print, 361 .print = ftrace_traceon_print,
@@ -361,6 +376,11 @@ static struct ftrace_probe_ops dump_probe_ops = {
361 .print = ftrace_dump_print, 376 .print = ftrace_dump_print,
362}; 377};
363 378
379static struct ftrace_probe_ops cpudump_probe_ops = {
380 .func = ftrace_cpudump_probe,
381 .print = ftrace_cpudump_print,
382};
383
364static struct ftrace_probe_ops traceon_probe_ops = { 384static struct ftrace_probe_ops traceon_probe_ops = {
365 .func = ftrace_traceon, 385 .func = ftrace_traceon,
366 .print = ftrace_traceon_print, 386 .print = ftrace_traceon_print,
@@ -457,6 +477,19 @@ ftrace_dump_callback(struct ftrace_hash *hash,
457 "1", enable); 477 "1", enable);
458} 478}
459 479
480static int
481ftrace_cpudump_callback(struct ftrace_hash *hash,
482 char *glob, char *cmd, char *param, int enable)
483{
484 struct ftrace_probe_ops *ops;
485
486 ops = &cpudump_probe_ops;
487
488 /* Only dump once. */
489 return ftrace_trace_probe_callback(ops, hash, glob, cmd,
490 "1", enable);
491}
492
460static struct ftrace_func_command ftrace_traceon_cmd = { 493static struct ftrace_func_command ftrace_traceon_cmd = {
461 .name = "traceon", 494 .name = "traceon",
462 .func = ftrace_trace_onoff_callback, 495 .func = ftrace_trace_onoff_callback,
@@ -477,6 +510,11 @@ static struct ftrace_func_command ftrace_dump_cmd = {
477 .func = ftrace_dump_callback, 510 .func = ftrace_dump_callback,
478}; 511};
479 512
513static struct ftrace_func_command ftrace_cpudump_cmd = {
514 .name = "cpudump",
515 .func = ftrace_cpudump_callback,
516};
517
480static int __init init_func_cmd_traceon(void) 518static int __init init_func_cmd_traceon(void)
481{ 519{
482 int ret; 520 int ret;
@@ -497,8 +535,14 @@ static int __init init_func_cmd_traceon(void)
497 if (ret) 535 if (ret)
498 goto out_free_stacktrace; 536 goto out_free_stacktrace;
499 537
538 ret = register_ftrace_command(&ftrace_cpudump_cmd);
539 if (ret)
540 goto out_free_dump;
541
500 return 0; 542 return 0;
501 543
544 out_free_dump:
545 unregister_ftrace_command(&ftrace_dump_cmd);
502 out_free_stacktrace: 546 out_free_stacktrace:
503 unregister_ftrace_command(&ftrace_stacktrace_cmd); 547 unregister_ftrace_command(&ftrace_stacktrace_cmd);
504 out_free_traceon: 548 out_free_traceon: