diff options
author | Matt Fleming <matt@console-pimps.org> | 2009-07-06 07:16:33 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2009-07-06 07:16:33 -0400 |
commit | c652d780c9cf7f860141de232b37160fe013feca (patch) | |
tree | 110c95ee2b66a7c9b032be8edad36f9b53f82af0 | |
parent | c1340c053be7a43d837a3acb352d5008be865a55 (diff) |
sh: Add ftrace syscall tracing support
Now that I've added TIF_SYSCALL_FTRACE the thread flags do not fit into
a single byte any more. Code testing them now needs to be aware of the
upper and lower bytes.
Signed-off-by: Matt Fleming <matt@console-pimps.org>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
-rw-r--r-- | arch/sh/Kconfig | 1 | ||||
-rw-r--r-- | arch/sh/include/asm/syscall_32.h | 1 | ||||
-rw-r--r-- | arch/sh/include/asm/thread_info.h | 11 | ||||
-rw-r--r-- | arch/sh/kernel/Makefile_32 | 1 | ||||
-rw-r--r-- | arch/sh/kernel/entry-common.S | 18 | ||||
-rw-r--r-- | arch/sh/kernel/ftrace.c | 68 | ||||
-rw-r--r-- | arch/sh/kernel/ptrace_32.c | 8 | ||||
-rw-r--r-- | arch/sh/lib/mcount.S | 2 |
8 files changed, 100 insertions, 10 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index 801a4a79ffe3..29e41ec6537d 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -32,6 +32,7 @@ config SUPERH32 | |||
32 | select HAVE_FTRACE_MCOUNT_RECORD | 32 | select HAVE_FTRACE_MCOUNT_RECORD |
33 | select HAVE_DYNAMIC_FTRACE | 33 | select HAVE_DYNAMIC_FTRACE |
34 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST | 34 | select HAVE_FUNCTION_TRACE_MCOUNT_TEST |
35 | select HAVE_FTRACE_SYSCALLS | ||
35 | select HAVE_ARCH_KGDB | 36 | select HAVE_ARCH_KGDB |
36 | select ARCH_HIBERNATION_POSSIBLE if MMU | 37 | select ARCH_HIBERNATION_POSSIBLE if MMU |
37 | 38 | ||
diff --git a/arch/sh/include/asm/syscall_32.h b/arch/sh/include/asm/syscall_32.h index 6f83f2cc45c1..7d80df4f09cb 100644 --- a/arch/sh/include/asm/syscall_32.h +++ b/arch/sh/include/asm/syscall_32.h | |||
@@ -65,6 +65,7 @@ static inline void syscall_get_arguments(struct task_struct *task, | |||
65 | case 3: args[2] = regs->regs[6]; | 65 | case 3: args[2] = regs->regs[6]; |
66 | case 2: args[1] = regs->regs[5]; | 66 | case 2: args[1] = regs->regs[5]; |
67 | case 1: args[0] = regs->regs[4]; | 67 | case 1: args[0] = regs->regs[4]; |
68 | case 0: | ||
68 | break; | 69 | break; |
69 | default: | 70 | default: |
70 | BUG(); | 71 | BUG(); |
diff --git a/arch/sh/include/asm/thread_info.h b/arch/sh/include/asm/thread_info.h index f09ac4806294..499e315f4be2 100644 --- a/arch/sh/include/asm/thread_info.h +++ b/arch/sh/include/asm/thread_info.h | |||
@@ -97,7 +97,7 @@ static inline struct thread_info *current_thread_info(void) | |||
97 | 97 | ||
98 | extern struct thread_info *alloc_thread_info(struct task_struct *tsk); | 98 | extern struct thread_info *alloc_thread_info(struct task_struct *tsk); |
99 | extern void free_thread_info(struct thread_info *ti); | 99 | extern void free_thread_info(struct thread_info *ti); |
100 | 100 | ||
101 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ | 101 | #endif /* THREAD_SHIFT < PAGE_SHIFT */ |
102 | 102 | ||
103 | #endif /* __ASSEMBLY__ */ | 103 | #endif /* __ASSEMBLY__ */ |
@@ -116,6 +116,7 @@ extern void free_thread_info(struct thread_info *ti); | |||
116 | #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ | 116 | #define TIF_SYSCALL_AUDIT 5 /* syscall auditing active */ |
117 | #define TIF_SECCOMP 6 /* secure computing */ | 117 | #define TIF_SECCOMP 6 /* secure computing */ |
118 | #define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ | 118 | #define TIF_NOTIFY_RESUME 7 /* callback before returning to user */ |
119 | #define TIF_SYSCALL_FTRACE 8 /* for ftrace syscall instrumentation */ | ||
119 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ | 120 | #define TIF_USEDFPU 16 /* FPU was used by this task this quantum (SMP) */ |
120 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ | 121 | #define TIF_POLLING_NRFLAG 17 /* true if poll_idle() is polling TIF_NEED_RESCHED */ |
121 | #define TIF_MEMDIE 18 | 122 | #define TIF_MEMDIE 18 |
@@ -129,25 +130,27 @@ extern void free_thread_info(struct thread_info *ti); | |||
129 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) | 130 | #define _TIF_SYSCALL_AUDIT (1 << TIF_SYSCALL_AUDIT) |
130 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) | 131 | #define _TIF_SECCOMP (1 << TIF_SECCOMP) |
131 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) | 132 | #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) |
133 | #define _TIF_SYSCALL_FTRACE (1 << TIF_SYSCALL_FTRACE) | ||
132 | #define _TIF_USEDFPU (1 << TIF_USEDFPU) | 134 | #define _TIF_USEDFPU (1 << TIF_USEDFPU) |
133 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) | 135 | #define _TIF_POLLING_NRFLAG (1 << TIF_POLLING_NRFLAG) |
134 | #define _TIF_FREEZE (1 << TIF_FREEZE) | 136 | #define _TIF_FREEZE (1 << TIF_FREEZE) |
135 | 137 | ||
136 | /* | 138 | /* |
137 | * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within a byte, or we | 139 | * _TIF_ALLWORK_MASK and _TIF_WORK_MASK need to fit within 2 bytes, or we |
138 | * blow the tst immediate size constraints and need to fix up | 140 | * blow the tst immediate size constraints and need to fix up |
139 | * arch/sh/kernel/entry-common.S. | 141 | * arch/sh/kernel/entry-common.S. |
140 | */ | 142 | */ |
141 | 143 | ||
142 | /* work to do in syscall trace */ | 144 | /* work to do in syscall trace */ |
143 | #define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \ | 145 | #define _TIF_WORK_SYSCALL_MASK (_TIF_SYSCALL_TRACE | _TIF_SINGLESTEP | \ |
144 | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP) | 146 | _TIF_SYSCALL_AUDIT | _TIF_SECCOMP | \ |
147 | _TIF_SYSCALL_FTRACE) | ||
145 | 148 | ||
146 | /* work to do on any return to u-space */ | 149 | /* work to do on any return to u-space */ |
147 | #define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ | 150 | #define _TIF_ALLWORK_MASK (_TIF_SYSCALL_TRACE | _TIF_SIGPENDING | \ |
148 | _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ | 151 | _TIF_NEED_RESCHED | _TIF_SYSCALL_AUDIT | \ |
149 | _TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \ | 152 | _TIF_SINGLESTEP | _TIF_RESTORE_SIGMASK | \ |
150 | _TIF_NOTIFY_RESUME) | 153 | _TIF_NOTIFY_RESUME | _TIF_SYSCALL_FTRACE) |
151 | 154 | ||
152 | /* work to do on interrupt/exception return */ | 155 | /* work to do on interrupt/exception return */ |
153 | #define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ | 156 | #define _TIF_WORK_MASK (_TIF_ALLWORK_MASK & ~(_TIF_SYSCALL_TRACE | \ |
diff --git a/arch/sh/kernel/Makefile_32 b/arch/sh/kernel/Makefile_32 index 9411e3e31e68..fee924a9c46c 100644 --- a/arch/sh/kernel/Makefile_32 +++ b/arch/sh/kernel/Makefile_32 | |||
@@ -29,6 +29,7 @@ obj-$(CONFIG_IO_TRAPPED) += io_trapped.o | |||
29 | obj-$(CONFIG_KPROBES) += kprobes.o | 29 | obj-$(CONFIG_KPROBES) += kprobes.o |
30 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o | 30 | obj-$(CONFIG_GENERIC_GPIO) += gpio.o |
31 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 31 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
32 | obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o | ||
32 | obj-$(CONFIG_DUMP_CODE) += disassemble.o | 33 | obj-$(CONFIG_DUMP_CODE) += disassemble.o |
33 | obj-$(CONFIG_HIBERNATION) += swsusp.o | 34 | obj-$(CONFIG_HIBERNATION) += swsusp.o |
34 | 35 | ||
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index d62359cfbbe2..d62175650c54 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
@@ -131,7 +131,7 @@ ENTRY(resume_userspace) | |||
131 | nop | 131 | nop |
132 | #endif | 132 | #endif |
133 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 133 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
134 | tst #_TIF_WORK_MASK, r0 | 134 | tst #(_TIF_WORK_MASK & 0xff), r0 |
135 | bt/s __restore_all | 135 | bt/s __restore_all |
136 | tst #_TIF_NEED_RESCHED, r0 | 136 | tst #_TIF_NEED_RESCHED, r0 |
137 | 137 | ||
@@ -163,7 +163,7 @@ work_resched: | |||
163 | #endif | 163 | #endif |
164 | ! | 164 | ! |
165 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 165 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
166 | tst #_TIF_WORK_MASK, r0 | 166 | tst #(_TIF_WORK_MASK & 0xff), r0 |
167 | bt __restore_all | 167 | bt __restore_all |
168 | bra work_pending | 168 | bra work_pending |
169 | tst #_TIF_NEED_RESCHED, r0 | 169 | tst #_TIF_NEED_RESCHED, r0 |
@@ -181,7 +181,7 @@ work_resched: | |||
181 | syscall_exit_work: | 181 | syscall_exit_work: |
182 | ! r0: current_thread_info->flags | 182 | ! r0: current_thread_info->flags |
183 | ! r8: current_thread_info | 183 | ! r8: current_thread_info |
184 | tst #_TIF_WORK_SYSCALL_MASK, r0 | 184 | tst #(_TIF_WORK_SYSCALL_MASK & 0xff), r0 |
185 | bt/s work_pending | 185 | bt/s work_pending |
186 | tst #_TIF_NEED_RESCHED, r0 | 186 | tst #_TIF_NEED_RESCHED, r0 |
187 | #ifdef CONFIG_TRACE_IRQFLAGS | 187 | #ifdef CONFIG_TRACE_IRQFLAGS |
@@ -331,8 +331,12 @@ ENTRY(system_call) | |||
331 | ! | 331 | ! |
332 | get_current_thread_info r8, r10 | 332 | get_current_thread_info r8, r10 |
333 | mov.l @(TI_FLAGS,r8), r8 | 333 | mov.l @(TI_FLAGS,r8), r8 |
334 | mov #_TIF_WORK_SYSCALL_MASK, r10 | 334 | mov #(_TIF_WORK_SYSCALL_MASK & 0xff), r10 |
335 | mov #(_TIF_WORK_SYSCALL_MASK >> 8), r9 | ||
335 | tst r10, r8 | 336 | tst r10, r8 |
337 | shll8 r9 | ||
338 | bf syscall_trace_entry | ||
339 | tst r9, r8 | ||
336 | bf syscall_trace_entry | 340 | bf syscall_trace_entry |
337 | ! | 341 | ! |
338 | mov.l 2f, r8 ! Number of syscalls | 342 | mov.l 2f, r8 ! Number of syscalls |
@@ -359,7 +363,11 @@ syscall_exit: | |||
359 | ! | 363 | ! |
360 | get_current_thread_info r8, r0 | 364 | get_current_thread_info r8, r0 |
361 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 365 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
362 | tst #_TIF_ALLWORK_MASK, r0 | 366 | tst #(_TIF_ALLWORK_MASK & 0xff), r0 |
367 | mov #(_TIF_ALLWORK_MASK >> 8), r1 | ||
368 | bf syscall_exit_work | ||
369 | shlr8 r0 | ||
370 | tst r0, r1 | ||
363 | bf syscall_exit_work | 371 | bf syscall_exit_work |
364 | bra __restore_all | 372 | bra __restore_all |
365 | nop | 373 | nop |
diff --git a/arch/sh/kernel/ftrace.c b/arch/sh/kernel/ftrace.c index 066f37dc32a9..4f62eced0aec 100644 --- a/arch/sh/kernel/ftrace.c +++ b/arch/sh/kernel/ftrace.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/io.h> | 18 | #include <linux/io.h> |
19 | #include <asm/ftrace.h> | 19 | #include <asm/ftrace.h> |
20 | #include <asm/cacheflush.h> | 20 | #include <asm/cacheflush.h> |
21 | #include <asm/unistd.h> | ||
22 | #include <trace/syscall.h> | ||
21 | 23 | ||
22 | static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; | 24 | static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; |
23 | 25 | ||
@@ -131,3 +133,69 @@ int __init ftrace_dyn_arch_init(void *data) | |||
131 | 133 | ||
132 | return 0; | 134 | return 0; |
133 | } | 135 | } |
136 | |||
137 | #ifdef CONFIG_FTRACE_SYSCALLS | ||
138 | |||
139 | extern unsigned long __start_syscalls_metadata[]; | ||
140 | extern unsigned long __stop_syscalls_metadata[]; | ||
141 | extern unsigned long *sys_call_table; | ||
142 | |||
143 | static struct syscall_metadata **syscalls_metadata; | ||
144 | |||
145 | static struct syscall_metadata *find_syscall_meta(unsigned long *syscall) | ||
146 | { | ||
147 | struct syscall_metadata *start; | ||
148 | struct syscall_metadata *stop; | ||
149 | char str[KSYM_SYMBOL_LEN]; | ||
150 | |||
151 | |||
152 | start = (struct syscall_metadata *)__start_syscalls_metadata; | ||
153 | stop = (struct syscall_metadata *)__stop_syscalls_metadata; | ||
154 | kallsyms_lookup((unsigned long) syscall, NULL, NULL, NULL, str); | ||
155 | |||
156 | for ( ; start < stop; start++) { | ||
157 | if (start->name && !strcmp(start->name, str)) | ||
158 | return start; | ||
159 | } | ||
160 | |||
161 | return NULL; | ||
162 | } | ||
163 | |||
164 | #define FTRACE_SYSCALL_MAX (NR_syscalls - 1) | ||
165 | |||
166 | struct syscall_metadata *syscall_nr_to_meta(int nr) | ||
167 | { | ||
168 | if (!syscalls_metadata || nr >= FTRACE_SYSCALL_MAX || nr < 0) | ||
169 | return NULL; | ||
170 | |||
171 | return syscalls_metadata[nr]; | ||
172 | } | ||
173 | |||
174 | void arch_init_ftrace_syscalls(void) | ||
175 | { | ||
176 | int i; | ||
177 | struct syscall_metadata *meta; | ||
178 | unsigned long **psys_syscall_table = &sys_call_table; | ||
179 | static atomic_t refs; | ||
180 | |||
181 | if (atomic_inc_return(&refs) != 1) | ||
182 | goto end; | ||
183 | |||
184 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * | ||
185 | FTRACE_SYSCALL_MAX, GFP_KERNEL); | ||
186 | if (!syscalls_metadata) { | ||
187 | WARN_ON(1); | ||
188 | return; | ||
189 | } | ||
190 | |||
191 | for (i = 0; i < FTRACE_SYSCALL_MAX; i++) { | ||
192 | meta = find_syscall_meta(psys_syscall_table[i]); | ||
193 | syscalls_metadata[i] = meta; | ||
194 | } | ||
195 | return; | ||
196 | |||
197 | /* Paranoid: avoid overflow */ | ||
198 | end: | ||
199 | atomic_dec(&refs); | ||
200 | } | ||
201 | #endif /* CONFIG_FTRACE_SYSCALLS */ | ||
diff --git a/arch/sh/kernel/ptrace_32.c b/arch/sh/kernel/ptrace_32.c index 3392e835a374..c198eceaee94 100644 --- a/arch/sh/kernel/ptrace_32.c +++ b/arch/sh/kernel/ptrace_32.c | |||
@@ -34,6 +34,8 @@ | |||
34 | #include <asm/syscalls.h> | 34 | #include <asm/syscalls.h> |
35 | #include <asm/fpu.h> | 35 | #include <asm/fpu.h> |
36 | 36 | ||
37 | #include <trace/syscall.h> | ||
38 | |||
37 | /* | 39 | /* |
38 | * This routine will get a word off of the process kernel stack. | 40 | * This routine will get a word off of the process kernel stack. |
39 | */ | 41 | */ |
@@ -459,6 +461,9 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs) | |||
459 | */ | 461 | */ |
460 | ret = -1L; | 462 | ret = -1L; |
461 | 463 | ||
464 | if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) | ||
465 | ftrace_syscall_enter(regs); | ||
466 | |||
462 | if (unlikely(current->audit_context)) | 467 | if (unlikely(current->audit_context)) |
463 | audit_syscall_entry(audit_arch(), regs->regs[3], | 468 | audit_syscall_entry(audit_arch(), regs->regs[3], |
464 | regs->regs[4], regs->regs[5], | 469 | regs->regs[4], regs->regs[5], |
@@ -475,6 +480,9 @@ asmlinkage void do_syscall_trace_leave(struct pt_regs *regs) | |||
475 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), | 480 | audit_syscall_exit(AUDITSC_RESULT(regs->regs[0]), |
476 | regs->regs[0]); | 481 | regs->regs[0]); |
477 | 482 | ||
483 | if (unlikely(test_thread_flag(TIF_SYSCALL_FTRACE))) | ||
484 | ftrace_syscall_exit(regs); | ||
485 | |||
478 | step = test_thread_flag(TIF_SINGLESTEP); | 486 | step = test_thread_flag(TIF_SINGLESTEP); |
479 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) | 487 | if (step || test_thread_flag(TIF_SYSCALL_TRACE)) |
480 | tracehook_report_syscall_exit(regs, step); | 488 | tracehook_report_syscall_exit(regs, step); |
diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S index cb87ef580b31..71e87f9b4fda 100644 --- a/arch/sh/lib/mcount.S +++ b/arch/sh/lib/mcount.S | |||
@@ -72,7 +72,7 @@ ftrace_caller: | |||
72 | mov.l @r0, r0 | 72 | mov.l @r0, r0 |
73 | tst r0, r0 | 73 | tst r0, r0 |
74 | bf ftrace_stub | 74 | bf ftrace_stub |
75 | 75 | ||
76 | MCOUNT_ENTER() | 76 | MCOUNT_ENTER() |
77 | 77 | ||
78 | .globl ftrace_call | 78 | .globl ftrace_call |