diff options
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
-rw-r--r-- | kernel/trace/trace_syscalls.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index e58a9c11ba85..f4eaec3d559a 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -1,6 +1,7 @@ | |||
1 | #include <trace/syscall.h> | 1 | #include <trace/syscall.h> |
2 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
3 | #include <linux/ftrace.h> | 3 | #include <linux/ftrace.h> |
4 | #include <linux/perf_counter.h> | ||
4 | #include <asm/syscall.h> | 5 | #include <asm/syscall.h> |
5 | 6 | ||
6 | #include "trace_output.h" | 7 | #include "trace_output.h" |
@@ -252,3 +253,123 @@ struct trace_event event_syscall_enter = { | |||
252 | struct trace_event event_syscall_exit = { | 253 | struct trace_event event_syscall_exit = { |
253 | .trace = print_syscall_exit, | 254 | .trace = print_syscall_exit, |
254 | }; | 255 | }; |
256 | |||
257 | #ifdef CONFIG_EVENT_PROFILE | ||
258 | static DECLARE_BITMAP(enabled_prof_enter_syscalls, FTRACE_SYSCALL_MAX); | ||
259 | static DECLARE_BITMAP(enabled_prof_exit_syscalls, FTRACE_SYSCALL_MAX); | ||
260 | static int sys_prof_refcount_enter; | ||
261 | static int sys_prof_refcount_exit; | ||
262 | |||
263 | static void prof_syscall_enter(struct pt_regs *regs, long id) | ||
264 | { | ||
265 | struct syscall_metadata *sys_data; | ||
266 | int syscall_nr; | ||
267 | |||
268 | syscall_nr = syscall_get_nr(current, regs); | ||
269 | if (!test_bit(syscall_nr, enabled_prof_enter_syscalls)) | ||
270 | return; | ||
271 | |||
272 | sys_data = syscall_nr_to_meta(syscall_nr); | ||
273 | if (!sys_data) | ||
274 | return; | ||
275 | |||
276 | perf_tpcounter_event(sys_data->enter_id, 0, 1, NULL, 0); | ||
277 | } | ||
278 | |||
279 | int reg_prof_syscall_enter(char *name) | ||
280 | { | ||
281 | int ret = 0; | ||
282 | int num; | ||
283 | |||
284 | num = syscall_name_to_nr(name); | ||
285 | if (num < 0 || num >= FTRACE_SYSCALL_MAX) | ||
286 | return -ENOSYS; | ||
287 | |||
288 | mutex_lock(&syscall_trace_lock); | ||
289 | if (!sys_prof_refcount_enter) | ||
290 | ret = register_trace_syscall_enter(prof_syscall_enter); | ||
291 | if (ret) { | ||
292 | pr_info("event trace: Could not activate" | ||
293 | "syscall entry trace point"); | ||
294 | } else { | ||
295 | set_bit(num, enabled_prof_enter_syscalls); | ||
296 | sys_prof_refcount_enter++; | ||
297 | } | ||
298 | mutex_unlock(&syscall_trace_lock); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | void unreg_prof_syscall_enter(char *name) | ||
303 | { | ||
304 | int num; | ||
305 | |||
306 | num = syscall_name_to_nr(name); | ||
307 | if (num < 0 || num >= FTRACE_SYSCALL_MAX) | ||
308 | return; | ||
309 | |||
310 | mutex_lock(&syscall_trace_lock); | ||
311 | sys_prof_refcount_enter--; | ||
312 | clear_bit(num, enabled_prof_enter_syscalls); | ||
313 | if (!sys_prof_refcount_enter) | ||
314 | unregister_trace_syscall_enter(prof_syscall_enter); | ||
315 | mutex_unlock(&syscall_trace_lock); | ||
316 | } | ||
317 | |||
318 | static void prof_syscall_exit(struct pt_regs *regs, long ret) | ||
319 | { | ||
320 | struct syscall_metadata *sys_data; | ||
321 | int syscall_nr; | ||
322 | |||
323 | syscall_nr = syscall_get_nr(current, regs); | ||
324 | if (!test_bit(syscall_nr, enabled_prof_exit_syscalls)) | ||
325 | return; | ||
326 | |||
327 | sys_data = syscall_nr_to_meta(syscall_nr); | ||
328 | if (!sys_data) | ||
329 | return; | ||
330 | |||
331 | perf_tpcounter_event(sys_data->exit_id, 0, 1, NULL, 0); | ||
332 | } | ||
333 | |||
334 | int reg_prof_syscall_exit(char *name) | ||
335 | { | ||
336 | int ret = 0; | ||
337 | int num; | ||
338 | |||
339 | num = syscall_name_to_nr(name); | ||
340 | if (num < 0 || num >= FTRACE_SYSCALL_MAX) | ||
341 | return -ENOSYS; | ||
342 | |||
343 | mutex_lock(&syscall_trace_lock); | ||
344 | if (!sys_prof_refcount_exit) | ||
345 | ret = register_trace_syscall_exit(prof_syscall_exit); | ||
346 | if (ret) { | ||
347 | pr_info("event trace: Could not activate" | ||
348 | "syscall entry trace point"); | ||
349 | } else { | ||
350 | set_bit(num, enabled_prof_exit_syscalls); | ||
351 | sys_prof_refcount_exit++; | ||
352 | } | ||
353 | mutex_unlock(&syscall_trace_lock); | ||
354 | return ret; | ||
355 | } | ||
356 | |||
357 | void unreg_prof_syscall_exit(char *name) | ||
358 | { | ||
359 | int num; | ||
360 | |||
361 | num = syscall_name_to_nr(name); | ||
362 | if (num < 0 || num >= FTRACE_SYSCALL_MAX) | ||
363 | return; | ||
364 | |||
365 | mutex_lock(&syscall_trace_lock); | ||
366 | sys_prof_refcount_exit--; | ||
367 | clear_bit(num, enabled_prof_exit_syscalls); | ||
368 | if (!sys_prof_refcount_exit) | ||
369 | unregister_trace_syscall_exit(prof_syscall_exit); | ||
370 | mutex_unlock(&syscall_trace_lock); | ||
371 | } | ||
372 | |||
373 | #endif | ||
374 | |||
375 | |||