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 /arch/sh/kernel/ftrace.c | |
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>
Diffstat (limited to 'arch/sh/kernel/ftrace.c')
-rw-r--r-- | arch/sh/kernel/ftrace.c | 68 |
1 files changed, 68 insertions, 0 deletions
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 */ | ||