diff options
author | Ingo Molnar <mingo@elte.hu> | 2010-03-12 04:20:57 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2010-03-12 04:20:59 -0500 |
commit | 937779db13fb6cb621e28d9ae0a6cf1d05b57d05 (patch) | |
tree | 6c27402677c347c4dc01980de78c270630588847 | |
parent | 6230f2c7ef01a69e2ba9370326572c287209d32a (diff) | |
parent | 9f591fd76afdc0e5192e9ed00a36f8efc0b4dfe6 (diff) |
Merge branch 'perf/urgent' into perf/core
Merge reason: We want to queue up a dependent patch.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
35 files changed, 522 insertions, 219 deletions
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c index fbe101d7505d..08460a2e9f41 100644 --- a/arch/powerpc/kernel/perf_event.c +++ b/arch/powerpc/kernel/perf_event.c | |||
@@ -1298,7 +1298,7 @@ static void power_pmu_setup(int cpu) | |||
1298 | } | 1298 | } |
1299 | 1299 | ||
1300 | static int __cpuinit | 1300 | static int __cpuinit |
1301 | power_pmu_notify(struct notifier_block *self, unsigned long action, void *hcpu) | 1301 | power_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu) |
1302 | { | 1302 | { |
1303 | unsigned int cpu = (long)hcpu; | 1303 | unsigned int cpu = (long)hcpu; |
1304 | 1304 | ||
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c index e24f6374f9f5..a6d92c34135c 100644 --- a/arch/x86/kernel/cpu/perf_event.c +++ b/arch/x86/kernel/cpu/perf_event.c | |||
@@ -787,7 +787,6 @@ void hw_perf_enable(void) | |||
787 | * step2: reprogram moved events into new counters | 787 | * step2: reprogram moved events into new counters |
788 | */ | 788 | */ |
789 | for (i = 0; i < n_running; i++) { | 789 | for (i = 0; i < n_running; i++) { |
790 | |||
791 | event = cpuc->event_list[i]; | 790 | event = cpuc->event_list[i]; |
792 | hwc = &event->hw; | 791 | hwc = &event->hw; |
793 | 792 | ||
@@ -802,21 +801,16 @@ void hw_perf_enable(void) | |||
802 | continue; | 801 | continue; |
803 | 802 | ||
804 | x86_pmu_stop(event); | 803 | x86_pmu_stop(event); |
805 | |||
806 | hwc->idx = -1; | ||
807 | } | 804 | } |
808 | 805 | ||
809 | for (i = 0; i < cpuc->n_events; i++) { | 806 | for (i = 0; i < cpuc->n_events; i++) { |
810 | |||
811 | event = cpuc->event_list[i]; | 807 | event = cpuc->event_list[i]; |
812 | hwc = &event->hw; | 808 | hwc = &event->hw; |
813 | 809 | ||
814 | if (i < n_running && | 810 | if (!match_prev_assignment(hwc, cpuc, i)) |
815 | match_prev_assignment(hwc, cpuc, i)) | ||
816 | continue; | ||
817 | |||
818 | if (hwc->idx == -1) | ||
819 | x86_assign_hw_event(event, cpuc, i); | 811 | x86_assign_hw_event(event, cpuc, i); |
812 | else if (i < n_running) | ||
813 | continue; | ||
820 | 814 | ||
821 | x86_pmu_start(event); | 815 | x86_pmu_start(event); |
822 | } | 816 | } |
@@ -1685,3 +1679,16 @@ struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
1685 | 1679 | ||
1686 | return entry; | 1680 | return entry; |
1687 | } | 1681 | } |
1682 | |||
1683 | void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) | ||
1684 | { | ||
1685 | regs->ip = ip; | ||
1686 | /* | ||
1687 | * perf_arch_fetch_caller_regs adds another call, we need to increment | ||
1688 | * the skip level | ||
1689 | */ | ||
1690 | regs->bp = rewind_frame_pointer(skip + 1); | ||
1691 | regs->cs = __KERNEL_CS; | ||
1692 | local_save_flags(regs->flags); | ||
1693 | } | ||
1694 | EXPORT_SYMBOL_GPL(perf_arch_fetch_caller_regs); | ||
diff --git a/arch/x86/kernel/dumpstack.h b/arch/x86/kernel/dumpstack.h index 4fd1420faffa..29e5f7c845b2 100644 --- a/arch/x86/kernel/dumpstack.h +++ b/arch/x86/kernel/dumpstack.h | |||
@@ -29,4 +29,19 @@ struct stack_frame { | |||
29 | struct stack_frame *next_frame; | 29 | struct stack_frame *next_frame; |
30 | unsigned long return_address; | 30 | unsigned long return_address; |
31 | }; | 31 | }; |
32 | |||
33 | static inline unsigned long rewind_frame_pointer(int n) | ||
34 | { | ||
35 | struct stack_frame *frame; | ||
36 | |||
37 | get_bp(frame); | ||
38 | |||
39 | #ifdef CONFIG_FRAME_POINTER | ||
40 | while (n--) | ||
41 | frame = frame->next_frame; | ||
32 | #endif | 42 | #endif |
43 | |||
44 | return (unsigned long)frame; | ||
45 | } | ||
46 | |||
47 | #endif /* DUMPSTACK_H */ | ||
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c index d5e2a2ebb627..272c9f1f05f3 100644 --- a/arch/x86/kernel/dumpstack_64.c +++ b/arch/x86/kernel/dumpstack_64.c | |||
@@ -208,7 +208,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
208 | if (in_irq_stack(stack, irq_stack, irq_stack_end)) { | 208 | if (in_irq_stack(stack, irq_stack, irq_stack_end)) { |
209 | if (ops->stack(data, "IRQ") < 0) | 209 | if (ops->stack(data, "IRQ") < 0) |
210 | break; | 210 | break; |
211 | bp = print_context_stack(tinfo, stack, bp, | 211 | bp = ops->walk_stack(tinfo, stack, bp, |
212 | ops, data, irq_stack_end, &graph); | 212 | ops, data, irq_stack_end, &graph); |
213 | /* | 213 | /* |
214 | * We link to the next stack (which would be | 214 | * We link to the next stack (which would be |
@@ -229,7 +229,7 @@ void dump_trace(struct task_struct *task, struct pt_regs *regs, | |||
229 | /* | 229 | /* |
230 | * This handles the process stack: | 230 | * This handles the process stack: |
231 | */ | 231 | */ |
232 | bp = print_context_stack(tinfo, stack, bp, ops, data, NULL, &graph); | 232 | bp = ops->walk_stack(tinfo, stack, bp, ops, data, NULL, &graph); |
233 | put_cpu(); | 233 | put_cpu(); |
234 | } | 234 | } |
235 | EXPORT_SYMBOL(dump_trace); | 235 | EXPORT_SYMBOL(dump_trace); |
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h index 6b7c444ab8f6..c0f4b364c711 100644 --- a/include/linux/ftrace_event.h +++ b/include/linux/ftrace_event.h | |||
@@ -131,12 +131,12 @@ struct ftrace_event_call { | |||
131 | void *mod; | 131 | void *mod; |
132 | void *data; | 132 | void *data; |
133 | 133 | ||
134 | int profile_count; | 134 | int perf_refcount; |
135 | int (*profile_enable)(struct ftrace_event_call *); | 135 | int (*perf_event_enable)(struct ftrace_event_call *); |
136 | void (*profile_disable)(struct ftrace_event_call *); | 136 | void (*perf_event_disable)(struct ftrace_event_call *); |
137 | }; | 137 | }; |
138 | 138 | ||
139 | #define FTRACE_MAX_PROFILE_SIZE 2048 | 139 | #define PERF_MAX_TRACE_SIZE 2048 |
140 | 140 | ||
141 | #define MAX_FILTER_PRED 32 | 141 | #define MAX_FILTER_PRED 32 |
142 | #define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ | 142 | #define MAX_FILTER_STR_VAL 256 /* Should handle KSYM_SYMBOL_LEN */ |
@@ -187,22 +187,25 @@ do { \ | |||
187 | 187 | ||
188 | #ifdef CONFIG_PERF_EVENTS | 188 | #ifdef CONFIG_PERF_EVENTS |
189 | struct perf_event; | 189 | struct perf_event; |
190 | extern int ftrace_profile_enable(int event_id); | 190 | |
191 | extern void ftrace_profile_disable(int event_id); | 191 | DECLARE_PER_CPU(struct pt_regs, perf_trace_regs); |
192 | |||
193 | extern int perf_trace_enable(int event_id); | ||
194 | extern void perf_trace_disable(int event_id); | ||
192 | extern int ftrace_profile_set_filter(struct perf_event *event, int event_id, | 195 | extern int ftrace_profile_set_filter(struct perf_event *event, int event_id, |
193 | char *filter_str); | 196 | char *filter_str); |
194 | extern void ftrace_profile_free_filter(struct perf_event *event); | 197 | extern void ftrace_profile_free_filter(struct perf_event *event); |
195 | extern void * | 198 | extern void * |
196 | ftrace_perf_buf_prepare(int size, unsigned short type, int *rctxp, | 199 | perf_trace_buf_prepare(int size, unsigned short type, int *rctxp, |
197 | unsigned long *irq_flags); | 200 | unsigned long *irq_flags); |
198 | 201 | ||
199 | static inline void | 202 | static inline void |
200 | ftrace_perf_buf_submit(void *raw_data, int size, int rctx, u64 addr, | 203 | perf_trace_buf_submit(void *raw_data, int size, int rctx, u64 addr, |
201 | u64 count, unsigned long irq_flags) | 204 | u64 count, unsigned long irq_flags, struct pt_regs *regs) |
202 | { | 205 | { |
203 | struct trace_entry *entry = raw_data; | 206 | struct trace_entry *entry = raw_data; |
204 | 207 | ||
205 | perf_tp_event(entry->type, addr, count, raw_data, size); | 208 | perf_tp_event(entry->type, addr, count, raw_data, size, regs); |
206 | perf_swevent_put_recursion_context(rctx); | 209 | perf_swevent_put_recursion_context(rctx); |
207 | local_irq_restore(irq_flags); | 210 | local_irq_restore(irq_flags); |
208 | } | 211 | } |
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index be85f7c4a94f..2bccb7b9da2d 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h | |||
@@ -459,6 +459,8 @@ enum perf_callchain_context { | |||
459 | #include <linux/fs.h> | 459 | #include <linux/fs.h> |
460 | #include <linux/pid_namespace.h> | 460 | #include <linux/pid_namespace.h> |
461 | #include <linux/workqueue.h> | 461 | #include <linux/workqueue.h> |
462 | #include <linux/ftrace.h> | ||
463 | #include <linux/cpu.h> | ||
462 | #include <asm/atomic.h> | 464 | #include <asm/atomic.h> |
463 | 465 | ||
464 | #define PERF_MAX_STACK_DEPTH 255 | 466 | #define PERF_MAX_STACK_DEPTH 255 |
@@ -865,6 +867,44 @@ perf_sw_event(u32 event_id, u64 nr, int nmi, struct pt_regs *regs, u64 addr) | |||
865 | __perf_sw_event(event_id, nr, nmi, regs, addr); | 867 | __perf_sw_event(event_id, nr, nmi, regs, addr); |
866 | } | 868 | } |
867 | 869 | ||
870 | extern void | ||
871 | perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip); | ||
872 | |||
873 | /* | ||
874 | * Take a snapshot of the regs. Skip ip and frame pointer to | ||
875 | * the nth caller. We only need a few of the regs: | ||
876 | * - ip for PERF_SAMPLE_IP | ||
877 | * - cs for user_mode() tests | ||
878 | * - bp for callchains | ||
879 | * - eflags, for future purposes, just in case | ||
880 | */ | ||
881 | static inline void perf_fetch_caller_regs(struct pt_regs *regs, int skip) | ||
882 | { | ||
883 | unsigned long ip; | ||
884 | |||
885 | memset(regs, 0, sizeof(*regs)); | ||
886 | |||
887 | switch (skip) { | ||
888 | case 1 : | ||
889 | ip = CALLER_ADDR0; | ||
890 | break; | ||
891 | case 2 : | ||
892 | ip = CALLER_ADDR1; | ||
893 | break; | ||
894 | case 3 : | ||
895 | ip = CALLER_ADDR2; | ||
896 | break; | ||
897 | case 4: | ||
898 | ip = CALLER_ADDR3; | ||
899 | break; | ||
900 | /* No need to support further for now */ | ||
901 | default: | ||
902 | ip = 0; | ||
903 | } | ||
904 | |||
905 | return perf_arch_fetch_caller_regs(regs, ip, skip); | ||
906 | } | ||
907 | |||
868 | extern void __perf_event_mmap(struct vm_area_struct *vma); | 908 | extern void __perf_event_mmap(struct vm_area_struct *vma); |
869 | 909 | ||
870 | static inline void perf_event_mmap(struct vm_area_struct *vma) | 910 | static inline void perf_event_mmap(struct vm_area_struct *vma) |
@@ -898,7 +938,8 @@ static inline bool perf_paranoid_kernel(void) | |||
898 | } | 938 | } |
899 | 939 | ||
900 | extern void perf_event_init(void); | 940 | extern void perf_event_init(void); |
901 | extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, int entry_size); | 941 | extern void perf_tp_event(int event_id, u64 addr, u64 count, void *record, |
942 | int entry_size, struct pt_regs *regs); | ||
902 | extern void perf_bp_event(struct perf_event *event, void *data); | 943 | extern void perf_bp_event(struct perf_event *event, void *data); |
903 | 944 | ||
904 | #ifndef perf_misc_flags | 945 | #ifndef perf_misc_flags |
diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 8126f239edf0..51435bcc3460 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h | |||
@@ -101,18 +101,18 @@ struct perf_event_attr; | |||
101 | 101 | ||
102 | #ifdef CONFIG_PERF_EVENTS | 102 | #ifdef CONFIG_PERF_EVENTS |
103 | 103 | ||
104 | #define TRACE_SYS_ENTER_PROFILE_INIT(sname) \ | 104 | #define TRACE_SYS_ENTER_PERF_INIT(sname) \ |
105 | .profile_enable = prof_sysenter_enable, \ | 105 | .perf_event_enable = perf_sysenter_enable, \ |
106 | .profile_disable = prof_sysenter_disable, | 106 | .perf_event_disable = perf_sysenter_disable, |
107 | 107 | ||
108 | #define TRACE_SYS_EXIT_PROFILE_INIT(sname) \ | 108 | #define TRACE_SYS_EXIT_PERF_INIT(sname) \ |
109 | .profile_enable = prof_sysexit_enable, \ | 109 | .perf_event_enable = perf_sysexit_enable, \ |
110 | .profile_disable = prof_sysexit_disable, | 110 | .perf_event_disable = perf_sysexit_disable, |
111 | #else | 111 | #else |
112 | #define TRACE_SYS_ENTER_PROFILE(sname) | 112 | #define TRACE_SYS_ENTER_PERF(sname) |
113 | #define TRACE_SYS_ENTER_PROFILE_INIT(sname) | 113 | #define TRACE_SYS_ENTER_PERF_INIT(sname) |
114 | #define TRACE_SYS_EXIT_PROFILE(sname) | 114 | #define TRACE_SYS_EXIT_PERF(sname) |
115 | #define TRACE_SYS_EXIT_PROFILE_INIT(sname) | 115 | #define TRACE_SYS_EXIT_PERF_INIT(sname) |
116 | #endif /* CONFIG_PERF_EVENTS */ | 116 | #endif /* CONFIG_PERF_EVENTS */ |
117 | 117 | ||
118 | #ifdef CONFIG_FTRACE_SYSCALLS | 118 | #ifdef CONFIG_FTRACE_SYSCALLS |
@@ -149,7 +149,7 @@ struct perf_event_attr; | |||
149 | .regfunc = reg_event_syscall_enter, \ | 149 | .regfunc = reg_event_syscall_enter, \ |
150 | .unregfunc = unreg_event_syscall_enter, \ | 150 | .unregfunc = unreg_event_syscall_enter, \ |
151 | .data = (void *)&__syscall_meta_##sname,\ | 151 | .data = (void *)&__syscall_meta_##sname,\ |
152 | TRACE_SYS_ENTER_PROFILE_INIT(sname) \ | 152 | TRACE_SYS_ENTER_PERF_INIT(sname) \ |
153 | } | 153 | } |
154 | 154 | ||
155 | #define SYSCALL_TRACE_EXIT_EVENT(sname) \ | 155 | #define SYSCALL_TRACE_EXIT_EVENT(sname) \ |
@@ -171,7 +171,7 @@ struct perf_event_attr; | |||
171 | .regfunc = reg_event_syscall_exit, \ | 171 | .regfunc = reg_event_syscall_exit, \ |
172 | .unregfunc = unreg_event_syscall_exit, \ | 172 | .unregfunc = unreg_event_syscall_exit, \ |
173 | .data = (void *)&__syscall_meta_##sname,\ | 173 | .data = (void *)&__syscall_meta_##sname,\ |
174 | TRACE_SYS_EXIT_PROFILE_INIT(sname) \ | 174 | TRACE_SYS_EXIT_PERF_INIT(sname) \ |
175 | } | 175 | } |
176 | 176 | ||
177 | #define SYSCALL_METADATA(sname, nb) \ | 177 | #define SYSCALL_METADATA(sname, nb) \ |
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h index 0804cd594803..25ab56f75d65 100644 --- a/include/trace/ftrace.h +++ b/include/trace/ftrace.h | |||
@@ -401,18 +401,18 @@ static inline notrace int ftrace_get_offsets_##call( \ | |||
401 | #undef DEFINE_EVENT | 401 | #undef DEFINE_EVENT |
402 | #define DEFINE_EVENT(template, name, proto, args) \ | 402 | #define DEFINE_EVENT(template, name, proto, args) \ |
403 | \ | 403 | \ |
404 | static void ftrace_profile_##name(proto); \ | 404 | static void perf_trace_##name(proto); \ |
405 | \ | 405 | \ |
406 | static notrace int \ | 406 | static notrace int \ |
407 | ftrace_profile_enable_##name(struct ftrace_event_call *unused) \ | 407 | perf_trace_enable_##name(struct ftrace_event_call *unused) \ |
408 | { \ | 408 | { \ |
409 | return register_trace_##name(ftrace_profile_##name); \ | 409 | return register_trace_##name(perf_trace_##name); \ |
410 | } \ | 410 | } \ |
411 | \ | 411 | \ |
412 | static notrace void \ | 412 | static notrace void \ |
413 | ftrace_profile_disable_##name(struct ftrace_event_call *unused) \ | 413 | perf_trace_disable_##name(struct ftrace_event_call *unused) \ |
414 | { \ | 414 | { \ |
415 | unregister_trace_##name(ftrace_profile_##name); \ | 415 | unregister_trace_##name(perf_trace_##name); \ |
416 | } | 416 | } |
417 | 417 | ||
418 | #undef DEFINE_EVENT_PRINT | 418 | #undef DEFINE_EVENT_PRINT |
@@ -507,12 +507,12 @@ ftrace_profile_disable_##name(struct ftrace_event_call *unused) \ | |||
507 | 507 | ||
508 | #ifdef CONFIG_PERF_EVENTS | 508 | #ifdef CONFIG_PERF_EVENTS |
509 | 509 | ||
510 | #define _TRACE_PROFILE_INIT(call) \ | 510 | #define _TRACE_PERF_INIT(call) \ |
511 | .profile_enable = ftrace_profile_enable_##call, \ | 511 | .perf_event_enable = perf_trace_enable_##call, \ |
512 | .profile_disable = ftrace_profile_disable_##call, | 512 | .perf_event_disable = perf_trace_disable_##call, |
513 | 513 | ||
514 | #else | 514 | #else |
515 | #define _TRACE_PROFILE_INIT(call) | 515 | #define _TRACE_PERF_INIT(call) |
516 | #endif /* CONFIG_PERF_EVENTS */ | 516 | #endif /* CONFIG_PERF_EVENTS */ |
517 | 517 | ||
518 | #undef __entry | 518 | #undef __entry |
@@ -638,7 +638,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
638 | .unregfunc = ftrace_raw_unreg_event_##call, \ | 638 | .unregfunc = ftrace_raw_unreg_event_##call, \ |
639 | .print_fmt = print_fmt_##template, \ | 639 | .print_fmt = print_fmt_##template, \ |
640 | .define_fields = ftrace_define_fields_##template, \ | 640 | .define_fields = ftrace_define_fields_##template, \ |
641 | _TRACE_PROFILE_INIT(call) \ | 641 | _TRACE_PERF_INIT(call) \ |
642 | } | 642 | } |
643 | 643 | ||
644 | #undef DEFINE_EVENT_PRINT | 644 | #undef DEFINE_EVENT_PRINT |
@@ -657,18 +657,18 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
657 | .unregfunc = ftrace_raw_unreg_event_##call, \ | 657 | .unregfunc = ftrace_raw_unreg_event_##call, \ |
658 | .print_fmt = print_fmt_##call, \ | 658 | .print_fmt = print_fmt_##call, \ |
659 | .define_fields = ftrace_define_fields_##template, \ | 659 | .define_fields = ftrace_define_fields_##template, \ |
660 | _TRACE_PROFILE_INIT(call) \ | 660 | _TRACE_PERF_INIT(call) \ |
661 | } | 661 | } |
662 | 662 | ||
663 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) | 663 | #include TRACE_INCLUDE(TRACE_INCLUDE_FILE) |
664 | 664 | ||
665 | /* | 665 | /* |
666 | * Define the insertion callback to profile events | 666 | * Define the insertion callback to perf events |
667 | * | 667 | * |
668 | * The job is very similar to ftrace_raw_event_<call> except that we don't | 668 | * The job is very similar to ftrace_raw_event_<call> except that we don't |
669 | * insert in the ring buffer but in a perf counter. | 669 | * insert in the ring buffer but in a perf counter. |
670 | * | 670 | * |
671 | * static void ftrace_profile_<call>(proto) | 671 | * static void ftrace_perf_<call>(proto) |
672 | * { | 672 | * { |
673 | * struct ftrace_data_offsets_<call> __maybe_unused __data_offsets; | 673 | * struct ftrace_data_offsets_<call> __maybe_unused __data_offsets; |
674 | * struct ftrace_event_call *event_call = &event_<call>; | 674 | * struct ftrace_event_call *event_call = &event_<call>; |
@@ -757,13 +757,14 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
757 | #undef DECLARE_EVENT_CLASS | 757 | #undef DECLARE_EVENT_CLASS |
758 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ | 758 | #define DECLARE_EVENT_CLASS(call, proto, args, tstruct, assign, print) \ |
759 | static notrace void \ | 759 | static notrace void \ |
760 | ftrace_profile_templ_##call(struct ftrace_event_call *event_call, \ | 760 | perf_trace_templ_##call(struct ftrace_event_call *event_call, \ |
761 | proto) \ | 761 | proto) \ |
762 | { \ | 762 | { \ |
763 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ | 763 | struct ftrace_data_offsets_##call __maybe_unused __data_offsets;\ |
764 | struct ftrace_raw_##call *entry; \ | 764 | struct ftrace_raw_##call *entry; \ |
765 | u64 __addr = 0, __count = 1; \ | 765 | u64 __addr = 0, __count = 1; \ |
766 | unsigned long irq_flags; \ | 766 | unsigned long irq_flags; \ |
767 | struct pt_regs *__regs; \ | ||
767 | int __entry_size; \ | 768 | int __entry_size; \ |
768 | int __data_size; \ | 769 | int __data_size; \ |
769 | int rctx; \ | 770 | int rctx; \ |
@@ -773,10 +774,10 @@ ftrace_profile_templ_##call(struct ftrace_event_call *event_call, \ | |||
773 | sizeof(u64)); \ | 774 | sizeof(u64)); \ |
774 | __entry_size -= sizeof(u32); \ | 775 | __entry_size -= sizeof(u32); \ |
775 | \ | 776 | \ |
776 | if (WARN_ONCE(__entry_size > FTRACE_MAX_PROFILE_SIZE, \ | 777 | if (WARN_ONCE(__entry_size > PERF_MAX_TRACE_SIZE, \ |
777 | "profile buffer not large enough")) \ | 778 | "profile buffer not large enough")) \ |
778 | return; \ | 779 | return; \ |
779 | entry = (struct ftrace_raw_##call *)ftrace_perf_buf_prepare( \ | 780 | entry = (struct ftrace_raw_##call *)perf_trace_buf_prepare( \ |
780 | __entry_size, event_call->id, &rctx, &irq_flags); \ | 781 | __entry_size, event_call->id, &rctx, &irq_flags); \ |
781 | if (!entry) \ | 782 | if (!entry) \ |
782 | return; \ | 783 | return; \ |
@@ -784,17 +785,20 @@ ftrace_profile_templ_##call(struct ftrace_event_call *event_call, \ | |||
784 | \ | 785 | \ |
785 | { assign; } \ | 786 | { assign; } \ |
786 | \ | 787 | \ |
787 | ftrace_perf_buf_submit(entry, __entry_size, rctx, __addr, \ | 788 | __regs = &__get_cpu_var(perf_trace_regs); \ |
788 | __count, irq_flags); \ | 789 | perf_fetch_caller_regs(__regs, 2); \ |
790 | \ | ||
791 | perf_trace_buf_submit(entry, __entry_size, rctx, __addr, \ | ||
792 | __count, irq_flags, __regs); \ | ||
789 | } | 793 | } |
790 | 794 | ||
791 | #undef DEFINE_EVENT | 795 | #undef DEFINE_EVENT |
792 | #define DEFINE_EVENT(template, call, proto, args) \ | 796 | #define DEFINE_EVENT(template, call, proto, args) \ |
793 | static notrace void ftrace_profile_##call(proto) \ | 797 | static notrace void perf_trace_##call(proto) \ |
794 | { \ | 798 | { \ |
795 | struct ftrace_event_call *event_call = &event_##call; \ | 799 | struct ftrace_event_call *event_call = &event_##call; \ |
796 | \ | 800 | \ |
797 | ftrace_profile_templ_##template(event_call, args); \ | 801 | perf_trace_templ_##template(event_call, args); \ |
798 | } | 802 | } |
799 | 803 | ||
800 | #undef DEFINE_EVENT_PRINT | 804 | #undef DEFINE_EVENT_PRINT |
diff --git a/include/trace/syscall.h b/include/trace/syscall.h index 0387100752f0..e5e5f48dbfb3 100644 --- a/include/trace/syscall.h +++ b/include/trace/syscall.h | |||
@@ -47,10 +47,10 @@ enum print_line_t print_syscall_exit(struct trace_iterator *iter, int flags); | |||
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #ifdef CONFIG_PERF_EVENTS | 49 | #ifdef CONFIG_PERF_EVENTS |
50 | int prof_sysenter_enable(struct ftrace_event_call *call); | 50 | int perf_sysenter_enable(struct ftrace_event_call *call); |
51 | void prof_sysenter_disable(struct ftrace_event_call *call); | 51 | void perf_sysenter_disable(struct ftrace_event_call *call); |
52 | int prof_sysexit_enable(struct ftrace_event_call *call); | 52 | int perf_sysexit_enable(struct ftrace_event_call *call); |
53 | void prof_sysexit_disable(struct ftrace_event_call *call); | 53 | void perf_sysexit_disable(struct ftrace_event_call *call); |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | #endif /* _TRACE_SYSCALL_H */ | 56 | #endif /* _TRACE_SYSCALL_H */ |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index fa034d29cf73..0ed46f3e51e9 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -259,7 +259,8 @@ static void __kprobes __free_insn_slot(struct kprobe_insn_cache *c, | |||
259 | struct kprobe_insn_page *kip; | 259 | struct kprobe_insn_page *kip; |
260 | 260 | ||
261 | list_for_each_entry(kip, &c->pages, list) { | 261 | list_for_each_entry(kip, &c->pages, list) { |
262 | long idx = ((long)slot - (long)kip->insns) / c->insn_size; | 262 | long idx = ((long)slot - (long)kip->insns) / |
263 | (c->insn_size * sizeof(kprobe_opcode_t)); | ||
263 | if (idx >= 0 && idx < slots_per_page(c)) { | 264 | if (idx >= 0 && idx < slots_per_page(c)) { |
264 | WARN_ON(kip->slot_used[idx] != SLOT_USED); | 265 | WARN_ON(kip->slot_used[idx] != SLOT_USED); |
265 | if (dirty) { | 266 | if (dirty) { |
diff --git a/kernel/lockdep.c b/kernel/lockdep.c index 0c30d0455de1..65b5f5b7c298 100644 --- a/kernel/lockdep.c +++ b/kernel/lockdep.c | |||
@@ -3211,8 +3211,6 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
3211 | { | 3211 | { |
3212 | unsigned long flags; | 3212 | unsigned long flags; |
3213 | 3213 | ||
3214 | trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip); | ||
3215 | |||
3216 | if (unlikely(current->lockdep_recursion)) | 3214 | if (unlikely(current->lockdep_recursion)) |
3217 | return; | 3215 | return; |
3218 | 3216 | ||
@@ -3220,6 +3218,7 @@ void lock_acquire(struct lockdep_map *lock, unsigned int subclass, | |||
3220 | check_flags(flags); | 3218 | check_flags(flags); |
3221 | 3219 | ||
3222 | current->lockdep_recursion = 1; | 3220 | current->lockdep_recursion = 1; |
3221 | trace_lock_acquire(lock, subclass, trylock, read, check, nest_lock, ip); | ||
3223 | __lock_acquire(lock, subclass, trylock, read, check, | 3222 | __lock_acquire(lock, subclass, trylock, read, check, |
3224 | irqs_disabled_flags(flags), nest_lock, ip, 0); | 3223 | irqs_disabled_flags(flags), nest_lock, ip, 0); |
3225 | current->lockdep_recursion = 0; | 3224 | current->lockdep_recursion = 0; |
@@ -3232,14 +3231,13 @@ void lock_release(struct lockdep_map *lock, int nested, | |||
3232 | { | 3231 | { |
3233 | unsigned long flags; | 3232 | unsigned long flags; |
3234 | 3233 | ||
3235 | trace_lock_release(lock, nested, ip); | ||
3236 | |||
3237 | if (unlikely(current->lockdep_recursion)) | 3234 | if (unlikely(current->lockdep_recursion)) |
3238 | return; | 3235 | return; |
3239 | 3236 | ||
3240 | raw_local_irq_save(flags); | 3237 | raw_local_irq_save(flags); |
3241 | check_flags(flags); | 3238 | check_flags(flags); |
3242 | current->lockdep_recursion = 1; | 3239 | current->lockdep_recursion = 1; |
3240 | trace_lock_release(lock, nested, ip); | ||
3243 | __lock_release(lock, nested, ip); | 3241 | __lock_release(lock, nested, ip); |
3244 | current->lockdep_recursion = 0; | 3242 | current->lockdep_recursion = 0; |
3245 | raw_local_irq_restore(flags); | 3243 | raw_local_irq_restore(flags); |
@@ -3413,8 +3411,6 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip) | |||
3413 | { | 3411 | { |
3414 | unsigned long flags; | 3412 | unsigned long flags; |
3415 | 3413 | ||
3416 | trace_lock_contended(lock, ip); | ||
3417 | |||
3418 | if (unlikely(!lock_stat)) | 3414 | if (unlikely(!lock_stat)) |
3419 | return; | 3415 | return; |
3420 | 3416 | ||
@@ -3424,6 +3420,7 @@ void lock_contended(struct lockdep_map *lock, unsigned long ip) | |||
3424 | raw_local_irq_save(flags); | 3420 | raw_local_irq_save(flags); |
3425 | check_flags(flags); | 3421 | check_flags(flags); |
3426 | current->lockdep_recursion = 1; | 3422 | current->lockdep_recursion = 1; |
3423 | trace_lock_contended(lock, ip); | ||
3427 | __lock_contended(lock, ip); | 3424 | __lock_contended(lock, ip); |
3428 | current->lockdep_recursion = 0; | 3425 | current->lockdep_recursion = 0; |
3429 | raw_local_irq_restore(flags); | 3426 | raw_local_irq_restore(flags); |
diff --git a/kernel/perf_event.c b/kernel/perf_event.c index 3853d49c7d56..8bf61273c58b 100644 --- a/kernel/perf_event.c +++ b/kernel/perf_event.c | |||
@@ -2790,6 +2790,11 @@ __weak struct perf_callchain_entry *perf_callchain(struct pt_regs *regs) | |||
2790 | return NULL; | 2790 | return NULL; |
2791 | } | 2791 | } |
2792 | 2792 | ||
2793 | __weak | ||
2794 | void perf_arch_fetch_caller_regs(struct pt_regs *regs, unsigned long ip, int skip) | ||
2795 | { | ||
2796 | } | ||
2797 | |||
2793 | /* | 2798 | /* |
2794 | * Output | 2799 | * Output |
2795 | */ | 2800 | */ |
@@ -4317,9 +4322,8 @@ static const struct pmu perf_ops_task_clock = { | |||
4317 | #ifdef CONFIG_EVENT_TRACING | 4322 | #ifdef CONFIG_EVENT_TRACING |
4318 | 4323 | ||
4319 | void perf_tp_event(int event_id, u64 addr, u64 count, void *record, | 4324 | void perf_tp_event(int event_id, u64 addr, u64 count, void *record, |
4320 | int entry_size) | 4325 | int entry_size, struct pt_regs *regs) |
4321 | { | 4326 | { |
4322 | struct pt_regs *regs = get_irq_regs(); | ||
4323 | struct perf_sample_data data; | 4327 | struct perf_sample_data data; |
4324 | struct perf_raw_record raw = { | 4328 | struct perf_raw_record raw = { |
4325 | .size = entry_size, | 4329 | .size = entry_size, |
@@ -4329,12 +4333,9 @@ void perf_tp_event(int event_id, u64 addr, u64 count, void *record, | |||
4329 | perf_sample_data_init(&data, addr); | 4333 | perf_sample_data_init(&data, addr); |
4330 | data.raw = &raw; | 4334 | data.raw = &raw; |
4331 | 4335 | ||
4332 | if (!regs) | ||
4333 | regs = task_pt_regs(current); | ||
4334 | |||
4335 | /* Trace events already protected against recursion */ | 4336 | /* Trace events already protected against recursion */ |
4336 | do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, | 4337 | do_perf_sw_event(PERF_TYPE_TRACEPOINT, event_id, count, 1, |
4337 | &data, regs); | 4338 | &data, regs); |
4338 | } | 4339 | } |
4339 | EXPORT_SYMBOL_GPL(perf_tp_event); | 4340 | EXPORT_SYMBOL_GPL(perf_tp_event); |
4340 | 4341 | ||
@@ -4350,7 +4351,7 @@ static int perf_tp_event_match(struct perf_event *event, | |||
4350 | 4351 | ||
4351 | static void tp_perf_event_destroy(struct perf_event *event) | 4352 | static void tp_perf_event_destroy(struct perf_event *event) |
4352 | { | 4353 | { |
4353 | ftrace_profile_disable(event->attr.config); | 4354 | perf_trace_disable(event->attr.config); |
4354 | } | 4355 | } |
4355 | 4356 | ||
4356 | static const struct pmu *tp_perf_event_init(struct perf_event *event) | 4357 | static const struct pmu *tp_perf_event_init(struct perf_event *event) |
@@ -4364,7 +4365,7 @@ static const struct pmu *tp_perf_event_init(struct perf_event *event) | |||
4364 | !capable(CAP_SYS_ADMIN)) | 4365 | !capable(CAP_SYS_ADMIN)) |
4365 | return ERR_PTR(-EPERM); | 4366 | return ERR_PTR(-EPERM); |
4366 | 4367 | ||
4367 | if (ftrace_profile_enable(event->attr.config)) | 4368 | if (perf_trace_enable(event->attr.config)) |
4368 | return NULL; | 4369 | return NULL; |
4369 | 4370 | ||
4370 | event->destroy = tp_perf_event_destroy; | 4371 | event->destroy = tp_perf_event_destroy; |
@@ -5371,12 +5372,22 @@ int perf_event_init_task(struct task_struct *child) | |||
5371 | return ret; | 5372 | return ret; |
5372 | } | 5373 | } |
5373 | 5374 | ||
5375 | static void __init perf_event_init_all_cpus(void) | ||
5376 | { | ||
5377 | int cpu; | ||
5378 | struct perf_cpu_context *cpuctx; | ||
5379 | |||
5380 | for_each_possible_cpu(cpu) { | ||
5381 | cpuctx = &per_cpu(perf_cpu_context, cpu); | ||
5382 | __perf_event_init_context(&cpuctx->ctx, NULL); | ||
5383 | } | ||
5384 | } | ||
5385 | |||
5374 | static void __cpuinit perf_event_init_cpu(int cpu) | 5386 | static void __cpuinit perf_event_init_cpu(int cpu) |
5375 | { | 5387 | { |
5376 | struct perf_cpu_context *cpuctx; | 5388 | struct perf_cpu_context *cpuctx; |
5377 | 5389 | ||
5378 | cpuctx = &per_cpu(perf_cpu_context, cpu); | 5390 | cpuctx = &per_cpu(perf_cpu_context, cpu); |
5379 | __perf_event_init_context(&cpuctx->ctx, NULL); | ||
5380 | 5391 | ||
5381 | spin_lock(&perf_resource_lock); | 5392 | spin_lock(&perf_resource_lock); |
5382 | cpuctx->max_pertask = perf_max_events - perf_reserved_percpu; | 5393 | cpuctx->max_pertask = perf_max_events - perf_reserved_percpu; |
@@ -5442,6 +5453,7 @@ static struct notifier_block __cpuinitdata perf_cpu_nb = { | |||
5442 | 5453 | ||
5443 | void __init perf_event_init(void) | 5454 | void __init perf_event_init(void) |
5444 | { | 5455 | { |
5456 | perf_event_init_all_cpus(); | ||
5445 | perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE, | 5457 | perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_UP_PREPARE, |
5446 | (void *)(long)smp_processor_id()); | 5458 | (void *)(long)smp_processor_id()); |
5447 | perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE, | 5459 | perf_cpu_notify(&perf_cpu_nb, (unsigned long)CPU_ONLINE, |
diff --git a/kernel/trace/Makefile b/kernel/trace/Makefile index d00c6fe23f54..78edc6490038 100644 --- a/kernel/trace/Makefile +++ b/kernel/trace/Makefile | |||
@@ -52,7 +52,7 @@ obj-$(CONFIG_EVENT_TRACING) += trace_events.o | |||
52 | obj-$(CONFIG_EVENT_TRACING) += trace_export.o | 52 | obj-$(CONFIG_EVENT_TRACING) += trace_export.o |
53 | obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o | 53 | obj-$(CONFIG_FTRACE_SYSCALLS) += trace_syscalls.o |
54 | ifeq ($(CONFIG_PERF_EVENTS),y) | 54 | ifeq ($(CONFIG_PERF_EVENTS),y) |
55 | obj-$(CONFIG_EVENT_TRACING) += trace_event_profile.o | 55 | obj-$(CONFIG_EVENT_TRACING) += trace_event_perf.o |
56 | endif | 56 | endif |
57 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o | 57 | obj-$(CONFIG_EVENT_TRACING) += trace_events_filter.o |
58 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o | 58 | obj-$(CONFIG_KPROBE_EVENT) += trace_kprobe.o |
diff --git a/kernel/trace/trace_event_profile.c b/kernel/trace/trace_event_perf.c index f0d693005075..0709e4f75114 100644 --- a/kernel/trace/trace_event_profile.c +++ b/kernel/trace/trace_event_perf.c | |||
@@ -1,32 +1,34 @@ | |||
1 | /* | 1 | /* |
2 | * trace event based perf counter profiling | 2 | * trace event based perf event profiling/tracing |
3 | * | 3 | * |
4 | * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com> | 4 | * Copyright (C) 2009 Red Hat Inc, Peter Zijlstra <pzijlstr@redhat.com> |
5 | * | 5 | * Copyright (C) 2009-2010 Frederic Weisbecker <fweisbec@gmail.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/kprobes.h> | 9 | #include <linux/kprobes.h> |
10 | #include "trace.h" | 10 | #include "trace.h" |
11 | 11 | ||
12 | DEFINE_PER_CPU(struct pt_regs, perf_trace_regs); | ||
13 | EXPORT_PER_CPU_SYMBOL_GPL(perf_trace_regs); | ||
12 | 14 | ||
13 | static char *perf_trace_buf; | 15 | static char *perf_trace_buf; |
14 | static char *perf_trace_buf_nmi; | 16 | static char *perf_trace_buf_nmi; |
15 | 17 | ||
16 | typedef typeof(char [FTRACE_MAX_PROFILE_SIZE]) perf_trace_t ; | 18 | typedef typeof(char [PERF_MAX_TRACE_SIZE]) perf_trace_t ; |
17 | 19 | ||
18 | /* Count the events in use (per event id, not per instance) */ | 20 | /* Count the events in use (per event id, not per instance) */ |
19 | static int total_profile_count; | 21 | static int total_ref_count; |
20 | 22 | ||
21 | static int ftrace_profile_enable_event(struct ftrace_event_call *event) | 23 | static int perf_trace_event_enable(struct ftrace_event_call *event) |
22 | { | 24 | { |
23 | char *buf; | 25 | char *buf; |
24 | int ret = -ENOMEM; | 26 | int ret = -ENOMEM; |
25 | 27 | ||
26 | if (event->profile_count++ > 0) | 28 | if (event->perf_refcount++ > 0) |
27 | return 0; | 29 | return 0; |
28 | 30 | ||
29 | if (!total_profile_count) { | 31 | if (!total_ref_count) { |
30 | buf = (char *)alloc_percpu(perf_trace_t); | 32 | buf = (char *)alloc_percpu(perf_trace_t); |
31 | if (!buf) | 33 | if (!buf) |
32 | goto fail_buf; | 34 | goto fail_buf; |
@@ -40,35 +42,35 @@ static int ftrace_profile_enable_event(struct ftrace_event_call *event) | |||
40 | rcu_assign_pointer(perf_trace_buf_nmi, buf); | 42 | rcu_assign_pointer(perf_trace_buf_nmi, buf); |
41 | } | 43 | } |
42 | 44 | ||
43 | ret = event->profile_enable(event); | 45 | ret = event->perf_event_enable(event); |
44 | if (!ret) { | 46 | if (!ret) { |
45 | total_profile_count++; | 47 | total_ref_count++; |
46 | return 0; | 48 | return 0; |
47 | } | 49 | } |
48 | 50 | ||
49 | fail_buf_nmi: | 51 | fail_buf_nmi: |
50 | if (!total_profile_count) { | 52 | if (!total_ref_count) { |
51 | free_percpu(perf_trace_buf_nmi); | 53 | free_percpu(perf_trace_buf_nmi); |
52 | free_percpu(perf_trace_buf); | 54 | free_percpu(perf_trace_buf); |
53 | perf_trace_buf_nmi = NULL; | 55 | perf_trace_buf_nmi = NULL; |
54 | perf_trace_buf = NULL; | 56 | perf_trace_buf = NULL; |
55 | } | 57 | } |
56 | fail_buf: | 58 | fail_buf: |
57 | event->profile_count--; | 59 | event->perf_refcount--; |
58 | 60 | ||
59 | return ret; | 61 | return ret; |
60 | } | 62 | } |
61 | 63 | ||
62 | int ftrace_profile_enable(int event_id) | 64 | int perf_trace_enable(int event_id) |
63 | { | 65 | { |
64 | struct ftrace_event_call *event; | 66 | struct ftrace_event_call *event; |
65 | int ret = -EINVAL; | 67 | int ret = -EINVAL; |
66 | 68 | ||
67 | mutex_lock(&event_mutex); | 69 | mutex_lock(&event_mutex); |
68 | list_for_each_entry(event, &ftrace_events, list) { | 70 | list_for_each_entry(event, &ftrace_events, list) { |
69 | if (event->id == event_id && event->profile_enable && | 71 | if (event->id == event_id && event->perf_event_enable && |
70 | try_module_get(event->mod)) { | 72 | try_module_get(event->mod)) { |
71 | ret = ftrace_profile_enable_event(event); | 73 | ret = perf_trace_event_enable(event); |
72 | break; | 74 | break; |
73 | } | 75 | } |
74 | } | 76 | } |
@@ -77,16 +79,16 @@ int ftrace_profile_enable(int event_id) | |||
77 | return ret; | 79 | return ret; |
78 | } | 80 | } |
79 | 81 | ||
80 | static void ftrace_profile_disable_event(struct ftrace_event_call *event) | 82 | static void perf_trace_event_disable(struct ftrace_event_call *event) |
81 | { | 83 | { |
82 | char *buf, *nmi_buf; | 84 | char *buf, *nmi_buf; |
83 | 85 | ||
84 | if (--event->profile_count > 0) | 86 | if (--event->perf_refcount > 0) |
85 | return; | 87 | return; |
86 | 88 | ||
87 | event->profile_disable(event); | 89 | event->perf_event_disable(event); |
88 | 90 | ||
89 | if (!--total_profile_count) { | 91 | if (!--total_ref_count) { |
90 | buf = perf_trace_buf; | 92 | buf = perf_trace_buf; |
91 | rcu_assign_pointer(perf_trace_buf, NULL); | 93 | rcu_assign_pointer(perf_trace_buf, NULL); |
92 | 94 | ||
@@ -104,14 +106,14 @@ static void ftrace_profile_disable_event(struct ftrace_event_call *event) | |||
104 | } | 106 | } |
105 | } | 107 | } |
106 | 108 | ||
107 | void ftrace_profile_disable(int event_id) | 109 | void perf_trace_disable(int event_id) |
108 | { | 110 | { |
109 | struct ftrace_event_call *event; | 111 | struct ftrace_event_call *event; |
110 | 112 | ||
111 | mutex_lock(&event_mutex); | 113 | mutex_lock(&event_mutex); |
112 | list_for_each_entry(event, &ftrace_events, list) { | 114 | list_for_each_entry(event, &ftrace_events, list) { |
113 | if (event->id == event_id) { | 115 | if (event->id == event_id) { |
114 | ftrace_profile_disable_event(event); | 116 | perf_trace_event_disable(event); |
115 | module_put(event->mod); | 117 | module_put(event->mod); |
116 | break; | 118 | break; |
117 | } | 119 | } |
@@ -119,8 +121,8 @@ void ftrace_profile_disable(int event_id) | |||
119 | mutex_unlock(&event_mutex); | 121 | mutex_unlock(&event_mutex); |
120 | } | 122 | } |
121 | 123 | ||
122 | __kprobes void *ftrace_perf_buf_prepare(int size, unsigned short type, | 124 | __kprobes void *perf_trace_buf_prepare(int size, unsigned short type, |
123 | int *rctxp, unsigned long *irq_flags) | 125 | int *rctxp, unsigned long *irq_flags) |
124 | { | 126 | { |
125 | struct trace_entry *entry; | 127 | struct trace_entry *entry; |
126 | char *trace_buf, *raw_data; | 128 | char *trace_buf, *raw_data; |
@@ -161,4 +163,4 @@ err_recursion: | |||
161 | local_irq_restore(*irq_flags); | 163 | local_irq_restore(*irq_flags); |
162 | return NULL; | 164 | return NULL; |
163 | } | 165 | } |
164 | EXPORT_SYMBOL_GPL(ftrace_perf_buf_prepare); | 166 | EXPORT_SYMBOL_GPL(perf_trace_buf_prepare); |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 3f972ad98d04..beab8bf2f310 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -938,7 +938,7 @@ event_create_dir(struct ftrace_event_call *call, struct dentry *d_events, | |||
938 | trace_create_file("enable", 0644, call->dir, call, | 938 | trace_create_file("enable", 0644, call->dir, call, |
939 | enable); | 939 | enable); |
940 | 940 | ||
941 | if (call->id && call->profile_enable) | 941 | if (call->id && call->perf_event_enable) |
942 | trace_create_file("id", 0444, call->dir, call, | 942 | trace_create_file("id", 0444, call->dir, call, |
943 | id); | 943 | id); |
944 | 944 | ||
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index 505c92273b1a..1251e367bae9 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c | |||
@@ -1214,7 +1214,7 @@ static int set_print_fmt(struct trace_probe *tp) | |||
1214 | #ifdef CONFIG_PERF_EVENTS | 1214 | #ifdef CONFIG_PERF_EVENTS |
1215 | 1215 | ||
1216 | /* Kprobe profile handler */ | 1216 | /* Kprobe profile handler */ |
1217 | static __kprobes void kprobe_profile_func(struct kprobe *kp, | 1217 | static __kprobes void kprobe_perf_func(struct kprobe *kp, |
1218 | struct pt_regs *regs) | 1218 | struct pt_regs *regs) |
1219 | { | 1219 | { |
1220 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); | 1220 | struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); |
@@ -1227,11 +1227,11 @@ static __kprobes void kprobe_profile_func(struct kprobe *kp, | |||
1227 | __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); | 1227 | __size = SIZEOF_KPROBE_TRACE_ENTRY(tp->nr_args); |
1228 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1228 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
1229 | size -= sizeof(u32); | 1229 | size -= sizeof(u32); |
1230 | if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, | 1230 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
1231 | "profile buffer not large enough")) | 1231 | "profile buffer not large enough")) |
1232 | return; | 1232 | return; |
1233 | 1233 | ||
1234 | entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags); | 1234 | entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags); |
1235 | if (!entry) | 1235 | if (!entry) |
1236 | return; | 1236 | return; |
1237 | 1237 | ||
@@ -1240,11 +1240,11 @@ static __kprobes void kprobe_profile_func(struct kprobe *kp, | |||
1240 | for (i = 0; i < tp->nr_args; i++) | 1240 | for (i = 0; i < tp->nr_args; i++) |
1241 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1241 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); |
1242 | 1242 | ||
1243 | ftrace_perf_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags); | 1243 | perf_trace_buf_submit(entry, size, rctx, entry->ip, 1, irq_flags, regs); |
1244 | } | 1244 | } |
1245 | 1245 | ||
1246 | /* Kretprobe profile handler */ | 1246 | /* Kretprobe profile handler */ |
1247 | static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri, | 1247 | static __kprobes void kretprobe_perf_func(struct kretprobe_instance *ri, |
1248 | struct pt_regs *regs) | 1248 | struct pt_regs *regs) |
1249 | { | 1249 | { |
1250 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); | 1250 | struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); |
@@ -1257,11 +1257,11 @@ static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri, | |||
1257 | __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); | 1257 | __size = SIZEOF_KRETPROBE_TRACE_ENTRY(tp->nr_args); |
1258 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); | 1258 | size = ALIGN(__size + sizeof(u32), sizeof(u64)); |
1259 | size -= sizeof(u32); | 1259 | size -= sizeof(u32); |
1260 | if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, | 1260 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
1261 | "profile buffer not large enough")) | 1261 | "profile buffer not large enough")) |
1262 | return; | 1262 | return; |
1263 | 1263 | ||
1264 | entry = ftrace_perf_buf_prepare(size, call->id, &rctx, &irq_flags); | 1264 | entry = perf_trace_buf_prepare(size, call->id, &rctx, &irq_flags); |
1265 | if (!entry) | 1265 | if (!entry) |
1266 | return; | 1266 | return; |
1267 | 1267 | ||
@@ -1271,10 +1271,11 @@ static __kprobes void kretprobe_profile_func(struct kretprobe_instance *ri, | |||
1271 | for (i = 0; i < tp->nr_args; i++) | 1271 | for (i = 0; i < tp->nr_args; i++) |
1272 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); | 1272 | entry->args[i] = call_fetch(&tp->args[i].fetch, regs); |
1273 | 1273 | ||
1274 | ftrace_perf_buf_submit(entry, size, rctx, entry->ret_ip, 1, irq_flags); | 1274 | perf_trace_buf_submit(entry, size, rctx, entry->ret_ip, 1, |
1275 | irq_flags, regs); | ||
1275 | } | 1276 | } |
1276 | 1277 | ||
1277 | static int probe_profile_enable(struct ftrace_event_call *call) | 1278 | static int probe_perf_enable(struct ftrace_event_call *call) |
1278 | { | 1279 | { |
1279 | struct trace_probe *tp = (struct trace_probe *)call->data; | 1280 | struct trace_probe *tp = (struct trace_probe *)call->data; |
1280 | 1281 | ||
@@ -1286,7 +1287,7 @@ static int probe_profile_enable(struct ftrace_event_call *call) | |||
1286 | return enable_kprobe(&tp->rp.kp); | 1287 | return enable_kprobe(&tp->rp.kp); |
1287 | } | 1288 | } |
1288 | 1289 | ||
1289 | static void probe_profile_disable(struct ftrace_event_call *call) | 1290 | static void probe_perf_disable(struct ftrace_event_call *call) |
1290 | { | 1291 | { |
1291 | struct trace_probe *tp = (struct trace_probe *)call->data; | 1292 | struct trace_probe *tp = (struct trace_probe *)call->data; |
1292 | 1293 | ||
@@ -1311,7 +1312,7 @@ int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) | |||
1311 | kprobe_trace_func(kp, regs); | 1312 | kprobe_trace_func(kp, regs); |
1312 | #ifdef CONFIG_PERF_EVENTS | 1313 | #ifdef CONFIG_PERF_EVENTS |
1313 | if (tp->flags & TP_FLAG_PROFILE) | 1314 | if (tp->flags & TP_FLAG_PROFILE) |
1314 | kprobe_profile_func(kp, regs); | 1315 | kprobe_perf_func(kp, regs); |
1315 | #endif | 1316 | #endif |
1316 | return 0; /* We don't tweek kernel, so just return 0 */ | 1317 | return 0; /* We don't tweek kernel, so just return 0 */ |
1317 | } | 1318 | } |
@@ -1325,7 +1326,7 @@ int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) | |||
1325 | kretprobe_trace_func(ri, regs); | 1326 | kretprobe_trace_func(ri, regs); |
1326 | #ifdef CONFIG_PERF_EVENTS | 1327 | #ifdef CONFIG_PERF_EVENTS |
1327 | if (tp->flags & TP_FLAG_PROFILE) | 1328 | if (tp->flags & TP_FLAG_PROFILE) |
1328 | kretprobe_profile_func(ri, regs); | 1329 | kretprobe_perf_func(ri, regs); |
1329 | #endif | 1330 | #endif |
1330 | return 0; /* We don't tweek kernel, so just return 0 */ | 1331 | return 0; /* We don't tweek kernel, so just return 0 */ |
1331 | } | 1332 | } |
@@ -1358,8 +1359,8 @@ static int register_probe_event(struct trace_probe *tp) | |||
1358 | call->unregfunc = probe_event_disable; | 1359 | call->unregfunc = probe_event_disable; |
1359 | 1360 | ||
1360 | #ifdef CONFIG_PERF_EVENTS | 1361 | #ifdef CONFIG_PERF_EVENTS |
1361 | call->profile_enable = probe_profile_enable; | 1362 | call->perf_event_enable = probe_perf_enable; |
1362 | call->profile_disable = probe_profile_disable; | 1363 | call->perf_event_disable = probe_perf_disable; |
1363 | #endif | 1364 | #endif |
1364 | call->data = tp; | 1365 | call->data = tp; |
1365 | ret = trace_add_event_call(call); | 1366 | ret = trace_add_event_call(call); |
diff --git a/kernel/trace/trace_syscalls.c b/kernel/trace/trace_syscalls.c index cba47d7935cc..33c2a5b769dc 100644 --- a/kernel/trace/trace_syscalls.c +++ b/kernel/trace/trace_syscalls.c | |||
@@ -428,12 +428,12 @@ core_initcall(init_ftrace_syscalls); | |||
428 | 428 | ||
429 | #ifdef CONFIG_PERF_EVENTS | 429 | #ifdef CONFIG_PERF_EVENTS |
430 | 430 | ||
431 | static DECLARE_BITMAP(enabled_prof_enter_syscalls, NR_syscalls); | 431 | static DECLARE_BITMAP(enabled_perf_enter_syscalls, NR_syscalls); |
432 | static DECLARE_BITMAP(enabled_prof_exit_syscalls, NR_syscalls); | 432 | static DECLARE_BITMAP(enabled_perf_exit_syscalls, NR_syscalls); |
433 | static int sys_prof_refcount_enter; | 433 | static int sys_perf_refcount_enter; |
434 | static int sys_prof_refcount_exit; | 434 | static int sys_perf_refcount_exit; |
435 | 435 | ||
436 | static void prof_syscall_enter(struct pt_regs *regs, long id) | 436 | static void perf_syscall_enter(struct pt_regs *regs, long id) |
437 | { | 437 | { |
438 | struct syscall_metadata *sys_data; | 438 | struct syscall_metadata *sys_data; |
439 | struct syscall_trace_enter *rec; | 439 | struct syscall_trace_enter *rec; |
@@ -443,7 +443,7 @@ static void prof_syscall_enter(struct pt_regs *regs, long id) | |||
443 | int size; | 443 | int size; |
444 | 444 | ||
445 | syscall_nr = syscall_get_nr(current, regs); | 445 | syscall_nr = syscall_get_nr(current, regs); |
446 | if (!test_bit(syscall_nr, enabled_prof_enter_syscalls)) | 446 | if (!test_bit(syscall_nr, enabled_perf_enter_syscalls)) |
447 | return; | 447 | return; |
448 | 448 | ||
449 | sys_data = syscall_nr_to_meta(syscall_nr); | 449 | sys_data = syscall_nr_to_meta(syscall_nr); |
@@ -455,11 +455,11 @@ static void prof_syscall_enter(struct pt_regs *regs, long id) | |||
455 | size = ALIGN(size + sizeof(u32), sizeof(u64)); | 455 | size = ALIGN(size + sizeof(u32), sizeof(u64)); |
456 | size -= sizeof(u32); | 456 | size -= sizeof(u32); |
457 | 457 | ||
458 | if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, | 458 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
459 | "profile buffer not large enough")) | 459 | "perf buffer not large enough")) |
460 | return; | 460 | return; |
461 | 461 | ||
462 | rec = (struct syscall_trace_enter *)ftrace_perf_buf_prepare(size, | 462 | rec = (struct syscall_trace_enter *)perf_trace_buf_prepare(size, |
463 | sys_data->enter_event->id, &rctx, &flags); | 463 | sys_data->enter_event->id, &rctx, &flags); |
464 | if (!rec) | 464 | if (!rec) |
465 | return; | 465 | return; |
@@ -467,10 +467,10 @@ static void prof_syscall_enter(struct pt_regs *regs, long id) | |||
467 | rec->nr = syscall_nr; | 467 | rec->nr = syscall_nr; |
468 | syscall_get_arguments(current, regs, 0, sys_data->nb_args, | 468 | syscall_get_arguments(current, regs, 0, sys_data->nb_args, |
469 | (unsigned long *)&rec->args); | 469 | (unsigned long *)&rec->args); |
470 | ftrace_perf_buf_submit(rec, size, rctx, 0, 1, flags); | 470 | perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); |
471 | } | 471 | } |
472 | 472 | ||
473 | int prof_sysenter_enable(struct ftrace_event_call *call) | 473 | int perf_sysenter_enable(struct ftrace_event_call *call) |
474 | { | 474 | { |
475 | int ret = 0; | 475 | int ret = 0; |
476 | int num; | 476 | int num; |
@@ -478,34 +478,34 @@ int prof_sysenter_enable(struct ftrace_event_call *call) | |||
478 | num = ((struct syscall_metadata *)call->data)->syscall_nr; | 478 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
479 | 479 | ||
480 | mutex_lock(&syscall_trace_lock); | 480 | mutex_lock(&syscall_trace_lock); |
481 | if (!sys_prof_refcount_enter) | 481 | if (!sys_perf_refcount_enter) |
482 | ret = register_trace_sys_enter(prof_syscall_enter); | 482 | ret = register_trace_sys_enter(perf_syscall_enter); |
483 | if (ret) { | 483 | if (ret) { |
484 | pr_info("event trace: Could not activate" | 484 | pr_info("event trace: Could not activate" |
485 | "syscall entry trace point"); | 485 | "syscall entry trace point"); |
486 | } else { | 486 | } else { |
487 | set_bit(num, enabled_prof_enter_syscalls); | 487 | set_bit(num, enabled_perf_enter_syscalls); |
488 | sys_prof_refcount_enter++; | 488 | sys_perf_refcount_enter++; |
489 | } | 489 | } |
490 | mutex_unlock(&syscall_trace_lock); | 490 | mutex_unlock(&syscall_trace_lock); |
491 | return ret; | 491 | return ret; |
492 | } | 492 | } |
493 | 493 | ||
494 | void prof_sysenter_disable(struct ftrace_event_call *call) | 494 | void perf_sysenter_disable(struct ftrace_event_call *call) |
495 | { | 495 | { |
496 | int num; | 496 | int num; |
497 | 497 | ||
498 | num = ((struct syscall_metadata *)call->data)->syscall_nr; | 498 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
499 | 499 | ||
500 | mutex_lock(&syscall_trace_lock); | 500 | mutex_lock(&syscall_trace_lock); |
501 | sys_prof_refcount_enter--; | 501 | sys_perf_refcount_enter--; |
502 | clear_bit(num, enabled_prof_enter_syscalls); | 502 | clear_bit(num, enabled_perf_enter_syscalls); |
503 | if (!sys_prof_refcount_enter) | 503 | if (!sys_perf_refcount_enter) |
504 | unregister_trace_sys_enter(prof_syscall_enter); | 504 | unregister_trace_sys_enter(perf_syscall_enter); |
505 | mutex_unlock(&syscall_trace_lock); | 505 | mutex_unlock(&syscall_trace_lock); |
506 | } | 506 | } |
507 | 507 | ||
508 | static void prof_syscall_exit(struct pt_regs *regs, long ret) | 508 | static void perf_syscall_exit(struct pt_regs *regs, long ret) |
509 | { | 509 | { |
510 | struct syscall_metadata *sys_data; | 510 | struct syscall_metadata *sys_data; |
511 | struct syscall_trace_exit *rec; | 511 | struct syscall_trace_exit *rec; |
@@ -515,7 +515,7 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret) | |||
515 | int size; | 515 | int size; |
516 | 516 | ||
517 | syscall_nr = syscall_get_nr(current, regs); | 517 | syscall_nr = syscall_get_nr(current, regs); |
518 | if (!test_bit(syscall_nr, enabled_prof_exit_syscalls)) | 518 | if (!test_bit(syscall_nr, enabled_perf_exit_syscalls)) |
519 | return; | 519 | return; |
520 | 520 | ||
521 | sys_data = syscall_nr_to_meta(syscall_nr); | 521 | sys_data = syscall_nr_to_meta(syscall_nr); |
@@ -530,11 +530,11 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret) | |||
530 | * Impossible, but be paranoid with the future | 530 | * Impossible, but be paranoid with the future |
531 | * How to put this check outside runtime? | 531 | * How to put this check outside runtime? |
532 | */ | 532 | */ |
533 | if (WARN_ONCE(size > FTRACE_MAX_PROFILE_SIZE, | 533 | if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, |
534 | "exit event has grown above profile buffer size")) | 534 | "exit event has grown above perf buffer size")) |
535 | return; | 535 | return; |
536 | 536 | ||
537 | rec = (struct syscall_trace_exit *)ftrace_perf_buf_prepare(size, | 537 | rec = (struct syscall_trace_exit *)perf_trace_buf_prepare(size, |
538 | sys_data->exit_event->id, &rctx, &flags); | 538 | sys_data->exit_event->id, &rctx, &flags); |
539 | if (!rec) | 539 | if (!rec) |
540 | return; | 540 | return; |
@@ -542,10 +542,10 @@ static void prof_syscall_exit(struct pt_regs *regs, long ret) | |||
542 | rec->nr = syscall_nr; | 542 | rec->nr = syscall_nr; |
543 | rec->ret = syscall_get_return_value(current, regs); | 543 | rec->ret = syscall_get_return_value(current, regs); |
544 | 544 | ||
545 | ftrace_perf_buf_submit(rec, size, rctx, 0, 1, flags); | 545 | perf_trace_buf_submit(rec, size, rctx, 0, 1, flags, regs); |
546 | } | 546 | } |
547 | 547 | ||
548 | int prof_sysexit_enable(struct ftrace_event_call *call) | 548 | int perf_sysexit_enable(struct ftrace_event_call *call) |
549 | { | 549 | { |
550 | int ret = 0; | 550 | int ret = 0; |
551 | int num; | 551 | int num; |
@@ -553,30 +553,30 @@ int prof_sysexit_enable(struct ftrace_event_call *call) | |||
553 | num = ((struct syscall_metadata *)call->data)->syscall_nr; | 553 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
554 | 554 | ||
555 | mutex_lock(&syscall_trace_lock); | 555 | mutex_lock(&syscall_trace_lock); |
556 | if (!sys_prof_refcount_exit) | 556 | if (!sys_perf_refcount_exit) |
557 | ret = register_trace_sys_exit(prof_syscall_exit); | 557 | ret = register_trace_sys_exit(perf_syscall_exit); |
558 | if (ret) { | 558 | if (ret) { |
559 | pr_info("event trace: Could not activate" | 559 | pr_info("event trace: Could not activate" |
560 | "syscall exit trace point"); | 560 | "syscall exit trace point"); |
561 | } else { | 561 | } else { |
562 | set_bit(num, enabled_prof_exit_syscalls); | 562 | set_bit(num, enabled_perf_exit_syscalls); |
563 | sys_prof_refcount_exit++; | 563 | sys_perf_refcount_exit++; |
564 | } | 564 | } |
565 | mutex_unlock(&syscall_trace_lock); | 565 | mutex_unlock(&syscall_trace_lock); |
566 | return ret; | 566 | return ret; |
567 | } | 567 | } |
568 | 568 | ||
569 | void prof_sysexit_disable(struct ftrace_event_call *call) | 569 | void perf_sysexit_disable(struct ftrace_event_call *call) |
570 | { | 570 | { |
571 | int num; | 571 | int num; |
572 | 572 | ||
573 | num = ((struct syscall_metadata *)call->data)->syscall_nr; | 573 | num = ((struct syscall_metadata *)call->data)->syscall_nr; |
574 | 574 | ||
575 | mutex_lock(&syscall_trace_lock); | 575 | mutex_lock(&syscall_trace_lock); |
576 | sys_prof_refcount_exit--; | 576 | sys_perf_refcount_exit--; |
577 | clear_bit(num, enabled_prof_exit_syscalls); | 577 | clear_bit(num, enabled_perf_exit_syscalls); |
578 | if (!sys_prof_refcount_exit) | 578 | if (!sys_perf_refcount_exit) |
579 | unregister_trace_sys_exit(prof_syscall_exit); | 579 | unregister_trace_sys_exit(perf_syscall_exit); |
580 | mutex_unlock(&syscall_trace_lock); | 580 | mutex_unlock(&syscall_trace_lock); |
581 | } | 581 | } |
582 | 582 | ||
diff --git a/tools/perf/Documentation/Makefile b/tools/perf/Documentation/Makefile index bdd3b7ecad0a..bd498d496952 100644 --- a/tools/perf/Documentation/Makefile +++ b/tools/perf/Documentation/Makefile | |||
@@ -24,7 +24,10 @@ DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) | |||
24 | DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT)) | 24 | DOC_MAN5=$(patsubst %.txt,%.5,$(MAN5_TXT)) |
25 | DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) | 25 | DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT)) |
26 | 26 | ||
27 | # Make the path relative to DESTDIR, not prefix | ||
28 | ifndef DESTDIR | ||
27 | prefix?=$(HOME) | 29 | prefix?=$(HOME) |
30 | endif | ||
28 | bindir?=$(prefix)/bin | 31 | bindir?=$(prefix)/bin |
29 | htmldir?=$(prefix)/share/doc/perf-doc | 32 | htmldir?=$(prefix)/share/doc/perf-doc |
30 | pdfdir?=$(prefix)/share/doc/perf-doc | 33 | pdfdir?=$(prefix)/share/doc/perf-doc |
@@ -32,7 +35,6 @@ mandir?=$(prefix)/share/man | |||
32 | man1dir=$(mandir)/man1 | 35 | man1dir=$(mandir)/man1 |
33 | man5dir=$(mandir)/man5 | 36 | man5dir=$(mandir)/man5 |
34 | man7dir=$(mandir)/man7 | 37 | man7dir=$(mandir)/man7 |
35 | # DESTDIR= | ||
36 | 38 | ||
37 | ASCIIDOC=asciidoc | 39 | ASCIIDOC=asciidoc |
38 | ASCIIDOC_EXTRA = --unsafe | 40 | ASCIIDOC_EXTRA = --unsafe |
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 2d537382c686..8a8f52db7e38 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -216,7 +216,10 @@ STRIP ?= strip | |||
216 | # runtime figures out where they are based on the path to the executable. | 216 | # runtime figures out where they are based on the path to the executable. |
217 | # This can help installing the suite in a relocatable way. | 217 | # This can help installing the suite in a relocatable way. |
218 | 218 | ||
219 | # Make the path relative to DESTDIR, not to prefix | ||
220 | ifndef DESTDIR | ||
219 | prefix = $(HOME) | 221 | prefix = $(HOME) |
222 | endif | ||
220 | bindir_relative = bin | 223 | bindir_relative = bin |
221 | bindir = $(prefix)/$(bindir_relative) | 224 | bindir = $(prefix)/$(bindir_relative) |
222 | mandir = share/man | 225 | mandir = share/man |
@@ -233,7 +236,6 @@ sysconfdir = $(prefix)/etc | |||
233 | ETC_PERFCONFIG = etc/perfconfig | 236 | ETC_PERFCONFIG = etc/perfconfig |
234 | endif | 237 | endif |
235 | lib = lib | 238 | lib = lib |
236 | # DESTDIR= | ||
237 | 239 | ||
238 | export prefix bindir sharedir sysconfdir | 240 | export prefix bindir sharedir sysconfdir |
239 | 241 | ||
@@ -387,6 +389,7 @@ LIB_H += util/thread.h | |||
387 | LIB_H += util/trace-event.h | 389 | LIB_H += util/trace-event.h |
388 | LIB_H += util/probe-finder.h | 390 | LIB_H += util/probe-finder.h |
389 | LIB_H += util/probe-event.h | 391 | LIB_H += util/probe-event.h |
392 | LIB_H += util/cpumap.h | ||
390 | 393 | ||
391 | LIB_OBJS += util/abspath.o | 394 | LIB_OBJS += util/abspath.o |
392 | LIB_OBJS += util/alias.o | 395 | LIB_OBJS += util/alias.o |
@@ -433,6 +436,7 @@ LIB_OBJS += util/sort.o | |||
433 | LIB_OBJS += util/hist.o | 436 | LIB_OBJS += util/hist.o |
434 | LIB_OBJS += util/probe-event.o | 437 | LIB_OBJS += util/probe-event.o |
435 | LIB_OBJS += util/util.o | 438 | LIB_OBJS += util/util.o |
439 | LIB_OBJS += util/cpumap.o | ||
436 | 440 | ||
437 | BUILTIN_OBJS += builtin-annotate.o | 441 | BUILTIN_OBJS += builtin-annotate.o |
438 | 442 | ||
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index 5ec5de995872..6ad7148451c5 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -116,7 +116,7 @@ static int perf_session__add_hist_entry(struct perf_session *self, | |||
116 | return 0; | 116 | return 0; |
117 | } | 117 | } |
118 | 118 | ||
119 | he = __perf_session__add_hist_entry(self, al, NULL, count, &hit); | 119 | he = __perf_session__add_hist_entry(&self->hists, al, NULL, count, &hit); |
120 | if (he == NULL) | 120 | if (he == NULL) |
121 | return -ENOMEM; | 121 | return -ENOMEM; |
122 | 122 | ||
@@ -564,8 +564,8 @@ static int __cmd_annotate(void) | |||
564 | if (verbose > 2) | 564 | if (verbose > 2) |
565 | dsos__fprintf(stdout); | 565 | dsos__fprintf(stdout); |
566 | 566 | ||
567 | perf_session__collapse_resort(session); | 567 | perf_session__collapse_resort(&session->hists); |
568 | perf_session__output_resort(session, session->event_total[0]); | 568 | perf_session__output_resort(&session->hists, session->event_total[0]); |
569 | perf_session__find_annotations(session); | 569 | perf_session__find_annotations(session); |
570 | out_delete: | 570 | out_delete: |
571 | perf_session__delete(session); | 571 | perf_session__delete(session); |
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 18b3f505f9db..1ea15d8aeed1 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -26,7 +26,8 @@ static int perf_session__add_hist_entry(struct perf_session *self, | |||
26 | struct addr_location *al, u64 count) | 26 | struct addr_location *al, u64 count) |
27 | { | 27 | { |
28 | bool hit; | 28 | bool hit; |
29 | struct hist_entry *he = __perf_session__add_hist_entry(self, al, NULL, | 29 | struct hist_entry *he = __perf_session__add_hist_entry(&self->hists, |
30 | al, NULL, | ||
30 | count, &hit); | 31 | count, &hit); |
31 | if (he == NULL) | 32 | if (he == NULL) |
32 | return -ENOMEM; | 33 | return -ENOMEM; |
@@ -114,7 +115,7 @@ static void perf_session__resort_hist_entries(struct perf_session *self) | |||
114 | 115 | ||
115 | static void perf_session__set_hist_entries_positions(struct perf_session *self) | 116 | static void perf_session__set_hist_entries_positions(struct perf_session *self) |
116 | { | 117 | { |
117 | perf_session__output_resort(self, self->events_stats.total); | 118 | perf_session__output_resort(&self->hists, self->events_stats.total); |
118 | perf_session__resort_hist_entries(self); | 119 | perf_session__resort_hist_entries(self); |
119 | } | 120 | } |
120 | 121 | ||
@@ -166,13 +167,15 @@ static int __cmd_diff(void) | |||
166 | goto out_delete; | 167 | goto out_delete; |
167 | } | 168 | } |
168 | 169 | ||
169 | perf_session__output_resort(session[1], session[1]->events_stats.total); | 170 | perf_session__output_resort(&session[1]->hists, |
171 | session[1]->events_stats.total); | ||
170 | if (show_displacement) | 172 | if (show_displacement) |
171 | perf_session__set_hist_entries_positions(session[0]); | 173 | perf_session__set_hist_entries_positions(session[0]); |
172 | 174 | ||
173 | perf_session__match_hists(session[0], session[1]); | 175 | perf_session__match_hists(session[0], session[1]); |
174 | perf_session__fprintf_hists(session[1], session[0], | 176 | perf_session__fprintf_hists(&session[1]->hists, session[0], |
175 | show_displacement, stdout); | 177 | show_displacement, stdout, |
178 | session[1]->events_stats.total); | ||
176 | out_delete: | 179 | out_delete: |
177 | for (i = 0; i < 2; ++i) | 180 | for (i = 0; i < 2; ++i) |
178 | perf_session__delete(session[i]); | 181 | perf_session__delete(session[i]); |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 6e4a39328b33..bed175d59e55 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include "util/debug.h" | 22 | #include "util/debug.h" |
23 | #include "util/session.h" | 23 | #include "util/session.h" |
24 | #include "util/symbol.h" | 24 | #include "util/symbol.h" |
25 | #include "util/cpumap.h" | ||
25 | 26 | ||
26 | #include <unistd.h> | 27 | #include <unistd.h> |
27 | #include <sched.h> | 28 | #include <sched.h> |
@@ -244,6 +245,9 @@ static void create_counter(int counter, int cpu, pid_t pid) | |||
244 | 245 | ||
245 | attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; | 246 | attr->sample_type |= PERF_SAMPLE_IP | PERF_SAMPLE_TID; |
246 | 247 | ||
248 | if (nr_counters > 1) | ||
249 | attr->sample_type |= PERF_SAMPLE_ID; | ||
250 | |||
247 | if (freq) { | 251 | if (freq) { |
248 | attr->sample_type |= PERF_SAMPLE_PERIOD; | 252 | attr->sample_type |= PERF_SAMPLE_PERIOD; |
249 | attr->freq = 1; | 253 | attr->freq = 1; |
@@ -392,6 +396,9 @@ static int process_buildids(void) | |||
392 | { | 396 | { |
393 | u64 size = lseek(output, 0, SEEK_CUR); | 397 | u64 size = lseek(output, 0, SEEK_CUR); |
394 | 398 | ||
399 | if (size == 0) | ||
400 | return 0; | ||
401 | |||
395 | session->fd = output; | 402 | session->fd = output; |
396 | return __perf_session__process_events(session, post_processing_offset, | 403 | return __perf_session__process_events(session, post_processing_offset, |
397 | size - post_processing_offset, | 404 | size - post_processing_offset, |
@@ -419,9 +426,6 @@ static int __cmd_record(int argc, const char **argv) | |||
419 | char buf; | 426 | char buf; |
420 | 427 | ||
421 | page_size = sysconf(_SC_PAGE_SIZE); | 428 | page_size = sysconf(_SC_PAGE_SIZE); |
422 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | ||
423 | assert(nr_cpus <= MAX_NR_CPUS); | ||
424 | assert(nr_cpus >= 0); | ||
425 | 429 | ||
426 | atexit(sig_atexit); | 430 | atexit(sig_atexit); |
427 | signal(SIGCHLD, sig_handler); | 431 | signal(SIGCHLD, sig_handler); |
@@ -545,8 +549,9 @@ static int __cmd_record(int argc, const char **argv) | |||
545 | if ((!system_wide && !inherit) || profile_cpu != -1) { | 549 | if ((!system_wide && !inherit) || profile_cpu != -1) { |
546 | open_counters(profile_cpu, target_pid); | 550 | open_counters(profile_cpu, target_pid); |
547 | } else { | 551 | } else { |
552 | nr_cpus = read_cpu_map(); | ||
548 | for (i = 0; i < nr_cpus; i++) | 553 | for (i = 0; i < nr_cpus; i++) |
549 | open_counters(i, target_pid); | 554 | open_counters(cpumap[i], target_pid); |
550 | } | 555 | } |
551 | 556 | ||
552 | if (file_new) { | 557 | if (file_new) { |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index cfc655d40bb7..f815de25d0fc 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -45,28 +45,71 @@ static char *pretty_printing_style = default_pretty_printing_style; | |||
45 | 45 | ||
46 | static char callchain_default_opt[] = "fractal,0.5"; | 46 | static char callchain_default_opt[] = "fractal,0.5"; |
47 | 47 | ||
48 | static struct event_stat_id *get_stats(struct perf_session *self, | ||
49 | u64 event_stream, u32 type, u64 config) | ||
50 | { | ||
51 | struct rb_node **p = &self->stats_by_id.rb_node; | ||
52 | struct rb_node *parent = NULL; | ||
53 | struct event_stat_id *iter, *new; | ||
54 | |||
55 | while (*p != NULL) { | ||
56 | parent = *p; | ||
57 | iter = rb_entry(parent, struct event_stat_id, rb_node); | ||
58 | if (iter->config == config) | ||
59 | return iter; | ||
60 | |||
61 | |||
62 | if (config > iter->config) | ||
63 | p = &(*p)->rb_right; | ||
64 | else | ||
65 | p = &(*p)->rb_left; | ||
66 | } | ||
67 | |||
68 | new = malloc(sizeof(struct event_stat_id)); | ||
69 | if (new == NULL) | ||
70 | return NULL; | ||
71 | memset(new, 0, sizeof(struct event_stat_id)); | ||
72 | new->event_stream = event_stream; | ||
73 | new->config = config; | ||
74 | new->type = type; | ||
75 | rb_link_node(&new->rb_node, parent, p); | ||
76 | rb_insert_color(&new->rb_node, &self->stats_by_id); | ||
77 | return new; | ||
78 | } | ||
79 | |||
48 | static int perf_session__add_hist_entry(struct perf_session *self, | 80 | static int perf_session__add_hist_entry(struct perf_session *self, |
49 | struct addr_location *al, | 81 | struct addr_location *al, |
50 | struct ip_callchain *chain, u64 count) | 82 | struct sample_data *data) |
51 | { | 83 | { |
52 | struct symbol **syms = NULL, *parent = NULL; | 84 | struct symbol **syms = NULL, *parent = NULL; |
53 | bool hit; | 85 | bool hit; |
54 | struct hist_entry *he; | 86 | struct hist_entry *he; |
87 | struct event_stat_id *stats; | ||
88 | struct perf_event_attr *attr; | ||
55 | 89 | ||
56 | if ((sort__has_parent || symbol_conf.use_callchain) && chain) | 90 | if ((sort__has_parent || symbol_conf.use_callchain) && data->callchain) |
57 | syms = perf_session__resolve_callchain(self, al->thread, | 91 | syms = perf_session__resolve_callchain(self, al->thread, |
58 | chain, &parent); | 92 | data->callchain, &parent); |
59 | he = __perf_session__add_hist_entry(self, al, parent, count, &hit); | 93 | |
94 | attr = perf_header__find_attr(data->id, &self->header); | ||
95 | if (attr) | ||
96 | stats = get_stats(self, data->id, attr->type, attr->config); | ||
97 | else | ||
98 | stats = get_stats(self, data->id, 0, 0); | ||
99 | if (stats == NULL) | ||
100 | return -ENOMEM; | ||
101 | he = __perf_session__add_hist_entry(&stats->hists, al, parent, | ||
102 | data->period, &hit); | ||
60 | if (he == NULL) | 103 | if (he == NULL) |
61 | return -ENOMEM; | 104 | return -ENOMEM; |
62 | 105 | ||
63 | if (hit) | 106 | if (hit) |
64 | he->count += count; | 107 | he->count += data->period; |
65 | 108 | ||
66 | if (symbol_conf.use_callchain) { | 109 | if (symbol_conf.use_callchain) { |
67 | if (!hit) | 110 | if (!hit) |
68 | callchain_init(&he->callchain); | 111 | callchain_init(&he->callchain); |
69 | append_chain(&he->callchain, chain, syms); | 112 | append_chain(&he->callchain, data->callchain, syms); |
70 | free(syms); | 113 | free(syms); |
71 | } | 114 | } |
72 | 115 | ||
@@ -86,10 +129,30 @@ static int validate_chain(struct ip_callchain *chain, event_t *event) | |||
86 | return 0; | 129 | return 0; |
87 | } | 130 | } |
88 | 131 | ||
132 | static int add_event_total(struct perf_session *session, | ||
133 | struct sample_data *data, | ||
134 | struct perf_event_attr *attr) | ||
135 | { | ||
136 | struct event_stat_id *stats; | ||
137 | |||
138 | if (attr) | ||
139 | stats = get_stats(session, data->id, attr->type, attr->config); | ||
140 | else | ||
141 | stats = get_stats(session, data->id, 0, 0); | ||
142 | |||
143 | if (!stats) | ||
144 | return -ENOMEM; | ||
145 | |||
146 | stats->stats.total += data->period; | ||
147 | session->events_stats.total += data->period; | ||
148 | return 0; | ||
149 | } | ||
150 | |||
89 | static int process_sample_event(event_t *event, struct perf_session *session) | 151 | static int process_sample_event(event_t *event, struct perf_session *session) |
90 | { | 152 | { |
91 | struct sample_data data = { .period = 1, }; | 153 | struct sample_data data = { .period = 1, }; |
92 | struct addr_location al; | 154 | struct addr_location al; |
155 | struct perf_event_attr *attr; | ||
93 | 156 | ||
94 | event__parse_sample(event, session->sample_type, &data); | 157 | event__parse_sample(event, session->sample_type, &data); |
95 | 158 | ||
@@ -123,12 +186,18 @@ static int process_sample_event(event_t *event, struct perf_session *session) | |||
123 | if (al.filtered || (hide_unresolved && al.sym == NULL)) | 186 | if (al.filtered || (hide_unresolved && al.sym == NULL)) |
124 | return 0; | 187 | return 0; |
125 | 188 | ||
126 | if (perf_session__add_hist_entry(session, &al, data.callchain, data.period)) { | 189 | if (perf_session__add_hist_entry(session, &al, &data)) { |
127 | pr_debug("problem incrementing symbol count, skipping event\n"); | 190 | pr_debug("problem incrementing symbol count, skipping event\n"); |
128 | return -1; | 191 | return -1; |
129 | } | 192 | } |
130 | 193 | ||
131 | session->events_stats.total += data.period; | 194 | attr = perf_header__find_attr(data.id, &session->header); |
195 | |||
196 | if (add_event_total(session, &data, attr)) { | ||
197 | pr_debug("problem adding event count\n"); | ||
198 | return -1; | ||
199 | } | ||
200 | |||
132 | return 0; | 201 | return 0; |
133 | } | 202 | } |
134 | 203 | ||
@@ -197,6 +266,7 @@ static int __cmd_report(void) | |||
197 | { | 266 | { |
198 | int ret = -EINVAL; | 267 | int ret = -EINVAL; |
199 | struct perf_session *session; | 268 | struct perf_session *session; |
269 | struct rb_node *next; | ||
200 | 270 | ||
201 | session = perf_session__new(input_name, O_RDONLY, force); | 271 | session = perf_session__new(input_name, O_RDONLY, force); |
202 | if (session == NULL) | 272 | if (session == NULL) |
@@ -224,10 +294,28 @@ static int __cmd_report(void) | |||
224 | if (verbose > 2) | 294 | if (verbose > 2) |
225 | dsos__fprintf(stdout); | 295 | dsos__fprintf(stdout); |
226 | 296 | ||
227 | perf_session__collapse_resort(session); | 297 | next = rb_first(&session->stats_by_id); |
228 | perf_session__output_resort(session, session->events_stats.total); | 298 | while (next) { |
229 | fprintf(stdout, "# Samples: %Ld\n#\n", session->events_stats.total); | 299 | struct event_stat_id *stats; |
230 | perf_session__fprintf_hists(session, NULL, false, stdout); | 300 | |
301 | stats = rb_entry(next, struct event_stat_id, rb_node); | ||
302 | perf_session__collapse_resort(&stats->hists); | ||
303 | perf_session__output_resort(&stats->hists, stats->stats.total); | ||
304 | if (rb_first(&session->stats_by_id) == | ||
305 | rb_last(&session->stats_by_id)) | ||
306 | fprintf(stdout, "# Samples: %Ld\n#\n", | ||
307 | stats->stats.total); | ||
308 | else | ||
309 | fprintf(stdout, "# Samples: %Ld %s\n#\n", | ||
310 | stats->stats.total, | ||
311 | __event_name(stats->type, stats->config)); | ||
312 | |||
313 | perf_session__fprintf_hists(&stats->hists, NULL, false, stdout, | ||
314 | stats->stats.total); | ||
315 | fprintf(stdout, "\n\n"); | ||
316 | next = rb_next(&stats->rb_node); | ||
317 | } | ||
318 | |||
231 | if (sort_order == default_sort_order && | 319 | if (sort_order == default_sort_order && |
232 | parent_pattern == default_parent_pattern) | 320 | parent_pattern == default_parent_pattern) |
233 | fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n"); | 321 | fprintf(stdout, "#\n# (For a higher level overview, try: perf report --sort comm,dso)\n#\n"); |
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index e8c85d5aec41..95db31cff6fd 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c | |||
@@ -45,6 +45,7 @@ | |||
45 | #include "util/event.h" | 45 | #include "util/event.h" |
46 | #include "util/debug.h" | 46 | #include "util/debug.h" |
47 | #include "util/header.h" | 47 | #include "util/header.h" |
48 | #include "util/cpumap.h" | ||
48 | 49 | ||
49 | #include <sys/prctl.h> | 50 | #include <sys/prctl.h> |
50 | #include <math.h> | 51 | #include <math.h> |
@@ -151,7 +152,7 @@ static void create_perf_stat_counter(int counter, int pid) | |||
151 | unsigned int cpu; | 152 | unsigned int cpu; |
152 | 153 | ||
153 | for (cpu = 0; cpu < nr_cpus; cpu++) { | 154 | for (cpu = 0; cpu < nr_cpus; cpu++) { |
154 | fd[cpu][counter] = sys_perf_event_open(attr, -1, cpu, -1, 0); | 155 | fd[cpu][counter] = sys_perf_event_open(attr, -1, cpumap[cpu], -1, 0); |
155 | if (fd[cpu][counter] < 0 && verbose) | 156 | if (fd[cpu][counter] < 0 && verbose) |
156 | fprintf(stderr, ERR_PERF_OPEN, counter, | 157 | fprintf(stderr, ERR_PERF_OPEN, counter, |
157 | fd[cpu][counter], strerror(errno)); | 158 | fd[cpu][counter], strerror(errno)); |
@@ -519,9 +520,10 @@ int cmd_stat(int argc, const char **argv, const char *prefix __used) | |||
519 | nr_counters = ARRAY_SIZE(default_attrs); | 520 | nr_counters = ARRAY_SIZE(default_attrs); |
520 | } | 521 | } |
521 | 522 | ||
522 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | 523 | if (system_wide) |
523 | assert(nr_cpus <= MAX_NR_CPUS); | 524 | nr_cpus = read_cpu_map(); |
524 | assert((int)nr_cpus >= 0); | 525 | else |
526 | nr_cpus = 1; | ||
525 | 527 | ||
526 | /* | 528 | /* |
527 | * We dont want to block the signals - that would cause | 529 | * We dont want to block the signals - that would cause |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index c051833f755c..ec4822322abd 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/rbtree.h> | 28 | #include <linux/rbtree.h> |
29 | #include "util/parse-options.h" | 29 | #include "util/parse-options.h" |
30 | #include "util/parse-events.h" | 30 | #include "util/parse-events.h" |
31 | #include "util/cpumap.h" | ||
31 | 32 | ||
32 | #include "util/debug.h" | 33 | #include "util/debug.h" |
33 | 34 | ||
@@ -1129,7 +1130,7 @@ static void start_counter(int i, int counter) | |||
1129 | 1130 | ||
1130 | cpu = profile_cpu; | 1131 | cpu = profile_cpu; |
1131 | if (target_pid == -1 && profile_cpu == -1) | 1132 | if (target_pid == -1 && profile_cpu == -1) |
1132 | cpu = i; | 1133 | cpu = cpumap[i]; |
1133 | 1134 | ||
1134 | attr = attrs + counter; | 1135 | attr = attrs + counter; |
1135 | 1136 | ||
@@ -1353,12 +1354,10 @@ int cmd_top(int argc, const char **argv, const char *prefix __used) | |||
1353 | attrs[counter].sample_period = default_interval; | 1354 | attrs[counter].sample_period = default_interval; |
1354 | } | 1355 | } |
1355 | 1356 | ||
1356 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | ||
1357 | assert(nr_cpus <= MAX_NR_CPUS); | ||
1358 | assert(nr_cpus >= 0); | ||
1359 | |||
1360 | if (target_pid != -1 || profile_cpu != -1) | 1357 | if (target_pid != -1 || profile_cpu != -1) |
1361 | nr_cpus = 1; | 1358 | nr_cpus = 1; |
1359 | else | ||
1360 | nr_cpus = read_cpu_map(); | ||
1362 | 1361 | ||
1363 | get_term_dimensions(&winsize); | 1362 | get_term_dimensions(&winsize); |
1364 | if (print_entries == 0) { | 1363 | if (print_entries == 0) { |
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c new file mode 100644 index 000000000000..4e01490e51e5 --- /dev/null +++ b/tools/perf/util/cpumap.c | |||
@@ -0,0 +1,59 @@ | |||
1 | #include "util.h" | ||
2 | #include "../perf.h" | ||
3 | #include "cpumap.h" | ||
4 | #include <assert.h> | ||
5 | #include <stdio.h> | ||
6 | |||
7 | int cpumap[MAX_NR_CPUS]; | ||
8 | |||
9 | static int default_cpu_map(void) | ||
10 | { | ||
11 | int nr_cpus, i; | ||
12 | |||
13 | nr_cpus = sysconf(_SC_NPROCESSORS_ONLN); | ||
14 | assert(nr_cpus <= MAX_NR_CPUS); | ||
15 | assert((int)nr_cpus >= 0); | ||
16 | |||
17 | for (i = 0; i < nr_cpus; ++i) | ||
18 | cpumap[i] = i; | ||
19 | |||
20 | return nr_cpus; | ||
21 | } | ||
22 | |||
23 | int read_cpu_map(void) | ||
24 | { | ||
25 | FILE *onlnf; | ||
26 | int nr_cpus = 0; | ||
27 | int n, cpu, prev; | ||
28 | char sep; | ||
29 | |||
30 | onlnf = fopen("/sys/devices/system/cpu/online", "r"); | ||
31 | if (!onlnf) | ||
32 | return default_cpu_map(); | ||
33 | |||
34 | sep = 0; | ||
35 | prev = -1; | ||
36 | for (;;) { | ||
37 | n = fscanf(onlnf, "%u%c", &cpu, &sep); | ||
38 | if (n <= 0) | ||
39 | break; | ||
40 | if (prev >= 0) { | ||
41 | assert(nr_cpus + cpu - prev - 1 < MAX_NR_CPUS); | ||
42 | while (++prev < cpu) | ||
43 | cpumap[nr_cpus++] = prev; | ||
44 | } | ||
45 | assert (nr_cpus < MAX_NR_CPUS); | ||
46 | cpumap[nr_cpus++] = cpu; | ||
47 | if (n == 2 && sep == '-') | ||
48 | prev = cpu; | ||
49 | else | ||
50 | prev = -1; | ||
51 | if (n == 1 || sep == '\n') | ||
52 | break; | ||
53 | } | ||
54 | fclose(onlnf); | ||
55 | if (nr_cpus > 0) | ||
56 | return nr_cpus; | ||
57 | |||
58 | return default_cpu_map(); | ||
59 | } | ||
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h new file mode 100644 index 000000000000..86c78bb33098 --- /dev/null +++ b/tools/perf/util/cpumap.h | |||
@@ -0,0 +1,7 @@ | |||
1 | #ifndef __PERF_CPUMAP_H | ||
2 | #define __PERF_CPUMAP_H | ||
3 | |||
4 | extern int read_cpu_map(void); | ||
5 | extern int cpumap[]; | ||
6 | |||
7 | #endif /* __PERF_CPUMAP_H */ | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 50a7132887f5..a33b94952e34 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -99,6 +99,15 @@ struct events_stats { | |||
99 | u64 lost; | 99 | u64 lost; |
100 | }; | 100 | }; |
101 | 101 | ||
102 | struct event_stat_id { | ||
103 | struct rb_node rb_node; | ||
104 | struct rb_root hists; | ||
105 | struct events_stats stats; | ||
106 | u64 config; | ||
107 | u64 event_stream; | ||
108 | u32 type; | ||
109 | }; | ||
110 | |||
102 | void event__print_totals(void); | 111 | void event__print_totals(void); |
103 | 112 | ||
104 | struct perf_session; | 113 | struct perf_session; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index e8daf5ca6fd2..bdcfd6190b21 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -12,12 +12,12 @@ struct callchain_param callchain_param = { | |||
12 | * histogram, sorted on item, collects counts | 12 | * histogram, sorted on item, collects counts |
13 | */ | 13 | */ |
14 | 14 | ||
15 | struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self, | 15 | struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, |
16 | struct addr_location *al, | 16 | struct addr_location *al, |
17 | struct symbol *sym_parent, | 17 | struct symbol *sym_parent, |
18 | u64 count, bool *hit) | 18 | u64 count, bool *hit) |
19 | { | 19 | { |
20 | struct rb_node **p = &self->hists.rb_node; | 20 | struct rb_node **p = &hists->rb_node; |
21 | struct rb_node *parent = NULL; | 21 | struct rb_node *parent = NULL; |
22 | struct hist_entry *he; | 22 | struct hist_entry *he; |
23 | struct hist_entry entry = { | 23 | struct hist_entry entry = { |
@@ -53,7 +53,7 @@ struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self, | |||
53 | return NULL; | 53 | return NULL; |
54 | *he = entry; | 54 | *he = entry; |
55 | rb_link_node(&he->rb_node, parent, p); | 55 | rb_link_node(&he->rb_node, parent, p); |
56 | rb_insert_color(&he->rb_node, &self->hists); | 56 | rb_insert_color(&he->rb_node, hists); |
57 | *hit = false; | 57 | *hit = false; |
58 | return he; | 58 | return he; |
59 | } | 59 | } |
@@ -130,7 +130,7 @@ static void collapse__insert_entry(struct rb_root *root, struct hist_entry *he) | |||
130 | rb_insert_color(&he->rb_node, root); | 130 | rb_insert_color(&he->rb_node, root); |
131 | } | 131 | } |
132 | 132 | ||
133 | void perf_session__collapse_resort(struct perf_session *self) | 133 | void perf_session__collapse_resort(struct rb_root *hists) |
134 | { | 134 | { |
135 | struct rb_root tmp; | 135 | struct rb_root tmp; |
136 | struct rb_node *next; | 136 | struct rb_node *next; |
@@ -140,17 +140,17 @@ void perf_session__collapse_resort(struct perf_session *self) | |||
140 | return; | 140 | return; |
141 | 141 | ||
142 | tmp = RB_ROOT; | 142 | tmp = RB_ROOT; |
143 | next = rb_first(&self->hists); | 143 | next = rb_first(hists); |
144 | 144 | ||
145 | while (next) { | 145 | while (next) { |
146 | n = rb_entry(next, struct hist_entry, rb_node); | 146 | n = rb_entry(next, struct hist_entry, rb_node); |
147 | next = rb_next(&n->rb_node); | 147 | next = rb_next(&n->rb_node); |
148 | 148 | ||
149 | rb_erase(&n->rb_node, &self->hists); | 149 | rb_erase(&n->rb_node, hists); |
150 | collapse__insert_entry(&tmp, n); | 150 | collapse__insert_entry(&tmp, n); |
151 | } | 151 | } |
152 | 152 | ||
153 | self->hists = tmp; | 153 | *hists = tmp; |
154 | } | 154 | } |
155 | 155 | ||
156 | /* | 156 | /* |
@@ -183,7 +183,7 @@ static void perf_session__insert_output_hist_entry(struct rb_root *root, | |||
183 | rb_insert_color(&he->rb_node, root); | 183 | rb_insert_color(&he->rb_node, root); |
184 | } | 184 | } |
185 | 185 | ||
186 | void perf_session__output_resort(struct perf_session *self, u64 total_samples) | 186 | void perf_session__output_resort(struct rb_root *hists, u64 total_samples) |
187 | { | 187 | { |
188 | struct rb_root tmp; | 188 | struct rb_root tmp; |
189 | struct rb_node *next; | 189 | struct rb_node *next; |
@@ -194,18 +194,18 @@ void perf_session__output_resort(struct perf_session *self, u64 total_samples) | |||
194 | total_samples * (callchain_param.min_percent / 100); | 194 | total_samples * (callchain_param.min_percent / 100); |
195 | 195 | ||
196 | tmp = RB_ROOT; | 196 | tmp = RB_ROOT; |
197 | next = rb_first(&self->hists); | 197 | next = rb_first(hists); |
198 | 198 | ||
199 | while (next) { | 199 | while (next) { |
200 | n = rb_entry(next, struct hist_entry, rb_node); | 200 | n = rb_entry(next, struct hist_entry, rb_node); |
201 | next = rb_next(&n->rb_node); | 201 | next = rb_next(&n->rb_node); |
202 | 202 | ||
203 | rb_erase(&n->rb_node, &self->hists); | 203 | rb_erase(&n->rb_node, hists); |
204 | perf_session__insert_output_hist_entry(&tmp, n, | 204 | perf_session__insert_output_hist_entry(&tmp, n, |
205 | min_callchain_hits); | 205 | min_callchain_hits); |
206 | } | 206 | } |
207 | 207 | ||
208 | self->hists = tmp; | 208 | *hists = tmp; |
209 | } | 209 | } |
210 | 210 | ||
211 | static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) | 211 | static size_t callchain__fprintf_left_margin(FILE *fp, int left_margin) |
@@ -456,10 +456,10 @@ static size_t hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self, | |||
456 | } | 456 | } |
457 | 457 | ||
458 | static size_t hist_entry__fprintf(struct hist_entry *self, | 458 | static size_t hist_entry__fprintf(struct hist_entry *self, |
459 | struct perf_session *session, | ||
460 | struct perf_session *pair_session, | 459 | struct perf_session *pair_session, |
461 | bool show_displacement, | 460 | bool show_displacement, |
462 | long displacement, FILE *fp) | 461 | long displacement, FILE *fp, |
462 | u64 session_total) | ||
463 | { | 463 | { |
464 | struct sort_entry *se; | 464 | struct sort_entry *se; |
465 | u64 count, total; | 465 | u64 count, total; |
@@ -474,7 +474,7 @@ static size_t hist_entry__fprintf(struct hist_entry *self, | |||
474 | total = pair_session->events_stats.total; | 474 | total = pair_session->events_stats.total; |
475 | } else { | 475 | } else { |
476 | count = self->count; | 476 | count = self->count; |
477 | total = session->events_stats.total; | 477 | total = session_total; |
478 | } | 478 | } |
479 | 479 | ||
480 | if (total) | 480 | if (total) |
@@ -496,8 +496,8 @@ static size_t hist_entry__fprintf(struct hist_entry *self, | |||
496 | 496 | ||
497 | if (total > 0) | 497 | if (total > 0) |
498 | old_percent = (count * 100.0) / total; | 498 | old_percent = (count * 100.0) / total; |
499 | if (session->events_stats.total > 0) | 499 | if (session_total > 0) |
500 | new_percent = (self->count * 100.0) / session->events_stats.total; | 500 | new_percent = (self->count * 100.0) / session_total; |
501 | 501 | ||
502 | diff = new_percent - old_percent; | 502 | diff = new_percent - old_percent; |
503 | 503 | ||
@@ -544,16 +544,17 @@ static size_t hist_entry__fprintf(struct hist_entry *self, | |||
544 | left_margin -= thread__comm_len(self->thread); | 544 | left_margin -= thread__comm_len(self->thread); |
545 | } | 545 | } |
546 | 546 | ||
547 | hist_entry_callchain__fprintf(fp, self, session->events_stats.total, | 547 | hist_entry_callchain__fprintf(fp, self, session_total, |
548 | left_margin); | 548 | left_margin); |
549 | } | 549 | } |
550 | 550 | ||
551 | return ret; | 551 | return ret; |
552 | } | 552 | } |
553 | 553 | ||
554 | size_t perf_session__fprintf_hists(struct perf_session *self, | 554 | size_t perf_session__fprintf_hists(struct rb_root *hists, |
555 | struct perf_session *pair, | 555 | struct perf_session *pair, |
556 | bool show_displacement, FILE *fp) | 556 | bool show_displacement, FILE *fp, |
557 | u64 session_total) | ||
557 | { | 558 | { |
558 | struct sort_entry *se; | 559 | struct sort_entry *se; |
559 | struct rb_node *nd; | 560 | struct rb_node *nd; |
@@ -641,7 +642,7 @@ size_t perf_session__fprintf_hists(struct perf_session *self, | |||
641 | fprintf(fp, "\n#\n"); | 642 | fprintf(fp, "\n#\n"); |
642 | 643 | ||
643 | print_entries: | 644 | print_entries: |
644 | for (nd = rb_first(&self->hists); nd; nd = rb_next(nd)) { | 645 | for (nd = rb_first(hists); nd; nd = rb_next(nd)) { |
645 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); | 646 | struct hist_entry *h = rb_entry(nd, struct hist_entry, rb_node); |
646 | 647 | ||
647 | if (show_displacement) { | 648 | if (show_displacement) { |
@@ -652,8 +653,13 @@ print_entries: | |||
652 | displacement = 0; | 653 | displacement = 0; |
653 | ++position; | 654 | ++position; |
654 | } | 655 | } |
655 | ret += hist_entry__fprintf(h, self, pair, show_displacement, | 656 | ret += hist_entry__fprintf(h, pair, show_displacement, |
656 | displacement, fp); | 657 | displacement, fp, session_total); |
658 | if (h->map == NULL && verbose > 1) { | ||
659 | __map_groups__fprintf_maps(&h->thread->mg, | ||
660 | MAP__FUNCTION, fp); | ||
661 | fprintf(fp, "%.10s end\n", graph_dotted_line); | ||
662 | } | ||
657 | } | 663 | } |
658 | 664 | ||
659 | free(rem_sq_bracket); | 665 | free(rem_sq_bracket); |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index e5f99b24048b..16f360cce5bf 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -10,8 +10,9 @@ struct perf_session; | |||
10 | struct hist_entry; | 10 | struct hist_entry; |
11 | struct addr_location; | 11 | struct addr_location; |
12 | struct symbol; | 12 | struct symbol; |
13 | struct rb_root; | ||
13 | 14 | ||
14 | struct hist_entry *__perf_session__add_hist_entry(struct perf_session *self, | 15 | struct hist_entry *__perf_session__add_hist_entry(struct rb_root *hists, |
15 | struct addr_location *al, | 16 | struct addr_location *al, |
16 | struct symbol *parent, | 17 | struct symbol *parent, |
17 | u64 count, bool *hit); | 18 | u64 count, bool *hit); |
@@ -19,9 +20,10 @@ extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); | |||
19 | extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); | 20 | extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); |
20 | void hist_entry__free(struct hist_entry *); | 21 | void hist_entry__free(struct hist_entry *); |
21 | 22 | ||
22 | void perf_session__output_resort(struct perf_session *self, u64 total_samples); | 23 | void perf_session__output_resort(struct rb_root *hists, u64 total_samples); |
23 | void perf_session__collapse_resort(struct perf_session *self); | 24 | void perf_session__collapse_resort(struct rb_root *hists); |
24 | size_t perf_session__fprintf_hists(struct perf_session *self, | 25 | size_t perf_session__fprintf_hists(struct rb_root *hists, |
25 | struct perf_session *pair, | 26 | struct perf_session *pair, |
26 | bool show_displacement, FILE *fp); | 27 | bool show_displacement, FILE *fp, |
28 | u64 session_total); | ||
27 | #endif /* __PERF_HIST_H */ | 29 | #endif /* __PERF_HIST_H */ |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index e77dc886760e..1e6c65ebbd80 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -169,7 +169,7 @@ static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) | |||
169 | { | 169 | { |
170 | Dwarf_Files *files; | 170 | Dwarf_Files *files; |
171 | size_t nfiles, i; | 171 | size_t nfiles, i; |
172 | const char *src; | 172 | const char *src = NULL; |
173 | int ret; | 173 | int ret; |
174 | 174 | ||
175 | if (!fname) | 175 | if (!fname) |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index 0de7258e70a5..eed1cb889008 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -70,6 +70,7 @@ struct perf_session *perf_session__new(const char *filename, int mode, bool forc | |||
70 | 70 | ||
71 | memcpy(self->filename, filename, len); | 71 | memcpy(self->filename, filename, len); |
72 | self->threads = RB_ROOT; | 72 | self->threads = RB_ROOT; |
73 | self->stats_by_id = RB_ROOT; | ||
73 | self->last_match = NULL; | 74 | self->last_match = NULL; |
74 | self->mmap_window = 32; | 75 | self->mmap_window = 32; |
75 | self->cwd = NULL; | 76 | self->cwd = NULL; |
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h index 31950fcd8a4d..5c33417eebb3 100644 --- a/tools/perf/util/session.h +++ b/tools/perf/util/session.h | |||
@@ -20,6 +20,7 @@ struct perf_session { | |||
20 | struct thread *last_match; | 20 | struct thread *last_match; |
21 | struct map *vmlinux_maps[MAP__NR_TYPES]; | 21 | struct map *vmlinux_maps[MAP__NR_TYPES]; |
22 | struct events_stats events_stats; | 22 | struct events_stats events_stats; |
23 | struct rb_root stats_by_id; | ||
23 | unsigned long event_total[PERF_RECORD_MAX]; | 24 | unsigned long event_total[PERF_RECORD_MAX]; |
24 | unsigned long unknown_events; | 25 | unsigned long unknown_events; |
25 | struct rb_root hists; | 26 | struct rb_root hists; |
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index 21b92162282b..fa968312ee7d 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c | |||
@@ -79,8 +79,8 @@ int thread__comm_len(struct thread *self) | |||
79 | return self->comm_len; | 79 | return self->comm_len; |
80 | } | 80 | } |
81 | 81 | ||
82 | static size_t __map_groups__fprintf_maps(struct map_groups *self, | 82 | size_t __map_groups__fprintf_maps(struct map_groups *self, |
83 | enum map_type type, FILE *fp) | 83 | enum map_type type, FILE *fp) |
84 | { | 84 | { |
85 | size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); | 85 | size_t printed = fprintf(fp, "%s:\n", map_type__name[type]); |
86 | struct rb_node *nd; | 86 | struct rb_node *nd; |
@@ -89,7 +89,7 @@ static size_t __map_groups__fprintf_maps(struct map_groups *self, | |||
89 | struct map *pos = rb_entry(nd, struct map, rb_node); | 89 | struct map *pos = rb_entry(nd, struct map, rb_node); |
90 | printed += fprintf(fp, "Map:"); | 90 | printed += fprintf(fp, "Map:"); |
91 | printed += map__fprintf(pos, fp); | 91 | printed += map__fprintf(pos, fp); |
92 | if (verbose > 1) { | 92 | if (verbose > 2) { |
93 | printed += dso__fprintf(pos->dso, type, fp); | 93 | printed += dso__fprintf(pos->dso, type, fp); |
94 | printed += fprintf(fp, "--\n"); | 94 | printed += fprintf(fp, "--\n"); |
95 | } | 95 | } |
@@ -183,8 +183,8 @@ struct thread *perf_session__findnew(struct perf_session *self, pid_t pid) | |||
183 | return th; | 183 | return th; |
184 | } | 184 | } |
185 | 185 | ||
186 | static void map_groups__remove_overlappings(struct map_groups *self, | 186 | static int map_groups__fixup_overlappings(struct map_groups *self, |
187 | struct map *map) | 187 | struct map *map) |
188 | { | 188 | { |
189 | struct rb_root *root = &self->maps[map->type]; | 189 | struct rb_root *root = &self->maps[map->type]; |
190 | struct rb_node *next = rb_first(root); | 190 | struct rb_node *next = rb_first(root); |
@@ -209,7 +209,36 @@ static void map_groups__remove_overlappings(struct map_groups *self, | |||
209 | * list. | 209 | * list. |
210 | */ | 210 | */ |
211 | list_add_tail(&pos->node, &self->removed_maps[map->type]); | 211 | list_add_tail(&pos->node, &self->removed_maps[map->type]); |
212 | /* | ||
213 | * Now check if we need to create new maps for areas not | ||
214 | * overlapped by the new map: | ||
215 | */ | ||
216 | if (map->start > pos->start) { | ||
217 | struct map *before = map__clone(pos); | ||
218 | |||
219 | if (before == NULL) | ||
220 | return -ENOMEM; | ||
221 | |||
222 | before->end = map->start - 1; | ||
223 | map_groups__insert(self, before); | ||
224 | if (verbose >= 2) | ||
225 | map__fprintf(before, stderr); | ||
226 | } | ||
227 | |||
228 | if (map->end < pos->end) { | ||
229 | struct map *after = map__clone(pos); | ||
230 | |||
231 | if (after == NULL) | ||
232 | return -ENOMEM; | ||
233 | |||
234 | after->start = map->end + 1; | ||
235 | map_groups__insert(self, after); | ||
236 | if (verbose >= 2) | ||
237 | map__fprintf(after, stderr); | ||
238 | } | ||
212 | } | 239 | } |
240 | |||
241 | return 0; | ||
213 | } | 242 | } |
214 | 243 | ||
215 | void maps__insert(struct rb_root *maps, struct map *map) | 244 | void maps__insert(struct rb_root *maps, struct map *map) |
@@ -254,7 +283,7 @@ struct map *maps__find(struct rb_root *maps, u64 ip) | |||
254 | 283 | ||
255 | void thread__insert_map(struct thread *self, struct map *map) | 284 | void thread__insert_map(struct thread *self, struct map *map) |
256 | { | 285 | { |
257 | map_groups__remove_overlappings(&self->mg, map); | 286 | map_groups__fixup_overlappings(&self->mg, map); |
258 | map_groups__insert(&self->mg, map); | 287 | map_groups__insert(&self->mg, map); |
259 | } | 288 | } |
260 | 289 | ||
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h index 0a28f39de545..dcf70303e58e 100644 --- a/tools/perf/util/thread.h +++ b/tools/perf/util/thread.h | |||
@@ -10,6 +10,9 @@ struct map_groups { | |||
10 | struct list_head removed_maps[MAP__NR_TYPES]; | 10 | struct list_head removed_maps[MAP__NR_TYPES]; |
11 | }; | 11 | }; |
12 | 12 | ||
13 | size_t __map_groups__fprintf_maps(struct map_groups *self, | ||
14 | enum map_type type, FILE *fp); | ||
15 | |||
13 | struct thread { | 16 | struct thread { |
14 | struct rb_node rb_node; | 17 | struct rb_node rb_node; |
15 | struct map_groups mg; | 18 | struct map_groups mg; |