diff options
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 */ | ||