aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/include/asm/ftrace.h7
-rw-r--r--arch/x86/kernel/ftrace.c63
2 files changed, 70 insertions, 0 deletions
diff --git a/arch/x86/include/asm/ftrace.h b/arch/x86/include/asm/ftrace.h
index db24c2278be0..bd2c6511c887 100644
--- a/arch/x86/include/asm/ftrace.h
+++ b/arch/x86/include/asm/ftrace.h
@@ -28,6 +28,13 @@
28 28
29#endif 29#endif
30 30
31/* FIXME: I don't want to stay hardcoded */
32#ifdef CONFIG_X86_64
33# define FTRACE_SYSCALL_MAX 296
34#else
35# define FTRACE_SYSCALL_MAX 333
36#endif
37
31#ifdef CONFIG_FUNCTION_TRACER 38#ifdef CONFIG_FUNCTION_TRACER
32#define MCOUNT_ADDR ((long)(mcount)) 39#define MCOUNT_ADDR ((long)(mcount))
33#define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */ 40#define MCOUNT_INSN_SIZE 5 /* sizeof mcount call */
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index a85da1764b1c..1d0d7f42efe3 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -453,3 +453,66 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr)
453 } 453 }
454} 454}
455#endif /* CONFIG_FUNCTION_GRAPH_TRACER */ 455#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
456
457#ifdef CONFIG_FTRACE_SYSCALLS
458
459extern unsigned long __start_syscalls_metadata[];
460extern unsigned long __stop_syscalls_metadata[];
461extern unsigned long *sys_call_table;
462
463static struct syscall_metadata **syscalls_metadata;
464
465static struct syscall_metadata *find_syscall_meta(unsigned long *syscall)
466{
467 struct syscall_metadata *start;
468 struct syscall_metadata *stop;
469 char str[KSYM_SYMBOL_LEN];
470
471
472 start = (struct syscall_metadata *)__start_syscalls_metadata;
473 stop = (struct syscall_metadata *)__stop_syscalls_metadata;
474 kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str);
475
476 for ( ; start < stop; start++) {
477 if (start->name && !strcmp(start->name, str))
478 return start;
479 }
480 return NULL;
481}
482
483struct syscall_metadata *syscall_nr_to_meta(int nr)
484{
485 if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0)
486 return NULL;
487
488 return syscalls_metadata[nr];
489}
490
491void arch_init_ftrace_syscalls(void)
492{
493 int i;
494 struct syscall_metadata *meta;
495 unsigned long **psys_syscall_table = &sys_call_table;
496 static atomic_t refs;
497
498 if (atomic_inc_return(&refs) != 1)
499 goto end;
500
501 syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) *
502 FTRACE_SYSCALL_MAX, GFP_KERNEL);
503 if (!syscalls_metadata) {
504 WARN_ON(1);
505 return;
506 }
507
508 for (i = 0; i < FTRACE_SYSCALL_MAX; i++) {
509 meta = find_syscall_meta(psys_syscall_table[i]);
510 syscalls_metadata[i] = meta;
511 }
512 return;
513
514 /* Paranoid: avoid overflow */
515end:
516 atomic_dec(&refs);
517}
518#endif