diff options
-rw-r--r-- | include/linux/ftrace_event.h | 19 | ||||
-rw-r--r-- | include/linux/syscalls.h | 29 | ||||
-rw-r--r-- | include/trace/ftrace.h | 133 | ||||
-rw-r--r-- | kernel/trace/trace_event_perf.c | 15 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 32 | ||||
-rw-r--r-- | kernel/trace/trace_kprobe.c | 34 | ||||
-rw-r--r-- | kernel/trace/trace_syscalls.c | 56 |
7 files changed, 171 insertions, 147 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 496eea898ee4..e665ed38b4bf 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h | |||
@@ -113,8 +113,23 @@ void tracing_record_cmdline(struct task_struct *tsk); | |||
113 | 113 | ||
114 | struct event_filter; | 114 | struct event_filter; |
115 | 115 | ||
116 | enum trace_reg { | ||
117 | TRACE_REG_REGISTER, | ||
118 | TRACE_REG_UNREGISTER, | ||
119 | TRACE_REG_PERF_REGISTER, | ||
120 | TRACE_REG_PERF_UNREGISTER, | ||
121 | }; | ||
122 | |||
123 | struct ftrace_event_call; | ||
124 | |||
116 | struct ftrace_event_class { | 125 | struct ftrace_event_class { |
117 | char *system; | 126 | char *system; |
127 | void *probe; | ||
128 | #ifdef CONFIG_PERF_EVENTS | ||
129 | void *perf_probe; | ||
130 | #endif | ||
131 | int (*reg)(struct ftrace_event_call *event, | ||
132 | enum trace_reg type); | ||
118 | }; | 133 | }; |
119 | 134 | ||
120 | struct ftrace_event_call { | 135 | struct ftrace_event_call { |
@@ -124,8 +139,6 @@ struct ftrace_event_call { | |||
124 | struct dentry *dir; | 139 | struct dentry *dir; |
125 | struct trace_event *event; | 140 | struct trace_event *event; |
126 | int enabled; | 141 | int enabled; |
127 | int (*regfunc)(struct ftrace_event_call *); | ||
128 | void (*unregfunc)(struct ftrace_event_call *); | ||
129 | int id; | 142 | int id; |
130 | const char *print_fmt; | 143 | const char *print_fmt; |
131 | int (*raw_init)(struct ftrace_event_call *); | 144 | int (*raw_init)(struct ftrace_event_call *); |
@@ -137,8 +150,6 @@ struct ftrace_event_call { | |||
137 | void *data; | 150 | void *data; |
138 | 151 | ||
139 | int perf_refcount; | 152 | int perf_refcount; |
140 | int (*perf_event_enable)(struct ftrace_event_call *); | ||
141 | void (*perf_event_disable)(struct ftrace_event_call *); | ||
142 | }; | 153 | }; |
143 | 154 | ||
144 | #define PERF_MAX_TRACE_SIZE 2048 | 155 | #define PERF_MAX_TRACE_SIZE 2048 |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index ac5791df2506..e3348c4c22e8 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -103,22 +103,6 @@ struct perf_event_attr; | |||
103 | #define __SC_TEST5(t5, a5, ...) __SC_TEST(t5); __SC_TEST4(__VA_ARGS__) | 103 | #define __SC_TEST5(t5, a5, ...) __SC_TEST(t5); __SC_TEST4(__VA_ARGS__) |
104 | #define __SC_TEST6(t6, a6, ...) __SC_TEST(t6); __SC_TEST5(__VA_ARGS__) | 104 | #define __SC_TEST6(t6, a6, ...) __SC_TEST(t6); __SC_TEST5(__VA_ARGS__) |
105 | 105 | ||
106 | #ifdef CONFIG_PERF_EVENTS | ||
107 | |||
108 | #define TRACE_SYS_ENTER_PERF_INIT(sname) \ | ||
109 | .perf_event_enable = perf_sysenter_enable, \ | ||
110 | .perf_event_disable = perf_sysenter_disable, | ||
111 | |||
112 | #define TRACE_SYS_EXIT_PERF_INIT(sname) \ | ||
113 | .perf_event_enable = perf_sysexit_enable, \ | ||
114 | .perf_event_disable = perf_sysexit_disable, | ||
115 | #else | ||
116 | #define TRACE_SYS_ENTER_PERF(sname) | ||
117 | #define TRACE_SYS_ENTER_PERF_INIT(sname) | ||
118 | #define TRACE_SYS_EXIT_PERF(sname) | ||
119 | #define TRACE_SYS_EXIT_PERF_INIT(sname) | ||
120 | #endif /* CONFIG_PERF_EVENTS */ | ||
121 | |||
122 | #ifdef CONFIG_FTRACE_SYSCALLS | 106 | #ifdef CONFIG_FTRACE_SYSCALLS |
123 | #define __SC_STR_ADECL1(t, a) #a | 107 | #define __SC_STR_ADECL1(t, a) #a |
124 | #define __SC_STR_ADECL2(t, a, ...) #a, __SC_STR_ADECL1(__VA_ARGS__) | 108 | #define __SC_STR_ADECL2(t, a, ...) #a, __SC_STR_ADECL1(__VA_ARGS__) |
@@ -134,7 +118,8 @@ struct perf_event_attr; | |||
134 | #define __SC_STR_TDECL5(t, a, ...) #t, __SC_STR_TDECL4(__VA_ARGS__) | 118 | #define __SC_STR_TDECL5(t, a, ...) #t, __SC_STR_TDECL4(__VA_ARGS__) |
135 | #define __SC_STR_TDECL6(t, a, ...) #t, __SC_STR_TDECL5(__VA_ARGS__) | 119 | #define __SC_STR_TDECL6(t, a, ...) #t, __SC_STR_TDECL5(__VA_ARGS__) |
136 | 120 | ||
137 | extern struct ftrace_event_class event_class_syscalls; | 121 | extern struct ftrace_event_class event_class_syscall_enter; |
122 | extern struct ftrace_event_class event_class_syscall_exit; | ||
138 | 123 | ||
139 | #define SYSCALL_TRACE_ENTER_EVENT(sname) \ | 124 | #define SYSCALL_TRACE_ENTER_EVENT(sname) \ |
140 | static const struct syscall_metadata __syscall_meta_##sname; \ | 125 | static const struct syscall_metadata __syscall_meta_##sname; \ |
@@ -148,14 +133,11 @@ extern struct ftrace_event_class event_class_syscalls; | |||
148 | __attribute__((section("_ftrace_events"))) \ | 133 | __attribute__((section("_ftrace_events"))) \ |
149 | event_enter_##sname = { \ | 134 | event_enter_##sname = { \ |
150 | .name = "sys_enter"#sname, \ | 135 | .name = "sys_enter"#sname, \ |
151 | .class = &event_class_syscalls, \ | 136 | .class = &event_class_syscall_enter, \ |
152 | .event = &enter_syscall_print_##sname, \ | 137 | .event = &enter_syscall_print_##sname, \ |
153 | .raw_init = init_syscall_trace, \ | 138 | .raw_init = init_syscall_trace, \ |
154 | .define_fields = syscall_enter_define_fields, \ | 139 | .define_fields = syscall_enter_define_fields, \ |
155 | .regfunc = reg_event_syscall_enter, \ | ||
156 | .unregfunc = unreg_event_syscall_enter, \ | ||
157 | .data = (void *)&__syscall_meta_##sname,\ | 140 | .data = (void *)&__syscall_meta_##sname,\ |
158 | TRACE_SYS_ENTER_PERF_INIT(sname) \ | ||
159 | } | 141 | } |
160 | 142 | ||
161 | #define SYSCALL_TRACE_EXIT_EVENT(sname) \ | 143 | #define SYSCALL_TRACE_EXIT_EVENT(sname) \ |
@@ -170,14 +152,11 @@ extern struct ftrace_event_class event_class_syscalls; | |||
170 | __attribute__((section("_ftrace_events"))) \ | 152 | __attribute__((section("_ftrace_events"))) \ |
171 | event_exit_##sname = { \ | 153 | event_exit_##sname = { \ |
172 | .name = "sys_exit"#sname, \ | 154 | .name = "sys_exit"#sname, \ |
173 | .class = &event_class_syscalls, \ | 155 | .class = &event_class_syscall_exit, \ |
174 | .event = &exit_syscall_print_##sname, \ | 156 | .event = &exit_syscall_print_##sname, \ |
175 | .raw_init = init_syscall_trace, \ | 157 | .raw_init = init_syscall_trace, \ |
176 | .define_fields = syscall_exit_define_fields, \ | 158 | .define_fields = syscall_exit_define_fields, \ |
177 | .regfunc = reg_event_syscall_exit, \ | ||
178 | .unregfunc = unreg_event_syscall_exit, \ | ||
179 | .data = (void *)&__syscall_meta_##sname,\ | 159 | .data = (void *)&__syscall_meta_##sname,\ |
180 | TRACE_SYS_EXIT_PERF_INIT(sname) \ | ||
181 | } | 160 | } |
182 | 161 | ||
183 | #define SYSCALL_METADATA(sname, nb) \ | 162 | #define SYSCALL_METADATA(sname, nb) \ |
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index ba28b644f41b..26d132418f92 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
@@ -381,53 +381,6 @@ static inline notrace int ftrace_get_offsets_##call( \ | |||
381 | 381 | ||
382 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | 382 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) |
383 | 383 | ||
384 | #ifdef CONFIG_PERF_EVENTS | ||
385 | |||
386 | /* | ||
387 | * Generate the functions needed for tracepoint perf_event support. | ||
388 | * | ||
389 | * NOTE: The insertion profile callback (ftrace_profile_<call>) is defined later | ||
390 | * | ||
391 | * static int ftrace_profile_enable_<call>(void) | ||
392 | * { | ||
393 | * return register_trace_<call>(ftrace_profile_<call>); | ||
394 | * } | ||
395 | * | ||
396 | * static void ftrace_profile_disable_<call>(void) | ||
397 | * { | ||
398 | * unregister_trace_<call>(ftrace_profile_<call>); | ||
399 | * } | ||
400 | * | ||
401 | */ | ||
402 | |||
403 | #undef DECLARE_EVENT_CLASS | ||
404 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) | ||
405 | |||
406 | #undef DEFINE_EVENT | ||
407 | #define DEFINE_EVENT(template, name, proto, args) \ | ||
408 | \ | ||
409 | static void perf_trace_##name(void *, proto); \ | ||
410 | \ | ||
411 | static notrace int \ | ||
412 | perf_trace_enable_##name(struct ftrace_event_call *unused) \ | ||
413 | { \ | ||
414 | return register_trace_##name(perf_trace_##name, NULL); \ | ||
415 | } \ | ||
416 | \ | ||
417 | static notrace void \ | ||
418 | perf_trace_disable_##name(struct ftrace_event_call *unused) \ | ||
419 | { \ | ||
420 | unregister_trace_##name(perf_trace_##name, NULL); \ | ||
421 | } | ||
422 | |||
423 | #undef DEFINE_EVENT_PRINT | ||
424 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ | ||
425 | DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args)) | ||
426 | |||
427 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | ||
428 | |||
429 | #endif /* CONFIG_PERF_EVENTS */ | ||
430 | |||
431 | /* | 384 | /* |
432 | * Stage 4 of the trace events. | 385 | * Stage 4 of the trace events. |
433 | * | 386 | * |
@@ -437,8 +390,9 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ | |||
437 | * | 390 | * |
438 | * static struct ftrace_event_call event_<call>; | 391 | * static struct ftrace_event_call event_<call>; |
439 | * | 392 | * |
440 | * static void ftrace_raw_event_<call>(proto) | 393 | * static void ftrace_raw_event_<call>(void *__data, proto) |
441 | * { | 394 | * { |
395 | * struct ftrace_event_call *event_call = __data; | ||
442 | * struct ftrace_data_offsets_<call> __maybe_unused __data_offsets; | 396 | * struct ftrace_data_offsets_<call> __maybe_unused __data_offsets; |
443 | * struct ring_buffer_event *event; | 397 | * struct ring_buffer_event *event; |
444 | * struct ftrace_raw_<call> *entry; <-- defined in stage 1 | 398 | * struct ftrace_raw_<call> *entry; <-- defined in stage 1 |
@@ -468,16 +422,6 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ | |||
468 | * event, irq_flags, pc); | 422 | * event, irq_flags, pc); |
469 | * } | 423 | * } |
470 | * | 424 | * |
471 | * static int ftrace_raw_reg_event_<call>(struct ftrace_event_call *unused) | ||
472 | * { | ||
473 | * return register_trace_<call>(ftrace_raw_event_<call>); | ||
474 | * } | ||
475 | * | ||
476 | * static void ftrace_unreg_event_<call>(struct ftrace_event_call *unused) | ||
477 | * { | ||
478 | * unregister_trace_<call>(ftrace_raw_event_<call>); | ||
479 | * } | ||
480 | * | ||
481 | * static struct trace_event ftrace_event_type_<call> = { | 425 | * static struct trace_event ftrace_event_type_<call> = { |
482 | * .trace = ftrace_raw_output_<call>, <-- stage 2 | 426 | * .trace = ftrace_raw_output_<call>, <-- stage 2 |
483 | * }; | 427 | * }; |
@@ -504,11 +448,15 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ | |||
504 | 448 | ||
505 | #ifdef CONFIG_PERF_EVENTS | 449 | #ifdef CONFIG_PERF_EVENTS |
506 | 450 | ||
451 | #define _TRACE_PERF_PROTO(call, proto) \ | ||
452 | static notrace void \ | ||
453 | perf_trace_##call(void *__data, proto); | ||
454 | |||
507 | #define _TRACE_PERF_INIT(call) \ | 455 | #define _TRACE_PERF_INIT(call) \ |
508 | .perf_event_enable = perf_trace_enable_##call, \ | 456 | .perf_probe = perf_trace_##call, |
509 | .perf_event_disable = perf_trace_disable_##call, | ||
510 | 457 | ||
511 | #else | 458 | #else |
459 | #define _TRACE_PERF_PROTO(call, proto) | ||
512 | #define _TRACE_PERF_INIT(call) | 460 | #define _TRACE_PERF_INIT(call) |
513 | #endif /* CONFIG_PERF_EVENTS */ | 461 | #endif /* CONFIG_PERF_EVENTS */ |
514 | 462 | ||
@@ -542,9 +490,9 @@ perf_trace_disable_##name(struct ftrace_event_call *unused) \ | |||
542 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ | 490 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ |
543 | \ | 491 | \ |
544 | static notrace void \ | 492 | static notrace void \ |
545 | ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \ | 493 | ftrace_raw_event_##call(void *__data, proto) \ |
546 | proto) \ | ||
547 | { \ | 494 | { \ |
495 | struct ftrace_event_call *event_call = __data; \ | ||
548 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ | 496 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ |
549 | struct ring_buffer_event *event; \ | 497 | struct ring_buffer_event *event; \ |
550 | struct ftrace_raw_##call *entry; \ | 498 | struct ftrace_raw_##call *entry; \ |
@@ -574,30 +522,23 @@ ftrace_raw_event_id_##call(struct ftrace_event_call *event_call, \ | |||
574 | trace_nowake_buffer_unlock_commit(buffer, \ | 522 | trace_nowake_buffer_unlock_commit(buffer, \ |
575 | event, irq_flags, pc); \ | 523 | event, irq_flags, pc); \ |
576 | } | 524 | } |
525 | /* | ||
526 | * The ftrace_test_probe is compiled out, it is only here as a build time check | ||
527 | * to make sure that if the tracepoint handling changes, the ftrace probe will | ||
528 | * fail to compile unless it too is updated. | ||
529 | */ | ||
577 | 530 | ||
578 | #undef DEFINE_EVENT | 531 | #undef DEFINE_EVENT |
579 | #define DEFINE_EVENT(template, call, proto, args) \ | 532 | #define DEFINE_EVENT(template, call, proto, args) \ |
580 | \ | 533 | \ |
581 | static notrace void ftrace_raw_event_##call(void *__ignore, proto) \ | ||
582 | { \ | ||
583 | ftrace_raw_event_id_##template(&event_##call, args); \ | ||
584 | } \ | ||
585 | \ | ||
586 | static notrace int \ | ||
587 | ftrace_raw_reg_event_##call(struct ftrace_event_call *unused) \ | ||
588 | { \ | ||
589 | return register_trace_##call(ftrace_raw_event_##call, NULL); \ | ||
590 | } \ | ||
591 | \ | ||
592 | static notrace void \ | ||
593 | ftrace_raw_unreg_event_##call(struct ftrace_event_call *unused) \ | ||
594 | { \ | ||
595 | unregister_trace_##call(ftrace_raw_event_##call, NULL); \ | ||
596 | } \ | ||
597 | \ | ||
598 | static struct trace_event ftrace_event_type_##call = { \ | 534 | static struct trace_event ftrace_event_type_##call = { \ |
599 | .trace = ftrace_raw_output_##call, \ | 535 | .trace = ftrace_raw_output_##call, \ |
600 | }; | 536 | }; \ |
537 | \ | ||
538 | static inline void ftrace_test_probe_##call(void) \ | ||
539 | { \ | ||
540 | check_trace_callback_type_##call(ftrace_raw_event_##template); \ | ||
541 | } | ||
601 | 542 | ||
602 | #undef DEFINE_EVENT_PRINT | 543 | #undef DEFINE_EVENT_PRINT |
603 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ | 544 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ |
@@ -618,9 +559,12 @@ static struct trace_event ftrace_event_type_##call = { \ | |||
618 | 559 | ||
619 | #undef DECLARE_EVENT_CLASS | 560 | #undef DECLARE_EVENT_CLASS |
620 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ | 561 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ |
562 | _TRACE_PERF_PROTO(call, PARAMS(proto)); \ | ||
621 | static const char print_fmt_##call[] = print; \ | 563 | static const char print_fmt_##call[] = print; \ |
622 | static struct ftrace_event_class __used event_class_##call = { \ | 564 | static struct ftrace_event_class __used event_class_##call = { \ |
623 | .system = __stringify(TRACE_SYSTEM) \ | 565 | .system = __stringify(TRACE_SYSTEM), \ |
566 | .probe = ftrace_raw_event_##call, \ | ||
567 | _TRACE_PERF_INIT(call) \ | ||
624 | }; | 568 | }; |
625 | 569 | ||
626 | #undef DEFINE_EVENT | 570 | #undef DEFINE_EVENT |
@@ -633,11 +577,8 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
633 | .class = &event_class_##template, \ | 577 | .class = &event_class_##template, \ |
634 | .event = &ftrace_event_type_##call, \ | 578 | .event = &ftrace_event_type_##call, \ |
635 | .raw_init = trace_event_raw_init, \ | 579 | .raw_init = trace_event_raw_init, \ |
636 | .regfunc = ftrace_raw_reg_event_##call, \ | ||
637 | .unregfunc = ftrace_raw_unreg_event_##call, \ | ||
638 | .print_fmt = print_fmt_##template, \ | 580 | .print_fmt = print_fmt_##template, \ |
639 | .define_fields = ftrace_define_fields_##template, \ | 581 | .define_fields = ftrace_define_fields_##template, \ |
640 | _TRACE_PERF_INIT(call) \ | ||
641 | }; | 582 | }; |
642 | 583 | ||
643 | #undef DEFINE_EVENT_PRINT | 584 | #undef DEFINE_EVENT_PRINT |
@@ -652,11 +593,8 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
652 | .class = &event_class_##template, \ | 593 | .class = &event_class_##template, \ |
653 | .event = &ftrace_event_type_##call, \ | 594 | .event = &ftrace_event_type_##call, \ |
654 | .raw_init = trace_event_raw_init, \ | 595 | .raw_init = trace_event_raw_init, \ |
655 | .regfunc = ftrace_raw_reg_event_##call, \ | ||
656 | .unregfunc = ftrace_raw_unreg_event_##call, \ | ||
657 | .print_fmt = print_fmt_##call, \ | 596 | .print_fmt = print_fmt_##call, \ |
658 | .define_fields = ftrace_define_fields_##template, \ | 597 | .define_fields = ftrace_define_fields_##template, \ |
659 | _TRACE_PERF_INIT(call) \ | ||
660 | } | 598 | } |
661 | 599 | ||
662 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | 600 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) |
@@ -756,9 +694,9 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
756 | #undef DECLARE_EVENT_CLASS | 694 | #undef DECLARE_EVENT_CLASS |
757 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ | 695 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ |
758 | static notrace void \ | 696 | static notrace void \ |
759 | perf_trace_templ_##call(struct ftrace_event_call *event_call, \ | 697 | perf_trace_##call(void *__data, proto) \ |
760 | proto) \ | ||
761 | { \ | 698 | { \ |
699 | struct ftrace_event_call *event_call = __data; \ | ||
762 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ | 700 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ |
763 | struct ftrace_raw_##call *entry; \ | 701 | struct ftrace_raw_##call *entry; \ |
764 | u64 __addr = 0, __count = 1; \ | 702 | u64 __addr = 0, __count = 1; \ |
@@ -791,15 +729,20 @@ perf_trace_templ_##call(struct ftrace_event_call *event_call, \ | |||
791 | __count, irq_flags, __regs); \ | 729 | __count, irq_flags, __regs); \ |
792 | } | 730 | } |
793 | 731 | ||
732 | /* | ||
733 | * This part is compiled out, it is only here as a build time check | ||
734 | * to make sure that if the tracepoint handling changes, the | ||
735 | * perf probe will fail to compile unless it too is updated. | ||
736 | */ | ||
794 | #undef DEFINE_EVENT | 737 | #undef DEFINE_EVENT |
795 | #define DEFINE_EVENT(template, call, proto, args) \ | 738 | #define DEFINE_EVENT(template, call, proto, args) \ |
796 | static notrace void perf_trace_##call(void *__ignore, proto) \ | 739 | static inline void perf_test_probe_##call(void) \ |
797 | { \ | 740 | { \ |
798 | struct ftrace_event_call *event_call = &event_##call; \ | 741 | check_trace_callback_type_##call(perf_trace_##template); \ |
799 | \ | 742 | \ |
800 | perf_trace_templ_##template(event_call, args); \ | ||
801 | } | 743 | } |
802 | 744 | ||
745 | |||
803 | #undef DEFINE_EVENT_PRINT | 746 | #undef DEFINE_EVENT_PRINT |
804 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ | 747 | #define DEFINE_EVENT_PRINT(template, name, proto, args, print) \ |
805 | DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args)) | 748 | DEFINE_EVENT(template, name, PARAMS(proto), PARAMS(args)) |
diff --git a/kernel/trace/trace_event_perf.c b/kernel/trace/trace_event_perf.c index 0565bb42566f..196fe9d26773 100644 --- a/kernel/trace/trace_event_perf.c +++ b/kernel/trace/trace_event_perf.c | |||
@@ -49,7 +49,12 @@ static int perf_trace_event_enable(struct ftrace_event_call *event) | |||
49 | rcu_assign_pointer(perf_trace_buf_nmi, buf); | 49 | rcu_assign_pointer(perf_trace_buf_nmi, buf); |
50 | } | 50 | } |
51 | 51 | ||
52 | ret = event->perf_event_enable(event); | 52 | if (event->class->reg) |
53 | ret = event->class->reg(event, TRACE_REG_PERF_REGISTER); | ||
54 | else | ||
55 | ret = tracepoint_probe_register(event->name, | ||
56 | event->class->perf_probe, | ||
57 | event); | ||
53 | if (!ret) { | 58 | if (!ret) { |
54 | total_ref_count++; | 59 | total_ref_count++; |
55 | return 0; | 60 | return 0; |
@@ -75,7 +80,8 @@ int perf_trace_enable(int event_id) | |||
75 | 80 | ||
76 | mutex_lock(&event_mutex); | 81 | mutex_lock(&event_mutex); |
77 | list_for_each_entry(event, &ftrace_events, list) { | 82 | list_for_each_entry(event, &ftrace_events, list) { |
78 | if (event->id == event_id && event->perf_event_enable && | 83 | if (event->id == event_id && |
84 | event->class && event->class->perf_probe && | ||
79 | try_module_get(event->mod)) { | 85 | try_module_get(event->mod)) { |
80 | ret = perf_trace_event_enable(event); | 86 | ret = perf_trace_event_enable(event); |
81 | break; | 87 | break; |
@@ -93,7 +99,10 @@ static void perf_trace_event_disable(struct ftrace_event_call *event) | |||
93 | if (--event->perf_refcount > 0) | 99 | if (--event->perf_refcount > 0) |
94 | return; | 100 | return; |
95 | 101 | ||
96 | event->perf_event_disable(event); | 102 | if (event->class->reg) |
103 | event->class->reg(event, TRACE_REG_PERF_UNREGISTER); | ||
104 | else | ||
105 | tracepoint_probe_unregister(event->name, event->class->perf_probe, event); | ||
97 | 106 | ||
98 | if (!--total_ref_count) { | 107 | if (!--total_ref_count) { |
99 | buf = perf_trace_buf; | 108 | buf = perf_trace_buf; |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 2f54b48d3632..19d1eb0a7188 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -127,13 +127,23 @@ static int ftrace_event_enable_disable(struct ftrace_event_call *call, | |||
127 | if (call->enabled) { | 127 | if (call->enabled) { |
128 | call->enabled = 0; | 128 | call->enabled = 0; |
129 | tracing_stop_cmdline_record(); | 129 | tracing_stop_cmdline_record(); |
130 | call->unregfunc(call); | 130 | if (call->class->reg) |
131 | call->class->reg(call, TRACE_REG_UNREGISTER); | ||
132 | else | ||
133 | tracepoint_probe_unregister(call->name, | ||
134 | call->class->probe, | ||
135 | call); | ||
131 | } | 136 | } |
132 | break; | 137 | break; |
133 | case 1: | 138 | case 1: |
134 | if (!call->enabled) { | 139 | if (!call->enabled) { |
135 | tracing_start_cmdline_record(); | 140 | tracing_start_cmdline_record(); |
136 | ret = call->regfunc(call); | 141 | if (call->class->reg) |
142 | ret = call->class->reg(call, TRACE_REG_REGISTER); | ||
143 | else | ||
144 | ret = tracepoint_probe_register(call->name, | ||
145 | call->class->probe, | ||
146 | call); | ||
137 | if (ret) { | 147 | if (ret) { |
138 | tracing_stop_cmdline_record(); | 148 | tracing_stop_cmdline_record(); |
139 | pr_info("event trace: Could not enable event " | 149 | pr_info("event trace: Could not enable event " |
@@ -171,7 +181,8 @@ static int __ftrace_set_clr_event(const char *match, const char *sub, | |||
171 | mutex_lock(&event_mutex); | 181 | mutex_lock(&event_mutex); |
172 | list_for_each_entry(call, &ftrace_events, list) { | 182 | list_for_each_entry(call, &ftrace_events, list) { |
173 | 183 | ||
174 | if (!call->name || !call->regfunc) | 184 | if (!call->name || !call->class || |
185 | (!call->class->probe && !call->class->reg)) | ||
175 | continue; | 186 | continue; |
176 | 187 | ||
177 | if (match && | 188 | if (match && |
@@ -297,7 +308,7 @@ t_next(struct seq_file *m, void *v, loff_t *pos) | |||
297 | * The ftrace subsystem is for showing formats only. | 308 | * The ftrace subsystem is for showing formats only. |
298 | * They can not be enabled or disabled via the event files. | 309 | * They can not be enabled or disabled via the event files. |
299 | */ | 310 | */ |
300 | if (call->regfunc) | 311 | if (call->class && (call->class->probe || call->class->reg)) |
301 | return call; | 312 | return call; |
302 | } | 313 | } |
303 | 314 | ||
@@ -450,7 +461,8 @@ system_enable_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
450 | 461 | ||
451 | mutex_lock(&event_mutex); | 462 | mutex_lock(&event_mutex); |
452 | list_for_each_entry(call, &ftrace_events, list) { | 463 | list_for_each_entry(call, &ftrace_events, list) { |
453 | if (!call->name || !call->regfunc) | 464 | if (!call->name || !call->class || |
465 | (!call->class->probe && !call->class->reg)) | ||
454 | continue; | 466 | continue; |
455 | 467 | ||
456 | if (system && strcmp(call->class->system, system) != 0) | 468 | if (system && strcmp(call->class->system, system) != 0) |
@@ -935,13 +947,15 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, | |||
935 | return -1; | 947 | return -1; |
936 | } | 948 | } |
937 | 949 | ||
938 | if (call->regfunc) | 950 | if (call->class->probe || call->class->reg) |
939 | trace_create_file("enable", 0644, call->dir, call, | 951 | trace_create_file("enable", 0644, call->dir, call, |
940 | enable); | 952 | enable); |
941 | 953 | ||
942 | if (call->id && call->perf_event_enable) | 954 | #ifdef CONFIG_PERF_EVENTS |
955 | if (call->id && (call->class->perf_probe || call->class->reg)) | ||
943 | trace_create_file("id", 0444, call->dir, call, | 956 | trace_create_file("id", 0444, call->dir, call, |
944 | id); | 957 | id); |
958 | #endif | ||
945 | 959 | ||
946 | if (call->define_fields) { | 960 | if (call->define_fields) { |
947 | ret = trace_define_common_fields(call); | 961 | ret = trace_define_common_fields(call); |
@@ -1388,8 +1402,8 @@ static __init void event_trace_self_tests(void) | |||
1388 | 1402 | ||
1389 | list_for_each_entry(call, &ftrace_events, list) { | 1403 | list_for_each_entry(call, &ftrace_events, list) { |
1390 | 1404 | ||
1391 | /* Only test those that have a regfunc */ | 1405 | /* Only test those that have a probe */ |
1392 | if (!call->regfunc) | 1406 | if (!call->class || !call->class->probe) |
1393 | continue; | 1407 | continue; |
1394 | 1408 | ||
1395 | /* | 1409 | /* |
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index eda220bf2065..f8af21a53f0c 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -202,6 +202,7 @@ struct trace_probe { | |||
202 | unsigned long nhit; | 202 | unsigned long nhit; |
203 | unsigned int flags; /* For TP_FLAG_* */ | 203 | unsigned int flags; /* For TP_FLAG_* */ |
204 | const char *symbol; /* symbol name */ | 204 | const char *symbol; /* symbol name */ |
205 | struct ftrace_event_class class; | ||
205 | struct ftrace_event_call call; | 206 | struct ftrace_event_call call; |
206 | struct trace_event event; | 207 | struct trace_event event; |
207 | unsigned int nr_args; | 208 | unsigned int nr_args; |
@@ -323,6 +324,7 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
323 | goto error; | 324 | goto error; |
324 | } | 325 | } |
325 | 326 | ||
327 | tp->call.class = &tp->class; | ||
326 | tp->call.name = kstrdup(event, GFP_KERNEL); | 328 | tp->call.name = kstrdup(event, GFP_KERNEL); |
327 | if (!tp->call.name) | 329 | if (!tp->call.name) |
328 | goto error; | 330 | goto error; |
@@ -332,8 +334,8 @@ static struct trace_probe *alloc_trace_probe(const char *group, | |||
332 | goto error; | 334 | goto error; |
333 | } | 335 | } |
334 | 336 | ||
335 | tp->call.class->system = kstrdup(group, GFP_KERNEL); | 337 | tp->class.system = kstrdup(group, GFP_KERNEL); |
336 | if (!tp->call.class->system) | 338 | if (!tp->class.system) |
337 | goto error; | 339 | goto error; |
338 | 340 | ||
339 | INIT_LIST_HEAD(&tp->list); | 341 | INIT_LIST_HEAD(&tp->list); |
@@ -1302,6 +1304,26 @@ static void probe_perf_disable(struct ftrace_event_call *call) | |||
1302 | } | 1304 | } |
1303 | #endif /* CONFIG_PERF_EVENTS */ | 1305 | #endif /* CONFIG_PERF_EVENTS */ |
1304 | 1306 | ||
1307 | static __kprobes | ||
1308 | int kprobe_register(struct ftrace_event_call *event, enum trace_reg type) | ||
1309 | { | ||
1310 | switch (type) { | ||
1311 | case TRACE_REG_REGISTER: | ||
1312 | return probe_event_enable(event); | ||
1313 | case TRACE_REG_UNREGISTER: | ||
1314 | probe_event_disable(event); | ||
1315 | return 0; | ||
1316 | |||
1317 | #ifdef CONFIG_PERF_EVENTS | ||
1318 | case TRACE_REG_PERF_REGISTER: | ||
1319 | return probe_perf_enable(event); | ||
1320 | case TRACE_REG_PERF_UNREGISTER: | ||
1321 | probe_perf_disable(event); | ||
1322 | return 0; | ||
1323 | #endif | ||
1324 | } | ||
1325 | return 0; | ||
1326 | } | ||
1305 | 1327 | ||
1306 | static __kprobes | 1328 | static __kprobes |
1307 | int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) | 1329 | int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) |
@@ -1355,13 +1377,7 @@ static int register_probe_event(struct trace_probe *tp) | |||
1355 | return -ENODEV; | 1377 | return -ENODEV; |
1356 | } | 1378 | } |
1357 | call->enabled = 0; | 1379 | call->enabled = 0; |
1358 | call->regfunc = probe_event_enable; | 1380 | call->class->reg = kprobe_register; |
1359 | call->unregfunc = probe_event_disable; | ||
1360 | |||
1361 | #ifdef CONFIG_PERF_EVENTS | ||
1362 | call->perf_event_enable = probe_perf_enable; | ||
1363 | call->perf_event_disable = probe_perf_disable; | ||
1364 | #endif | ||
1365 | call->data = tp; | 1381 | call->data = tp; |
1366 | ret = trace_add_event_call(call); | 1382 | ret = trace_add_event_call(call); |
1367 | if (ret) { | 1383 | if (ret) { |
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index b8d30e7ecd05..a21d366cae46 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -15,8 +15,19 @@ static int sys_refcount_exit; | |||
15 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); | 15 | static DECLARE_BITMAP(enabled_enter_syscalls, NR_syscalls); |
16 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); | 16 | static DECLARE_BITMAP(enabled_exit_syscalls, NR_syscalls); |
17 | 17 | ||
18 | struct ftrace_event_class event_class_syscalls = { | 18 | static int syscall_enter_register(struct ftrace_event_call *event, |
19 | .system = "syscalls" | 19 | enum trace_reg type); |
20 | static int syscall_exit_register(struct ftrace_event_call *event, | ||
21 | enum trace_reg type); | ||
22 | |||
23 | struct ftrace_event_class event_class_syscall_enter = { | ||
24 | .system = "syscalls", | ||
25 | .reg = syscall_enter_register | ||
26 | }; | ||
27 | |||
28 | struct ftrace_event_class event_class_syscall_exit = { | ||
29 | .system = "syscalls", | ||
30 | .reg = syscall_exit_register | ||
20 | }; | 31 | }; |
21 | 32 | ||
22 | extern unsigned long __start_syscalls_metadata[]; | 33 | extern unsigned long __start_syscalls_metadata[]; |
@@ -587,3 +598,44 @@ void perf_sysexit_disable(struct ftrace_event_call *call) | |||
587 | 598 | ||
588 | #endif /* CONFIG_PERF_EVENTS */ | 599 | #endif /* CONFIG_PERF_EVENTS */ |
589 | 600 | ||
601 | static int syscall_enter_register(struct ftrace_event_call *event, | ||
602 | enum trace_reg type) | ||
603 | { | ||
604 | switch (type) { | ||
605 | case TRACE_REG_REGISTER: | ||
606 | return reg_event_syscall_enter(event); | ||
607 | case TRACE_REG_UNREGISTER: | ||
608 | unreg_event_syscall_enter(event); | ||
609 | return 0; | ||
610 | |||
611 | #ifdef CONFIG_PERF_EVENTS | ||
612 | case TRACE_REG_PERF_REGISTER: | ||
613 | return perf_sysenter_enable(event); | ||
614 | case TRACE_REG_PERF_UNREGISTER: | ||
615 | perf_sysenter_disable(event); | ||
616 | return 0; | ||
617 | #endif | ||
618 | } | ||
619 | return 0; | ||
620 | } | ||
621 | |||
622 | static int syscall_exit_register(struct ftrace_event_call *event, | ||
623 | enum trace_reg type) | ||
624 | { | ||
625 | switch (type) { | ||
626 | case TRACE_REG_REGISTER: | ||
627 | return reg_event_syscall_exit(event); | ||
628 | case TRACE_REG_UNREGISTER: | ||
629 | unreg_event_syscall_exit(event); | ||
630 | return 0; | ||
631 | |||
632 | #ifdef CONFIG_PERF_EVENTS | ||
633 | case TRACE_REG_PERF_REGISTER: | ||
634 | return perf_sysexit_enable(event); | ||
635 | case TRACE_REG_PERF_UNREGISTER: | ||
636 | perf_sysexit_disable(event); | ||
637 | return 0; | ||
638 | #endif | ||
639 | } | ||
640 | return 0; | ||
641 | } | ||