aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2008-11-14 19:21:19 -0500
committerIngo Molnar <mingo@elte.hu>2008-11-16 01:30:07 -0500
commitb17e8a37a13d0e87165054714434534bb7e69f2d (patch)
tree0acfd6ec460bfab35807eb6be058d946c380353e /kernel/trace
parentf3c7ac40a99f4044b843e6e2c4f46ab2d354c563 (diff)
ftrace: disable ftrace on anomalies in trace start and stop
Impact: robust feature to disable ftrace on start or stop tracing on error Currently only the initial conversion to nops will disable ftrace on an anomaly. But if an anomaly happens on start or stopping of the tracer, it will silently fail. This patch adds a check there too, to disable ftrace and warn if the conversion fails. Signed-off-by: Steven Rostedt <srostedt@redhat.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/ftrace.c81
1 files changed, 44 insertions, 37 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 3160254f6c7e..d5bd21f39524 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -348,6 +348,47 @@ ftrace_record_ip(unsigned long ip)
348 return rec; 348 return rec;
349} 349}
350 350
351static void print_ip_ins(const char *fmt, unsigned char *p)
352{
353 int i;
354
355 printk(KERN_CONT "%s", fmt);
356
357 for (i = 0; i < MCOUNT_INSN_SIZE; i++)
358 printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
359}
360
361static void ftrace_bug(int failed, unsigned long ip,
362 unsigned char *expected,
363 unsigned char *replace)
364{
365 switch (failed) {
366 case -EFAULT:
367 FTRACE_WARN_ON_ONCE(1);
368 pr_info("ftrace faulted on modifying ");
369 print_ip_sym(ip);
370 break;
371 case -EINVAL:
372 FTRACE_WARN_ON_ONCE(1);
373 pr_info("ftrace failed to modify ");
374 print_ip_sym(ip);
375 print_ip_ins(" expected: ", expected);
376 print_ip_ins(" actual: ", (unsigned char *)ip);
377 print_ip_ins(" replace: ", replace);
378 printk(KERN_CONT "\n");
379 break;
380 case -EPERM:
381 FTRACE_WARN_ON_ONCE(1);
382 pr_info("ftrace faulted on writing ");
383 print_ip_sym(ip);
384 break;
385 default:
386 FTRACE_WARN_ON_ONCE(1);
387 pr_info("ftrace faulted on unknown error ");
388 print_ip_sym(ip);
389 }
390}
391
351#define FTRACE_ADDR ((long)(ftrace_caller)) 392#define FTRACE_ADDR ((long)(ftrace_caller))
352 393
353static int 394static int
@@ -465,22 +506,13 @@ static void ftrace_replace_code(int enable)
465 if ((system_state == SYSTEM_BOOTING) || 506 if ((system_state == SYSTEM_BOOTING) ||
466 !core_kernel_text(rec->ip)) { 507 !core_kernel_text(rec->ip)) {
467 ftrace_free_rec(rec); 508 ftrace_free_rec(rec);
468 } 509 } else
510 ftrace_bug(failed, rec->ip, old, new);
469 } 511 }
470 } 512 }
471 } 513 }
472} 514}
473 515
474static void print_ip_ins(const char *fmt, unsigned char *p)
475{
476 int i;
477
478 printk(KERN_CONT "%s", fmt);
479
480 for (i = 0; i < MCOUNT_INSN_SIZE; i++)
481 printk(KERN_CONT "%s%02x", i ? ":" : "", p[i]);
482}
483
484static int 516static int
485ftrace_code_disable(struct dyn_ftrace *rec) 517ftrace_code_disable(struct dyn_ftrace *rec)
486{ 518{
@@ -495,32 +527,7 @@ ftrace_code_disable(struct dyn_ftrace *rec)
495 527
496 ret = ftrace_modify_code(ip, call, nop); 528 ret = ftrace_modify_code(ip, call, nop);
497 if (ret) { 529 if (ret) {
498 switch (ret) { 530 ftrace_bug(ret, ip, call, nop);
499 case -EFAULT:
500 FTRACE_WARN_ON_ONCE(1);
501 pr_info("ftrace faulted on modifying ");
502 print_ip_sym(ip);
503 break;
504 case -EINVAL:
505 FTRACE_WARN_ON_ONCE(1);
506 pr_info("ftrace failed to modify ");
507 print_ip_sym(ip);
508 print_ip_ins(" expected: ", call);
509 print_ip_ins(" actual: ", (unsigned char *)ip);
510 print_ip_ins(" replace: ", nop);
511 printk(KERN_CONT "\n");
512 break;
513 case -EPERM:
514 FTRACE_WARN_ON_ONCE(1);
515 pr_info("ftrace faulted on writing ");
516 print_ip_sym(ip);
517 break;
518 default:
519 FTRACE_WARN_ON_ONCE(1);
520 pr_info("ftrace faulted on unknown error ");
521 print_ip_sym(ip);
522 }
523
524 rec->flags |= FTRACE_FL_FAILED; 531 rec->flags |= FTRACE_FL_FAILED;
525 return 0; 532 return 0;
526 } 533 }