diff options
Diffstat (limited to 'kernel/trace/trace_syscalls.c')
-rw-r--r-- | kernel/trace/trace_syscalls.c | 229 |
1 files changed, 146 insertions, 83 deletions
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index 527e17eae575..57501d90096a 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -14,6 +14,43 @@ static int sys_refcount_exit; | |||
14 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); | 14 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); |
15 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); | 15 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); |
16 | 16 | ||
17 | extern unsigned long __start_syscalls_metadata[]; | ||
18 | extern unsigned long __stop_syscalls_metadata[]; | ||
19 | |||
20 | static struct syscall_metadata **syscalls_metadata; | ||
21 | |||
22 | static struct syscall_metadata *find_syscall_meta(unsigned long syscall) | ||
23 | { | ||
24 | struct syscall_metadata *start; | ||
25 | struct syscall_metadata *stop; | ||
26 | char str[KSYM_SYMBOL_LEN]; | ||
27 | |||
28 | |||
29 | start = (struct syscall_metadata *)__start_syscalls_metadata; | ||
30 | stop = (struct syscall_metadata *)__stop_syscalls_metadata; | ||
31 | kallsyms_lookup(syscall, NULL, NULL, NULL, str); | ||
32 | |||
33 | for ( ; start < stop; start++) { | ||
34 | /* | ||
35 | * Only compare after the "sys" prefix. Archs that use | ||
36 | * syscall wrappers may have syscalls symbols aliases prefixed | ||
37 | * with "SyS" instead of "sys", leading to an unwanted | ||
38 | * mismatch. | ||
39 | */ | ||
40 | if (start->name && !strcmp(start->name + 3, str + 3)) | ||
41 | return start; | ||
42 | } | ||
43 | return NULL; | ||
44 | } | ||
45 | |||
46 | static struct syscall_metadata *syscall_nr_to_meta(int nr) | ||
47 | { | ||
48 | if (!syscalls_metadata || nr >= NR_syscalls || nr < 0) | ||
49 | return NULL; | ||
50 | |||
51 | return syscalls_metadata[nr]; | ||
52 | } | ||
53 | |||
17 | enum print_line_t | 54 | enum print_line_t |
18 | print_syscall_enter(struct trace_iterator *iter, int flags) | 55 | print_syscall_enter(struct trace_iterator *iter, int flags) |
19 | { | 56 | { |
@@ -30,7 +67,7 @@ print_syscall_enter(struct trace_iterator *iter, int flags) | |||
30 | if (!entry) | 67 | if (!entry) |
31 | goto end; | 68 | goto end; |
32 | 69 | ||
33 | if (entry->enter_id != ent->type) { | 70 | if (entry->enter_event->id != ent->type) { |
34 | WARN_ON_ONCE(1); | 71 | WARN_ON_ONCE(1); |
35 | goto end; | 72 | goto end; |
36 | } | 73 | } |
@@ -85,7 +122,7 @@ print_syscall_exit(struct trace_iterator *iter, int flags) | |||
85 | return TRACE_TYPE_HANDLED; | 122 | return TRACE_TYPE_HANDLED; |
86 | } | 123 | } |
87 | 124 | ||
88 | if (entry->exit_id != ent->type) { | 125 | if (entry->exit_event->id != ent->type) { |
89 | WARN_ON_ONCE(1); | 126 | WARN_ON_ONCE(1); |
90 | return TRACE_TYPE_UNHANDLED; | 127 | return TRACE_TYPE_UNHANDLED; |
91 | } | 128 | } |
@@ -103,24 +140,19 @@ extern char *__bad_type_size(void); | |||
103 | #define SYSCALL_FIELD(type, name) \ | 140 | #define SYSCALL_FIELD(type, name) \ |
104 | sizeof(type) != sizeof(trace.name) ? \ | 141 | sizeof(type) != sizeof(trace.name) ? \ |
105 | __bad_type_size() : \ | 142 | __bad_type_size() : \ |
106 | #type, #name, offsetof(typeof(trace), name), sizeof(trace.name) | 143 | #type, #name, offsetof(typeof(trace), name), \ |
144 | sizeof(trace.name), is_signed_type(type) | ||
107 | 145 | ||
108 | int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) | 146 | int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) |
109 | { | 147 | { |
110 | int i; | 148 | int i; |
111 | int nr; | ||
112 | int ret; | 149 | int ret; |
113 | struct syscall_metadata *entry; | 150 | struct syscall_metadata *entry = call->data; |
114 | struct syscall_trace_enter trace; | 151 | struct syscall_trace_enter trace; |
115 | int offset = offsetof(struct syscall_trace_enter, args); | 152 | int offset = offsetof(struct syscall_trace_enter, args); |
116 | 153 | ||
117 | nr = syscall_name_to_nr(call->data); | 154 | ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;" |
118 | entry = syscall_nr_to_meta(nr); | 155 | "\tsigned:%u;\n", |
119 | |||
120 | if (!entry) | ||
121 | return 0; | ||
122 | |||
123 | ret = trace_seq_printf(s, "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", | ||
124 | SYSCALL_FIELD(int, nr)); | 156 | SYSCALL_FIELD(int, nr)); |
125 | if (!ret) | 157 | if (!ret) |
126 | return 0; | 158 | return 0; |
@@ -130,8 +162,10 @@ int syscall_enter_format(struct ftrace_event_call *call, struct trace_seq *s) | |||
130 | entry->args[i]); | 162 | entry->args[i]); |
131 | if (!ret) | 163 | if (!ret) |
132 | return 0; | 164 | return 0; |
133 | ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;\n", offset, | 165 | ret = trace_seq_printf(s, "\toffset:%d;\tsize:%zu;" |
134 | sizeof(unsigned long)); | 166 | "\tsigned:%u;\n", offset, |
167 | sizeof(unsigned long), | ||
168 | is_signed_type(unsigned long)); | ||
135 | if (!ret) | 169 | if (!ret) |
136 | return 0; | 170 | return 0; |
137 | offset += sizeof(unsigned long); | 171 | offset += sizeof(unsigned long); |
@@ -163,8 +197,10 @@ int syscall_exit_format(struct ftrace_event_call *call, struct trace_seq *s) | |||
163 | struct syscall_trace_exit trace; | 197 | struct syscall_trace_exit trace; |
164 | 198 | ||
165 | ret = trace_seq_printf(s, | 199 | ret = trace_seq_printf(s, |
166 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n" | 200 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;" |
167 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;\n", | 201 | "\tsigned:%u;\n" |
202 | "\tfield:%s %s;\toffset:%zu;\tsize:%zu;" | ||
203 | "\tsigned:%u;\n", | ||
168 | SYSCALL_FIELD(int, nr), | 204 | SYSCALL_FIELD(int, nr), |
169 | SYSCALL_FIELD(long, ret)); | 205 | SYSCALL_FIELD(long, ret)); |
170 | if (!ret) | 206 | if (!ret) |
@@ -176,22 +212,19 @@ int syscall_exit_format(struct ftrace_event_call *call, struct trace_seq *s) | |||
176 | int syscall_enter_define_fields(struct ftrace_event_call *call) | 212 | int syscall_enter_define_fields(struct ftrace_event_call *call) |
177 | { | 213 | { |
178 | struct syscall_trace_enter trace; | 214 | struct syscall_trace_enter trace; |
179 | struct syscall_metadata *meta; | 215 | struct syscall_metadata *meta = call->data; |
180 | int ret; | 216 | int ret; |
181 | int nr; | ||
182 | int i; | 217 | int i; |
183 | int offset = offsetof(typeof(trace), args); | 218 | int offset = offsetof(typeof(trace), args); |
184 | 219 | ||
185 | nr = syscall_name_to_nr(call->data); | ||
186 | meta = syscall_nr_to_meta(nr); | ||
187 | |||
188 | if (!meta) | ||
189 | return 0; | ||
190 | |||
191 | ret = trace_define_common_fields(call); | 220 | ret = trace_define_common_fields(call); |
192 | if (ret) | 221 | if (ret) |
193 | return ret; | 222 | return ret; |
194 | 223 | ||
224 | ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER); | ||
225 | if (ret) | ||
226 | return ret; | ||
227 | |||
195 | for (i = 0; i < meta->nb_args; i++) { | 228 | for (i = 0; i < meta->nb_args; i++) { |
196 | ret = trace_define_field(call, meta->types[i], | 229 | ret = trace_define_field(call, meta->types[i], |
197 | meta->args[i], offset, | 230 | meta->args[i], offset, |
@@ -212,7 +245,11 @@ int syscall_exit_define_fields(struct ftrace_event_call *call) | |||
212 | if (ret) | 245 | if (ret) |
213 | return ret; | 246 | return ret; |
214 | 247 | ||
215 | ret = trace_define_field(call, SYSCALL_FIELD(long, ret), 0, | 248 | ret = trace_define_field(call, SYSCALL_FIELD(int, nr), FILTER_OTHER); |
249 | if (ret) | ||
250 | return ret; | ||
251 | |||
252 | ret = trace_define_field(call, SYSCALL_FIELD(long, ret), | ||
216 | FILTER_OTHER); | 253 | FILTER_OTHER); |
217 | 254 | ||
218 | return ret; | 255 | return ret; |
@@ -239,8 +276,8 @@ void ftrace_syscall_enter(struct pt_regs *regs, long id) | |||
239 | 276 | ||
240 | size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; | 277 | size = sizeof(*entry) + sizeof(unsigned long) * sys_data->nb_args; |
241 | 278 | ||
242 | event = trace_current_buffer_lock_reserve(&buffer, sys_data->enter_id, | 279 | event = trace_current_buffer_lock_reserve(&buffer, |
243 | size, 0, 0); | 280 | sys_data->enter_event->id, size, 0, 0); |
244 | if (!event) | 281 | if (!event) |
245 | return; | 282 | return; |
246 | 283 | ||
@@ -271,8 +308,8 @@ void ftrace_syscall_exit(struct pt_regs *regs, long ret) | |||
271 | if (!sys_data) | 308 | if (!sys_data) |
272 | return; | 309 | return; |
273 | 310 | ||
274 | event = trace_current_buffer_lock_reserve(&buffer, sys_data->exit_id, | 311 | event = trace_current_buffer_lock_reserve(&buffer, |
275 | sizeof(*entry), 0, 0); | 312 | sys_data->exit_event->id, sizeof(*entry), 0, 0); |
276 | if (!event) | 313 | if (!event) |
277 | return; | 314 | return; |
278 | 315 | ||
@@ -285,14 +322,12 @@ void ftrace_syscall_exit(struct pt_regs *regs, long ret) | |||
285 | trace_current_buffer_unlock_commit(buffer, event, 0, 0); | 322 | trace_current_buffer_unlock_commit(buffer, event, 0, 0); |
286 | } | 323 | } |
287 | 324 | ||
288 | int reg_event_syscall_enter(void *ptr) | 325 | int reg_event_syscall_enter(struct ftrace_event_call *call) |
289 | { | 326 | { |
290 | int ret = 0; | 327 | int ret = 0; |
291 | int num; | 328 | int num; |
292 | char *name; | ||
293 | 329 | ||
294 | name = (char *)ptr; | 330 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
295 | num = syscall_name_to_nr(name); | ||
296 | if (num < 0 || num >= NR_syscalls) | 331 | if (num < 0 || num >= NR_syscalls) |
297 | return -ENOSYS; | 332 | return -ENOSYS; |
298 | mutex_lock(&syscall_trace_lock); | 333 | mutex_lock(&syscall_trace_lock); |
@@ -309,13 +344,11 @@ int reg_event_syscall_enter(void *ptr) | |||
309 | return ret; | 344 | return ret; |
310 | } | 345 | } |
311 | 346 | ||
312 | void unreg_event_syscall_enter(void *ptr) | 347 | void unreg_event_syscall_enter(struct ftrace_event_call *call) |
313 | { | 348 | { |
314 | int num; | 349 | int num; |
315 | char *name; | ||
316 | 350 | ||
317 | name = (char *)ptr; | 351 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
318 | num = syscall_name_to_nr(name); | ||
319 | if (num < 0 || num >= NR_syscalls) | 352 | if (num < 0 || num >= NR_syscalls) |
320 | return; | 353 | return; |
321 | mutex_lock(&syscall_trace_lock); | 354 | mutex_lock(&syscall_trace_lock); |
@@ -326,14 +359,12 @@ void unreg_event_syscall_enter(void *ptr) | |||
326 | mutex_unlock(&syscall_trace_lock); | 359 | mutex_unlock(&syscall_trace_lock); |
327 | } | 360 | } |
328 | 361 | ||
329 | int reg_event_syscall_exit(void *ptr) | 362 | int reg_event_syscall_exit(struct ftrace_event_call *call) |
330 | { | 363 | { |
331 | int ret = 0; | 364 | int ret = 0; |
332 | int num; | 365 | int num; |
333 | char *name; | ||
334 | 366 | ||
335 | name = (char *)ptr; | 367 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
336 | num = syscall_name_to_nr(name); | ||
337 | if (num < 0 || num >= NR_syscalls) | 368 | if (num < 0 || num >= NR_syscalls) |
338 | return -ENOSYS; | 369 | return -ENOSYS; |
339 | mutex_lock(&syscall_trace_lock); | 370 | mutex_lock(&syscall_trace_lock); |
@@ -350,13 +381,11 @@ int reg_event_syscall_exit(void *ptr) | |||
350 | return ret; | 381 | return ret; |
351 | } | 382 | } |
352 | 383 | ||
353 | void unreg_event_syscall_exit(void *ptr) | 384 | void unreg_event_syscall_exit(struct ftrace_event_call *call) |
354 | { | 385 | { |
355 | int num; | 386 | int num; |
356 | char *name; | ||
357 | 387 | ||
358 | name = (char *)ptr; | 388 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
359 | num = syscall_name_to_nr(name); | ||
360 | if (num < 0 || num >= NR_syscalls) | 389 | if (num < 0 || num >= NR_syscalls) |
361 | return; | 390 | return; |
362 | mutex_lock(&syscall_trace_lock); | 391 | mutex_lock(&syscall_trace_lock); |
@@ -367,13 +396,44 @@ void unreg_event_syscall_exit(void *ptr) | |||
367 | mutex_unlock(&syscall_trace_lock); | 396 | mutex_unlock(&syscall_trace_lock); |
368 | } | 397 | } |
369 | 398 | ||
370 | struct trace_event event_syscall_enter = { | 399 | int init_syscall_trace(struct ftrace_event_call *call) |
371 | .trace = print_syscall_enter, | 400 | { |
372 | }; | 401 | int id; |
402 | |||
403 | id = register_ftrace_event(call->event); | ||
404 | if (!id) | ||
405 | return -ENODEV; | ||
406 | call->id = id; | ||
407 | INIT_LIST_HEAD(&call->fields); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | int __init init_ftrace_syscalls(void) | ||
412 | { | ||
413 | struct syscall_metadata *meta; | ||
414 | unsigned long addr; | ||
415 | int i; | ||
416 | |||
417 | syscalls_metadata = kzalloc(sizeof(*syscalls_metadata) * | ||
418 | NR_syscalls, GFP_KERNEL); | ||
419 | if (!syscalls_metadata) { | ||
420 | WARN_ON(1); | ||
421 | return -ENOMEM; | ||
422 | } | ||
423 | |||
424 | for (i = 0; i < NR_syscalls; i++) { | ||
425 | addr = arch_syscall_addr(i); | ||
426 | meta = find_syscall_meta(addr); | ||
427 | if (!meta) | ||
428 | continue; | ||
429 | |||
430 | meta->syscall_nr = i; | ||
431 | syscalls_metadata[i] = meta; | ||
432 | } | ||
373 | 433 | ||
374 | struct trace_event event_syscall_exit = { | 434 | return 0; |
375 | .trace = print_syscall_exit, | 435 | } |
376 | }; | 436 | core_initcall(init_ftrace_syscalls); |
377 | 437 | ||
378 | #ifdef CONFIG_EVENT_PROFILE | 438 | #ifdef CONFIG_EVENT_PROFILE |
379 | 439 | ||
@@ -387,8 +447,10 @@ static void prof_syscall_enter(struct pt_regs *regs, long id) | |||
387 | struct syscall_metadata *sys_data; | 447 | struct syscall_metadata *sys_data; |
388 | struct syscall_trace_enter *rec; | 448 | struct syscall_trace_enter *rec; |
389 | unsigned long flags; | 449 | unsigned long flags; |
450 | char *trace_buf; | ||
390 | char *raw_data; | 451 | char *raw_data; |
391 | int syscall_nr; | 452 | int syscall_nr; |
453 | int rctx; | ||
392 | int size; | 454 | int size; |
393 | int cpu; | 455 | int cpu; |
394 | 456 | ||
@@ -412,41 +474,42 @@ static void prof_syscall_enter(struct pt_regs *regs, long id) | |||
412 | /* Protect the per cpu buffer, begin the rcu read side */ | 474 | /* Protect the per cpu buffer, begin the rcu read side */ |
413 | local_irq_save(flags); | 475 | local_irq_save(flags); |
414 | 476 | ||
477 | rctx = perf_swevent_get_recursion_context(); | ||
478 | if (rctx < 0) | ||
479 | goto end_recursion; | ||
480 | |||
415 | cpu = smp_processor_id(); | 481 | cpu = smp_processor_id(); |
416 | 482 | ||
417 | if (in_nmi()) | 483 | trace_buf = rcu_dereference(perf_trace_buf); |
418 | raw_data = rcu_dereference(trace_profile_buf_nmi); | ||
419 | else | ||
420 | raw_data = rcu_dereference(trace_profile_buf); | ||
421 | 484 | ||
422 | if (!raw_data) | 485 | if (!trace_buf) |
423 | goto end; | 486 | goto end; |
424 | 487 | ||
425 | raw_data = per_cpu_ptr(raw_data, cpu); | 488 | raw_data = per_cpu_ptr(trace_buf, cpu); |
426 | 489 | ||
427 | /* zero the dead bytes from align to not leak stack to user */ | 490 | /* zero the dead bytes from align to not leak stack to user */ |
428 | *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; | 491 | *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; |
429 | 492 | ||
430 | rec = (struct syscall_trace_enter *) raw_data; | 493 | rec = (struct syscall_trace_enter *) raw_data; |
431 | tracing_generic_entry_update(&rec->ent, 0, 0); | 494 | tracing_generic_entry_update(&rec->ent, 0, 0); |
432 | rec->ent.type = sys_data->enter_id; | 495 | rec->ent.type = sys_data->enter_event->id; |
433 | rec->nr = syscall_nr; | 496 | rec->nr = syscall_nr; |
434 | syscall_get_arguments(current, regs, 0, sys_data->nb_args, | 497 | syscall_get_arguments(current, regs, 0, sys_data->nb_args, |
435 | (unsigned long *)&rec->args); | 498 | (unsigned long *)&rec->args); |
436 | perf_tp_event(sys_data->enter_id, 0, 1, rec, size); | 499 | perf_tp_event(sys_data->enter_event->id, 0, 1, rec, size); |
437 | 500 | ||
438 | end: | 501 | end: |
502 | perf_swevent_put_recursion_context(rctx); | ||
503 | end_recursion: | ||
439 | local_irq_restore(flags); | 504 | local_irq_restore(flags); |
440 | } | 505 | } |
441 | 506 | ||
442 | int reg_prof_syscall_enter(char *name) | 507 | int prof_sysenter_enable(struct ftrace_event_call *call) |
443 | { | 508 | { |
444 | int ret = 0; | 509 | int ret = 0; |
445 | int num; | 510 | int num; |
446 | 511 | ||
447 | num = syscall_name_to_nr(name); | 512 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
448 | if (num < 0 || num >= NR_syscalls) | ||
449 | return -ENOSYS; | ||
450 | 513 | ||
451 | mutex_lock(&syscall_trace_lock); | 514 | mutex_lock(&syscall_trace_lock); |
452 | if (!sys_prof_refcount_enter) | 515 | if (!sys_prof_refcount_enter) |
@@ -462,13 +525,11 @@ int reg_prof_syscall_enter(char *name) | |||
462 | return ret; | 525 | return ret; |
463 | } | 526 | } |
464 | 527 | ||
465 | void unreg_prof_syscall_enter(char *name) | 528 | void prof_sysenter_disable(struct ftrace_event_call *call) |
466 | { | 529 | { |
467 | int num; | 530 | int num; |
468 | 531 | ||
469 | num = syscall_name_to_nr(name); | 532 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
470 | if (num < 0 || num >= NR_syscalls) | ||
471 | return; | ||
472 | 533 | ||
473 | mutex_lock(&syscall_trace_lock); | 534 | mutex_lock(&syscall_trace_lock); |
474 | sys_prof_refcount_enter--; | 535 | sys_prof_refcount_enter--; |
@@ -484,7 +545,9 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret) | |||
484 | struct syscall_trace_exit *rec; | 545 | struct syscall_trace_exit *rec; |
485 | unsigned long flags; | 546 | unsigned long flags; |
486 | int syscall_nr; | 547 | int syscall_nr; |
548 | char *trace_buf; | ||
487 | char *raw_data; | 549 | char *raw_data; |
550 | int rctx; | ||
488 | int size; | 551 | int size; |
489 | int cpu; | 552 | int cpu; |
490 | 553 | ||
@@ -510,17 +573,19 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret) | |||
510 | 573 | ||
511 | /* Protect the per cpu buffer, begin the rcu read side */ | 574 | /* Protect the per cpu buffer, begin the rcu read side */ |
512 | local_irq_save(flags); | 575 | local_irq_save(flags); |
576 | |||
577 | rctx = perf_swevent_get_recursion_context(); | ||
578 | if (rctx < 0) | ||
579 | goto end_recursion; | ||
580 | |||
513 | cpu = smp_processor_id(); | 581 | cpu = smp_processor_id(); |
514 | 582 | ||
515 | if (in_nmi()) | 583 | trace_buf = rcu_dereference(perf_trace_buf); |
516 | raw_data = rcu_dereference(trace_profile_buf_nmi); | ||
517 | else | ||
518 | raw_data = rcu_dereference(trace_profile_buf); | ||
519 | 584 | ||
520 | if (!raw_data) | 585 | if (!trace_buf) |
521 | goto end; | 586 | goto end; |
522 | 587 | ||
523 | raw_data = per_cpu_ptr(raw_data, cpu); | 588 | raw_data = per_cpu_ptr(trace_buf, cpu); |
524 | 589 | ||
525 | /* zero the dead bytes from align to not leak stack to user */ | 590 | /* zero the dead bytes from align to not leak stack to user */ |
526 | *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; | 591 | *(u64 *)(&raw_data[size - sizeof(u64)]) = 0ULL; |
@@ -528,24 +593,24 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret) | |||
528 | rec = (struct syscall_trace_exit *)raw_data; | 593 | rec = (struct syscall_trace_exit *)raw_data; |
529 | 594 | ||
530 | tracing_generic_entry_update(&rec->ent, 0, 0); | 595 | tracing_generic_entry_update(&rec->ent, 0, 0); |
531 | rec->ent.type = sys_data->exit_id; | 596 | rec->ent.type = sys_data->exit_event->id; |
532 | rec->nr = syscall_nr; | 597 | rec->nr = syscall_nr; |
533 | rec->ret = syscall_get_return_value(current, regs); | 598 | rec->ret = syscall_get_return_value(current, regs); |
534 | 599 | ||
535 | perf_tp_event(sys_data->exit_id, 0, 1, rec, size); | 600 | perf_tp_event(sys_data->exit_event->id, 0, 1, rec, size); |
536 | 601 | ||
537 | end: | 602 | end: |
603 | perf_swevent_put_recursion_context(rctx); | ||
604 | end_recursion: | ||
538 | local_irq_restore(flags); | 605 | local_irq_restore(flags); |
539 | } | 606 | } |
540 | 607 | ||
541 | int reg_prof_syscall_exit(char *name) | 608 | int prof_sysexit_enable(struct ftrace_event_call *call) |
542 | { | 609 | { |
543 | int ret = 0; | 610 | int ret = 0; |
544 | int num; | 611 | int num; |
545 | 612 | ||
546 | num = syscall_name_to_nr(name); | 613 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
547 | if (num < 0 || num >= NR_syscalls) | ||
548 | return -ENOSYS; | ||
549 | 614 | ||
550 | mutex_lock(&syscall_trace_lock); | 615 | mutex_lock(&syscall_trace_lock); |
551 | if (!sys_prof_refcount_exit) | 616 | if (!sys_prof_refcount_exit) |
@@ -561,13 +626,11 @@ int reg_prof_syscall_exit(char *name) | |||
561 | return ret; | 626 | return ret; |
562 | } | 627 | } |
563 | 628 | ||
564 | void unreg_prof_syscall_exit(char *name) | 629 | void prof_sysexit_disable(struct ftrace_event_call *call) |
565 | { | 630 | { |
566 | int num; | 631 | int num; |
567 | 632 | ||
568 | num = syscall_name_to_nr(name); | 633 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
569 | if (num < 0 || num >= NR_syscalls) | ||
570 | return; | ||
571 | 634 | ||
572 | mutex_lock(&syscall_trace_lock); | 635 | mutex_lock(&syscall_trace_lock); |
573 | sys_prof_refcount_exit--; | 636 | sys_prof_refcount_exit--; |