[S390] ftrace: add system call tracer support
authorHeiko Carstens <heiko.carstens@de.ibm.com>
Fri, 12 Jun 2009 08:26:47 +0000 (10:26 +0200)
committerMartin Schwidefsky <schwidefsky@de.ibm.com>
Fri, 12 Jun 2009 08:27:39 +0000 (10:27 +0200)
System call tracer support for s390.

Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com>
Signed-off-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
arch/s390/Kconfig
arch/s390/include/asm/syscall.h
arch/s390/include/asm/thread_info.h
arch/s390/kernel/entry.S
arch/s390/kernel/entry64.S
arch/s390/kernel/ftrace.c
arch/s390/kernel/ptrace.c

index 9023cc900bdae646a3dd2fdf21464ce39a94d183..99dc3ded6b4975dc190d0243b856d539c9a932ce 100644 (file)
@@ -84,6 +84,7 @@ config S390
        select HAVE_FUNCTION_TRACER
        select HAVE_FUNCTION_TRACE_MCOUNT_TEST
        select HAVE_FTRACE_MCOUNT_RECORD
+       select HAVE_FTRACE_SYSCALLS
        select HAVE_DYNAMIC_FTRACE
        select HAVE_FUNCTION_GRAPH_TRACER
        select HAVE_DEFAULT_NO_SPIN_MUTEXES
index 2429b87eb28d92c6fc6adf5a5887f2b29e062d70..e0a73d3eb8371be3bb599413aa09cd65a7f7da56 100644 (file)
@@ -12,6 +12,7 @@
 #ifndef _ASM_SYSCALL_H
 #define _ASM_SYSCALL_H 1
 
+#include <linux/sched.h>
 #include <asm/ptrace.h>
 
 static inline long syscall_get_nr(struct task_struct *task,
index 2f86653dda696481f772538751ef91fbd1cc0834..925bcc6490354c3f2fa2c5dbbca8b37b553b1bd6 100644 (file)
@@ -92,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)
 #define TIF_SYSCALL_TRACE      8       /* syscall trace active */
 #define TIF_SYSCALL_AUDIT      9       /* syscall auditing active */
 #define TIF_SECCOMP            10      /* secure computing */
+#define TIF_SYSCALL_FTRACE     11      /* ftrace syscall instrumentation */
 #define TIF_USEDFPU            16      /* FPU was used by this task this quantum (SMP) */
 #define TIF_POLLING_NRFLAG     17      /* true if poll_idle() is polling 
                                           TIF_NEED_RESCHED */
@@ -110,6 +111,7 @@ static inline struct thread_info *current_thread_info(void)
 #define _TIF_SYSCALL_TRACE     (1<<TIF_SYSCALL_TRACE)
 #define _TIF_SYSCALL_AUDIT     (1<<TIF_SYSCALL_AUDIT)
 #define _TIF_SECCOMP           (1<<TIF_SECCOMP)
+#define _TIF_SYSCALL_FTRACE    (1<<TIF_SYSCALL_FTRACE)
 #define _TIF_USEDFPU           (1<<TIF_USEDFPU)
 #define _TIF_POLLING_NRFLAG    (1<<TIF_POLLING_NRFLAG)
 #define _TIF_31BIT             (1<<TIF_31BIT)
index db25cdc21e12781d67c94f3eb0f363dfa285ec8d..c4c80a22bc1f315215111d240a8756b479e2fe37 100644 (file)
@@ -53,7 +53,8 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
+               _TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8)
 
 STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER
 STACK_SIZE  = 1 << STACK_SHIFT
@@ -1108,6 +1109,7 @@ cleanup_io_leave_insn:
 
                .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esa
+       .globl  sys_call_table
 sys_call_table:
 #include "syscalls.S"
 #undef SYSCALL
index 3cec9b504f5f52fb2af83f004e442ec3784c393d..f6618e9e15efd85b47ca37e4923685edaca85cb8 100644 (file)
@@ -56,7 +56,8 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP )
 _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \
                 _TIF_MCCK_PENDING)
-_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8)
+_TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \
+               _TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8)
 
 #define BASED(name) name-system_call(%r13)
 
@@ -1059,6 +1060,7 @@ cleanup_io_leave_insn:
 
                .section .rodata, "a"
 #define SYSCALL(esa,esame,emu) .long esame
+       .globl  sys_call_table
 sys_call_table:
 #include "syscalls.S"
 #undef SYSCALL
index c92a10953279fc16c0645a6849a9300c59934828..82ddfd3a75aff0e60ac3c2bebae964fcf8808477 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/ftrace.h>
 #include <linux/kernel.h>
 #include <linux/types.h>
+#include <trace/syscall.h>
 #include <asm/lowcore.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
@@ -202,3 +203,58 @@ out:
        return parent;
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
+
+#ifdef CONFIG_FTRACE_SYSCALLS
+
+extern unsigned long __start_syscalls_metadata[];
+extern unsigned long __stop_syscalls_metadata[];
+extern unsigned int sys_call_table[];
+
+static struct syscall_metadata **syscalls_metadata;
+
+struct syscall_metadata *syscall_nr_to_meta(int nr)
+{
+       if (!syscalls_metadata || nr >= NR_syscalls || nr < 0)
+               return NULL;
+
+       return syscalls_metadata[nr];
+}
+
+static struct syscall_metadata *find_syscall_meta(unsigned long syscall)
+{
+       struct syscall_metadata *start;
+       struct syscall_metadata *stop;
+       char str[KSYM_SYMBOL_LEN];
+
+       start = (struct syscall_metadata *)__start_syscalls_metadata;
+       stop = (struct syscall_metadata *)__stop_syscalls_metadata;
+       kallsyms_lookup(syscall, NULL, NULL, NULL, str);
+
+       for ( ; start < stop; start++) {
+               if (start->name && !strcmp(start->name + 3, str + 3))
+                       return start;
+       }
+       return NULL;
+}
+
+void arch_init_ftrace_syscalls(void)
+{
+       struct syscall_metadata *meta;
+       int i;
+       static atomic_t refs;
+
+       if (atomic_inc_return(&refs) != 1)
+               goto out;
+       syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls,
+                                   GFP_KERNEL);
+       if (!syscalls_metadata)
+               goto out;
+       for (i = 0; i < NR_syscalls; i++) {
+               meta = find_syscall_meta((unsigned long)sys_call_table[i]);
+               syscalls_metadata[i] = meta;
+       }
+       return;
+out:
+       atomic_dec(&refs);
+}
+#endif
index b6fc1ae2ffcbfe85dfa5f2b3d720f682e44ff61a..490b39934d65aa8a98cc76f5772b10f3ef9735ea 100644 (file)
@@ -37,6 +37,7 @@
 #include <linux/regset.h>
 #include <linux/tracehook.h>
 #include <linux/seccomp.h>
+#include <trace/syscall.h>
 #include <asm/compat.h>
 #include <asm/segment.h>
 #include <asm/page.h>
@@ -661,6 +662,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
                ret = -1;
        }
 
+       if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+               ftrace_syscall_enter(regs);
+
        if (unlikely(current->audit_context))
                audit_syscall_entry(is_compat_task() ?
                                        AUDIT_ARCH_S390 : AUDIT_ARCH_S390X,
@@ -676,6 +680,9 @@ asmlinkage void do_syscall_trace_exit(struct pt_regs *regs)
                audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]),
                                   regs->gprs[2]);
 
+       if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE)))
+               ftrace_syscall_exit(regs);
+
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall_exit(regs, 0);
 }