aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatt Fleming <matt@console-pimps.org>2009-07-06 07:16:33 -0400
committerPaul Mundt <lethal@linux-sh.org>2009-07-06 07:16:33 -0400
commitc652d780c9cf7f860141de232b37160fe013feca (patch)
tree110c95ee2b66a7c9b032be8edad36f9b53f82af0
parentc1340c053be7a43d837a3acb352d5008be865a55 (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/Kconfig1
-rw-r--r--arch/sh/include/asm/syscall_32.h1
-rw-r--r--arch/sh/include/asm/thread_info.h11
-rw-r--r--arch/sh/kernel/Makefile_321
-rw-r--r--arch/sh/kernel/entry-common.S18
-rw-r--r--arch/sh/kernel/ftrace.c68
-rw-r--r--arch/sh/kernel/ptrace_32.c8
-rw-r--r--arch/sh/lib/mcount.S2
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
98extern struct thread_info *alloc_thread_info(struct task_struct *tsk); 98extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
99extern void free_thread_info(struct thread_info *ti); 99extern 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
29obj-$(CONFIG_KPROBES) += kprobes.o 29obj-$(CONFIG_KPROBES) += kprobes.o
30obj-$(CONFIG_GENERIC_GPIO) += gpio.o 30obj-$(CONFIG_GENERIC_GPIO) += gpio.o
31obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o 31obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o
32obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o
32obj-$(CONFIG_DUMP_CODE) += disassemble.o 33obj-$(CONFIG_DUMP_CODE) += disassemble.o
33obj-$(CONFIG_HIBERNATION) += swsusp.o 34obj-$(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:
181syscall_exit_work: 181syscall_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
22static unsigned char ftrace_replaced_code[MCOUNT_INSN_SIZE]; 24static 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
139extern unsigned long __start_syscalls_metadata[];
140extern unsigned long __stop_syscalls_metadata[];
141extern unsigned long *sys_call_table;
142
143static struct syscall_metadata **syscalls_metadata;
144
145static 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
166struct 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
174void 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 */
198end:
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