diff options
author | Heiko Carstens <heiko.carstens@de.ibm.com> | 2009-06-12 04:26:47 -0400 |
---|---|---|
committer | Martin Schwidefsky <schwidefsky@de.ibm.com> | 2009-06-12 04:27:39 -0400 |
commit | 9bf1226b33dc2f94fc37ffd70ee161e2bda1ff5c (patch) | |
tree | 3bad5cab583d2940bf9755398a1da7bc77e1b759 | |
parent | 88dbd2037229bd2ed7543ffd0d8f2d9dec9d31d2 (diff) |
[S390] ftrace: add system call tracer support
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>
-rw-r--r-- | arch/s390/Kconfig | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/syscall.h | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/thread_info.h | 2 | ||||
-rw-r--r-- | arch/s390/kernel/entry.S | 4 | ||||
-rw-r--r-- | arch/s390/kernel/entry64.S | 4 | ||||
-rw-r--r-- | arch/s390/kernel/ftrace.c | 56 | ||||
-rw-r--r-- | arch/s390/kernel/ptrace.c | 7 |
7 files changed, 73 insertions, 2 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index 9023cc900bda..99dc3ded6b49 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -84,6 +84,7 @@ config S390 | |||
84 | select HAVE_FUNCTION_TRACER | 84 | select HAVE_FUNCTION_TRACER |
85 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | 85 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST |
86 | select HAVE_FTRACE_MCOUNT_RECORD | 86 | select HAVE_FTRACE_MCOUNT_RECORD |
87 | select HAVE_FTRACE_SYSCALLS | ||
87 | select HAVE_DYNAMIC_FTRACE | 88 | select HAVE_DYNAMIC_FTRACE |
88 | select HAVE_FUNCTION_GRAPH_TRACER | 89 | select HAVE_FUNCTION_GRAPH_TRACER |
89 | select HAVE_DEFAULT_NO_SPIN_MUTEXES | 90 | select HAVE_DEFAULT_NO_SPIN_MUTEXES |
diff --git a/arch/s390/include/asm/syscall.h b/arch/s390/include/asm/syscall.h index 2429b87eb28d..e0a73d3eb837 100644 --- a/arch/s390/include/asm/syscall.h +++ b/arch/s390/include/asm/syscall.h | |||
@@ -12,6 +12,7 @@ | |||
12 | #ifndef _ASM_SYSCALL_H | 12 | #ifndef _ASM_SYSCALL_H |
13 | #define _ASM_SYSCALL_H 1 | 13 | #define _ASM_SYSCALL_H 1 |
14 | 14 | ||
15 | #include <linux/sched.h> | ||
15 | #include <asm/ptrace.h> | 16 | #include <asm/ptrace.h> |
16 | 17 | ||
17 | static inline long syscall_get_nr(struct task_struct *task, | 18 | static inline long syscall_get_nr(struct task_struct *task, |
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index 2f86653dda69..925bcc649035 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h | |||
@@ -92,6 +92,7 @@ static inline struct thread_info *current_thread_info(void) | |||
92 | #define TIF_SYSCALL_TRACE 8 /* syscall trace active */ | 92 | #define TIF_SYSCALL_TRACE 8 /* syscall trace active */ |
93 | #define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ | 93 | #define TIF_SYSCALL_AUDIT 9 /* syscall auditing active */ |
94 | #define TIF_SECCOMP 10 /* secure computing */ | 94 | #define TIF_SECCOMP 10 /* secure computing */ |
95 | #define TIF_SYSCALL_FTRACE 11 /* ftrace syscall instrumentation */ | ||
95 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ | 96 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ |
96 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling | 97 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling |
97 | TIF_NEED_RESCHED */ | 98 | TIF_NEED_RESCHED */ |
@@ -110,6 +111,7 @@ static inline struct thread_info *current_thread_info(void) | |||
110 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 111 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
111 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) | 112 | #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) |
112 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) | 113 | #define _TIF_SECCOMP (1<<TIF_SECCOMP) |
114 | #define _TIF_SYSCALL_FTRACE (1<<TIF_SYSCALL_FTRACE) | ||
113 | #define _TIF_USEDFPU (1<<TIF_USEDFPU) | 115 | #define _TIF_USEDFPU (1<<TIF_USEDFPU) |
114 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) | 116 | #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) |
115 | #define _TIF_31BIT (1<<TIF_31BIT) | 117 | #define _TIF_31BIT (1<<TIF_31BIT) |
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index db25cdc21e12..c4c80a22bc1f 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S | |||
@@ -53,7 +53,8 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | |||
53 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 53 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) |
54 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 54 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
55 | _TIF_MCCK_PENDING) | 55 | _TIF_MCCK_PENDING) |
56 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8) | 56 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ |
57 | _TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8) | ||
57 | 58 | ||
58 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER | 59 | STACK_SHIFT = PAGE_SHIFT + THREAD_ORDER |
59 | STACK_SIZE = 1 << STACK_SHIFT | 60 | STACK_SIZE = 1 << STACK_SHIFT |
@@ -1108,6 +1109,7 @@ cleanup_io_leave_insn: | |||
1108 | 1109 | ||
1109 | .section .rodata, "a" | 1110 | .section .rodata, "a" |
1110 | #define SYSCALL(esa,esame,emu) .long esa | 1111 | #define SYSCALL(esa,esame,emu) .long esa |
1112 | .globl sys_call_table | ||
1111 | sys_call_table: | 1113 | sys_call_table: |
1112 | #include "syscalls.S" | 1114 | #include "syscalls.S" |
1113 | #undef SYSCALL | 1115 | #undef SYSCALL |
diff --git a/arch/s390/kernel/entry64.S b/arch/s390/kernel/entry64.S index 3cec9b504f5f..f6618e9e15ef 100644 --- a/arch/s390/kernel/entry64.S +++ b/arch/s390/kernel/entry64.S | |||
@@ -56,7 +56,8 @@ _TIF_WORK_SVC = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | |||
56 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) | 56 | _TIF_MCCK_PENDING | _TIF_RESTART_SVC | _TIF_SINGLE_STEP ) |
57 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ | 57 | _TIF_WORK_INT = (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED | \ |
58 | _TIF_MCCK_PENDING) | 58 | _TIF_MCCK_PENDING) |
59 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | _TIF_SECCOMP>>8) | 59 | _TIF_SYSCALL = (_TIF_SYSCALL_TRACE>>8 | _TIF_SYSCALL_AUDIT>>8 | \ |
60 | _TIF_SECCOMP>>8 | _TIF_SYSCALL_FTRACE>>8) | ||
60 | 61 | ||
61 | #define BASED(name) name-system_call(%r13) | 62 | #define BASED(name) name-system_call(%r13) |
62 | 63 | ||
@@ -1059,6 +1060,7 @@ cleanup_io_leave_insn: | |||
1059 | 1060 | ||
1060 | .section .rodata, "a" | 1061 | .section .rodata, "a" |
1061 | #define SYSCALL(esa,esame,emu) .long esame | 1062 | #define SYSCALL(esa,esame,emu) .long esame |
1063 | .globl sys_call_table | ||
1062 | sys_call_table: | 1064 | sys_call_table: |
1063 | #include "syscalls.S" | 1065 | #include "syscalls.S" |
1064 | #undef SYSCALL | 1066 | #undef SYSCALL |
diff --git a/arch/s390/kernel/ftrace.c b/arch/s390/kernel/ftrace.c index c92a10953279..82ddfd3a75af 100644 --- a/arch/s390/kernel/ftrace.c +++ b/arch/s390/kernel/ftrace.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/ftrace.h> | 12 | #include <linux/ftrace.h> |
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <trace/syscall.h> | ||
15 | #include <asm/lowcore.h> | 16 | #include <asm/lowcore.h> |
16 | 17 | ||
17 | #ifdef CONFIG_DYNAMIC_FTRACE | 18 | #ifdef CONFIG_DYNAMIC_FTRACE |
@@ -202,3 +203,58 @@ out: | |||
202 | return parent; | 203 | return parent; |
203 | } | 204 | } |
204 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | 205 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ |
206 | |||
207 | #ifdef CONFIG_FTRACE_SYSCALLS | ||
208 | |||
209 | extern unsigned long __start_syscalls_metadata[]; | ||
210 | extern unsigned long __stop_syscalls_metadata[]; | ||
211 | extern unsigned int sys_call_table[]; | ||
212 | |||
213 | static struct syscall_metadata **syscalls_metadata; | ||
214 | |||
215 | struct syscall_metadata *syscall_nr_to_meta(int nr) | ||
216 | { | ||
217 | if (!syscalls_metadata || nr >= NR_syscalls || nr < 0) | ||
218 | return NULL; | ||
219 | |||
220 | return syscalls_metadata[nr]; | ||
221 | } | ||
222 | |||
223 | static struct syscall_metadata *find_syscall_meta(unsigned long syscall) | ||
224 | { | ||
225 | struct syscall_metadata *start; | ||
226 | struct syscall_metadata *stop; | ||
227 | char str[KSYM_SYMBOL_LEN]; | ||
228 | |||
229 | start = (struct syscall_metadata *)__start_syscalls_metadata; | ||
230 | stop = (struct syscall_metadata *)__stop_syscalls_metadata; | ||
231 | kallsyms_lookup(syscall, NULL, NULL, NULL, str); | ||
232 | |||
233 | for ( ; start < stop; start++) { | ||
234 | if (start->name && !strcmp(start->name + 3, str + 3)) | ||
235 | return start; | ||
236 | } | ||
237 | return NULL; | ||
238 | } | ||
239 | |||
240 | void arch_init_ftrace_syscalls(void) | ||
241 | { | ||
242 | struct syscall_metadata *meta; | ||
243 | int i; | ||
244 | static atomic_t refs; | ||
245 | |||
246 | if (atomic_inc_return(&refs) != 1) | ||
247 | goto out; | ||
248 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * NR_syscalls, | ||
249 | GFP_KERNEL); | ||
250 | if (!syscalls_metadata) | ||
251 | goto out; | ||
252 | for (i = 0; i < NR_syscalls; i++) { | ||
253 | meta = find_syscall_meta((unsigned long)sys_call_table[i]); | ||
254 | syscalls_metadata[i] = meta; | ||
255 | } | ||
256 | return; | ||
257 | out: | ||
258 | atomic_dec(&refs); | ||
259 | } | ||
260 | #endif | ||
diff --git a/arch/s390/kernel/ptrace.c b/arch/s390/kernel/ptrace.c index b6fc1ae2ffcb..490b39934d65 100644 --- a/arch/s390/kernel/ptrace.c +++ b/arch/s390/kernel/ptrace.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/regset.h> | 37 | #include <linux/regset.h> |
38 | #include <linux/tracehook.h> | 38 | #include <linux/tracehook.h> |
39 | #include <linux/seccomp.h> | 39 | #include <linux/seccomp.h> |
40 | #include <trace/syscall.h> | ||
40 | #include <asm/compat.h> | 41 | #include <asm/compat.h> |
41 | #include <asm/segment.h> | 42 | #include <asm/segment.h> |
42 | #include <asm/page.h> | 43 | #include <asm/page.h> |
@@ -661,6 +662,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) | |||
661 | ret = -1; | 662 | ret = -1; |
662 | } | 663 | } |
663 | 664 | ||
665 | if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) | ||
666 | ftrace_syscall_enter(regs); | ||
667 | |||
664 | if (unlikely(current->audit_context)) | 668 | if (unlikely(current->audit_context)) |
665 | audit_syscall_entry(is_compat_task() ? | 669 | audit_syscall_entry(is_compat_task() ? |
666 | AUDIT_ARCH_S390 : AUDIT_ARCH_S390X, | 670 | AUDIT_ARCH_S390 : AUDIT_ARCH_S390X, |
@@ -676,6 +680,9 @@ asmlinkage void do_syscall_trace_exit(struct pt_regs *regs) | |||
676 | audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), | 680 | audit_syscall_exit(AUDITSC_RESULT(regs->gprs[2]), |
677 | regs->gprs[2]); | 681 | regs->gprs[2]); |
678 | 682 | ||
683 | if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) | ||
684 | ftrace_syscall_exit(regs); | ||
685 | |||
679 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | 686 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
680 | tracehook_report_syscall_exit(regs, 0); | 687 | tracehook_report_syscall_exit(regs, 0); |
681 | } | 688 | } |