aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_syscalls.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
-rw-r--r--kernel/trace/trace_syscalls.c121
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 = {
252struct trace_event event_syscall_exit = { 253struct trace_event event_syscall_exit = {
253 .trace = print_syscall_exit, 254 .trace = print_syscall_exit,
254}; 255};
256
257#ifdef CONFIG_EVENT_PROFILE
258static DECLARE_BITMAP(enabled_prof_enter_syscalls, FTRACE_SYSCALL_MAX);
259static DECLARE_BITMAP(enabled_prof_exit_syscalls, FTRACE_SYSCALL_MAX);
260static int sys_prof_refcount_enter;
261static int sys_prof_refcount_exit;
262
263static 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
279int 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
302void 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
318static 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
334int 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
357void 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