aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/ftrace.c10
-rw-r--r--include/linux/syscalls.h22
-rw-r--r--include/trace/syscall.h8
-rw-r--r--kernel/trace/trace.h6
-rw-r--r--kernel/trace/trace_syscalls.c26
5 files changed, 52 insertions, 20 deletions
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 0d93d409b8d2..3cff1214e176 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -516,6 +516,16 @@ int syscall_name_to_nr(char *name)
516 return -1; 516 return -1;
517} 517}
518 518
519void set_syscall_enter_id(int num, int id)
520{
521 syscalls_metadata[num]->enter_id = id;
522}
523
524void set_syscall_exit_id(int num, int id)
525{
526 syscalls_metadata[num]->exit_id = id;
527}
528
519static int __init arch_init_ftrace_syscalls(void) 529static int __init arch_init_ftrace_syscalls(void)
520{ 530{
521 int i; 531 int i;
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h
index 5e5b4d33a31c..ce4b01c658eb 100644
--- a/include/linux/syscalls.h
+++ b/include/linux/syscalls.h
@@ -116,13 +116,20 @@ struct perf_counter_attr;
116 116
117#define SYSCALL_TRACE_ENTER_EVENT(sname) \ 117#define SYSCALL_TRACE_ENTER_EVENT(sname) \
118 static struct ftrace_event_call event_enter_##sname; \ 118 static struct ftrace_event_call event_enter_##sname; \
119 struct trace_event enter_syscall_print_##sname = { \
120 .trace = print_syscall_enter, \
121 }; \
119 static int init_enter_##sname(void) \ 122 static int init_enter_##sname(void) \
120 { \ 123 { \
121 int num; \ 124 int num, id; \
122 num = syscall_name_to_nr("sys"#sname); \ 125 num = syscall_name_to_nr("sys"#sname); \
123 if (num < 0) \ 126 if (num < 0) \
124 return -ENOSYS; \ 127 return -ENOSYS; \
125 register_ftrace_event(&event_syscall_enter); \ 128 id = register_ftrace_event(&enter_syscall_print_##sname);\
129 if (!id) \
130 return -ENODEV; \
131 event_enter_##sname.id = id; \
132 set_syscall_enter_id(num, id); \
126 INIT_LIST_HEAD(&event_enter_##sname.fields); \ 133 INIT_LIST_HEAD(&event_enter_##sname.fields); \
127 init_preds(&event_enter_##sname); \ 134 init_preds(&event_enter_##sname); \
128 return 0; \ 135 return 0; \
@@ -142,13 +149,20 @@ struct perf_counter_attr;
142 149
143#define SYSCALL_TRACE_EXIT_EVENT(sname) \ 150#define SYSCALL_TRACE_EXIT_EVENT(sname) \
144 static struct ftrace_event_call event_exit_##sname; \ 151 static struct ftrace_event_call event_exit_##sname; \
152 struct trace_event exit_syscall_print_##sname = { \
153 .trace = print_syscall_exit, \
154 }; \
145 static int init_exit_##sname(void) \ 155 static int init_exit_##sname(void) \
146 { \ 156 { \
147 int num; \ 157 int num, id; \
148 num = syscall_name_to_nr("sys"#sname); \ 158 num = syscall_name_to_nr("sys"#sname); \
149 if (num < 0) \ 159 if (num < 0) \
150 return -ENOSYS; \ 160 return -ENOSYS; \
151 register_ftrace_event(&event_syscall_exit); \ 161 id = register_ftrace_event(&exit_syscall_print_##sname);\
162 if (!id) \
163 return -ENODEV; \
164 event_exit_##sname.id = id; \
165 set_syscall_exit_id(num, id); \
152 INIT_LIST_HEAD(&event_exit_##sname.fields); \ 166 INIT_LIST_HEAD(&event_exit_##sname.fields); \
153 init_preds(&event_exit_##sname); \ 167 init_preds(&event_exit_##sname); \
154 return 0; \ 168 return 0; \
diff --git a/include/trace/syscall.h b/include/trace/syscall.h
index 73fb8b4a9955..df628404241a 100644
--- a/include/trace/syscall.h
+++ b/include/trace/syscall.h
@@ -32,23 +32,31 @@ DECLARE_TRACE_WITH_CALLBACK(syscall_exit,
32 * @nb_args: number of parameters it takes 32 * @nb_args: number of parameters it takes
33 * @types: list of types as strings 33 * @types: list of types as strings
34 * @args: list of args as strings (args[i] matches types[i]) 34 * @args: list of args as strings (args[i] matches types[i])
35 * @enter_id: associated ftrace enter event id
36 * @exit_id: associated ftrace exit event id
35 */ 37 */
36struct syscall_metadata { 38struct syscall_metadata {
37 const char *name; 39 const char *name;
38 int nb_args; 40 int nb_args;
39 const char **types; 41 const char **types;
40 const char **args; 42 const char **args;
43 int enter_id;
44 int exit_id;
41}; 45};
42 46
43#ifdef CONFIG_FTRACE_SYSCALLS 47#ifdef CONFIG_FTRACE_SYSCALLS
44extern struct syscall_metadata *syscall_nr_to_meta(int nr); 48extern struct syscall_metadata *syscall_nr_to_meta(int nr);
45extern int syscall_name_to_nr(char *name); 49extern int syscall_name_to_nr(char *name);
50void set_syscall_enter_id(int num, int id);
51void set_syscall_exit_id(int num, int id);
46extern struct trace_event event_syscall_enter; 52extern struct trace_event event_syscall_enter;
47extern struct trace_event event_syscall_exit; 53extern struct trace_event event_syscall_exit;
48extern int reg_event_syscall_enter(void *ptr); 54extern int reg_event_syscall_enter(void *ptr);
49extern void unreg_event_syscall_enter(void *ptr); 55extern void unreg_event_syscall_enter(void *ptr);
50extern int reg_event_syscall_exit(void *ptr); 56extern int reg_event_syscall_exit(void *ptr);
51extern void unreg_event_syscall_exit(void *ptr); 57extern void unreg_event_syscall_exit(void *ptr);
58enum print_line_t print_syscall_enter(struct trace_iterator *iter, int flags);
59enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags);
52#endif 60#endif
53 61
54#endif /* _TRACE_SYSCALL_H */ 62#endif /* _TRACE_SYSCALL_H */
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index d682357e4b1f..300ef788c976 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -34,8 +34,6 @@ enum trace_type {
34 TRACE_GRAPH_ENT, 34 TRACE_GRAPH_ENT,
35 TRACE_USER_STACK, 35 TRACE_USER_STACK,
36 TRACE_HW_BRANCHES, 36 TRACE_HW_BRANCHES,
37 TRACE_SYSCALL_ENTER,
38 TRACE_SYSCALL_EXIT,
39 TRACE_KMEM_ALLOC, 37 TRACE_KMEM_ALLOC,
40 TRACE_KMEM_FREE, 38 TRACE_KMEM_FREE,
41 TRACE_POWER, 39 TRACE_POWER,
@@ -319,10 +317,6 @@ extern void __ftrace_bad_type(void);
319 TRACE_KMEM_ALLOC); \ 317 TRACE_KMEM_ALLOC); \
320 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \ 318 IF_ASSIGN(var, ent, struct kmemtrace_free_entry, \
321 TRACE_KMEM_FREE); \ 319 TRACE_KMEM_FREE); \
322 IF_ASSIGN(var, ent, struct syscall_trace_enter, \
323 TRACE_SYSCALL_ENTER); \
324 IF_ASSIGN(var, ent, struct syscall_trace_exit, \
325 TRACE_SYSCALL_EXIT); \
326 __ftrace_bad_type(); \ 320 __ftrace_bad_type(); \
327 } while (0) 321 } while (0)
328 322
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c
index c7ae25ee95d8..e58a9c11ba85 100644
--- a/kernel/trace/trace_syscalls.c
+++ b/kernel/trace/trace_syscalls.c
@@ -36,14 +36,18 @@ print_syscall_enter(struct trace_iterator *iter, int flags)
36 struct syscall_metadata *entry; 36 struct syscall_metadata *entry;
37 int i, ret, syscall; 37 int i, ret, syscall;
38 38
39 trace_assign_type(trace, ent); 39 trace = (typeof(trace))ent;
40
41 syscall = trace->nr; 40 syscall = trace->nr;
42
43 entry = syscall_nr_to_meta(syscall); 41 entry = syscall_nr_to_meta(syscall);
42
44 if (!entry) 43 if (!entry)
45 goto end; 44 goto end;
46 45
46 if (entry->enter_id != ent->type) {
47 WARN_ON_ONCE(1);
48 goto end;
49 }
50
47 ret = trace_seq_printf(s, "%s(", entry->name); 51 ret = trace_seq_printf(s, "%s(", entry->name);
48 if (!ret) 52 if (!ret)
49 return TRACE_TYPE_PARTIAL_LINE; 53 return TRACE_TYPE_PARTIAL_LINE;
@@ -78,16 +82,20 @@ print_syscall_exit(struct trace_iterator *iter, int flags)
78 struct syscall_metadata *entry; 82 struct syscall_metadata *entry;
79 int ret; 83 int ret;
80 84
81 trace_assign_type(trace, ent); 85 trace = (typeof(trace))ent;
82
83 syscall = trace->nr; 86 syscall = trace->nr;
84
85 entry = syscall_nr_to_meta(syscall); 87 entry = syscall_nr_to_meta(syscall);
88
86 if (!entry) { 89 if (!entry) {
87 trace_seq_printf(s, "\n"); 90 trace_seq_printf(s, "\n");
88 return TRACE_TYPE_HANDLED; 91 return TRACE_TYPE_HANDLED;
89 } 92 }
90 93
94 if (entry->exit_id != ent->type) {
95 WARN_ON_ONCE(1);
96 return TRACE_TYPE_UNHANDLED;
97 }
98
91 ret = trace_seq_printf(s, "%s -> 0x%lx\n", entry->name, 99 ret = trace_seq_printf(s, "%s -> 0x%lx\n", entry->name,
92 trace->ret); 100 trace->ret);
93 if (!ret) 101 if (!ret)
@@ -114,7 +122,7 @@ void ftrace_syscall_enter(struct pt_regs *regs, long id)
114 122
115 size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; 123 size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args;
116 124
117 event = trace_current_buffer_lock_reserve(TRACE_SYSCALL_ENTER, size, 125 event = trace_current_buffer_lock_reserve(sys_data->enter_id, size,
118 0, 0); 126 0, 0);
119 if (!event) 127 if (!event)
120 return; 128 return;
@@ -142,7 +150,7 @@ void ftrace_syscall_exit(struct pt_regs *regs, long ret)
142 if (!sys_data) 150 if (!sys_data)
143 return; 151 return;
144 152
145 event = trace_current_buffer_lock_reserve(TRACE_SYSCALL_EXIT, 153 event = trace_current_buffer_lock_reserve(sys_data->exit_id,
146 sizeof(*entry), 0, 0); 154 sizeof(*entry), 0, 0);
147 if (!event) 155 if (!event)
148 return; 156 return;
@@ -239,10 +247,8 @@ void unreg_event_syscall_exit(void *ptr)
239 247
240struct trace_event event_syscall_enter = { 248struct trace_event event_syscall_enter = {
241 .trace = print_syscall_enter, 249 .trace = print_syscall_enter,
242 .type = TRACE_SYSCALL_ENTER
243}; 250};
244 251
245struct trace_event event_syscall_exit = { 252struct trace_event event_syscall_exit = {
246 .trace = print_syscall_exit, 253 .trace = print_syscall_exit,
247 .type = TRACE_SYSCALL_EXIT
248}; 254};