History

Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull perf updates from Ingo Molnar: "Bigger kernel side changes: - Add backwards writing capability to the perf ring-buffer code, which is preparation for future advanced features like robust 'overwrite support' and snapshot mode. (Wang Nan) - Add pause and resume ioctls for the perf ringbuffer (Wang Nan) - x86 Intel cstate code cleanups and reorgnization (Thomas Gleixner) - x86 Intel uncore and CPU PMU driver updates (Kan Liang, Peter Zijlstra) - x86 AUX (Intel PT) related enhancements and updates (Alexander Shishkin) - x86 MSR PMU driver enhancements and updates (Huang Rui) - ... and lots of other changes spread out over 40+ commits. Biggest tooling side changes: - 'perf trace' features and enhancements. (Arnaldo Carvalho de Melo) - BPF tooling updates (Wang Nan) - 'perf sched' updates (Jiri Olsa) - 'perf probe' updates (Masami Hiramatsu) - ... plus 200+ other enhancements, fixes and cleanups to tools/ The merge commits, the shortlog and the changelogs contain a lot more details" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (249 commits) perf/core: Disable the event on a truncated AUX record perf/x86/intel/pt: Generate PMI in the STOP region as well perf buildid-cache: Use lsdir() for looking up buildid caches perf symbols: Use lsdir() for the search in kcore cache directory perf tools: Use SBUILD_ID_SIZE where applicable perf tools: Fix lsdir to set errno correctly perf trace: Move seccomp args beautifiers to tools/perf/trace/beauty/ perf trace: Move flock op beautifier to tools/perf/trace/beauty/ perf build: Add build-test for debug-frame on arm/arm64 perf build: Add build-test for libunwind cross-platforms support perf script: Fix export of callchains with recursion in db-export perf script: Fix callchain addresses in db-export perf script: Fix symbol insertion behavior in db-export perf symbols: Add dso__insert_symbol function perf scripting python: Use Py_FatalError instead of die() perf tools: Remove xrealloc and ALLOC_GROW perf help: Do not use ALLOC_GROW in add_cmd_list perf pmu: Make pmu_formats_string to check return value of strbuf perf header: Make topology checkers to check return value of strbuf perf tools: Make alias handler to check return value of strbuf ...

Linus Torvalds committed 10 years ago

Commit 36db1712 parents 3469d26 3f56e68217 files · +8328 −2731Browse files

Unified · Split

217 files
  1. Documentation/sysctl/kernel.txt +14 −0
  2. arch/arm/kernel/hw_breakpoint.c +2 −2
  3. arch/arm/kernel/perf_callchain.c +1 −1
  4. arch/arm64/kernel/hw_breakpoint.c +2 −2
  5. arch/arm64/kernel/perf_callchain.c +2 −2
  6. arch/metag/kernel/perf_callchain.c +1 −1
  7. arch/mips/kernel/perf_event.c +2 −2
  8. arch/powerpc/perf/callchain.c +2 −2
  9. arch/sparc/kernel/perf_event.c +3 −3
  10. arch/x86/Kconfig +2 −13
  11. arch/x86/events/Kconfig +36 −0
  12. arch/x86/events/Makefile +3 −6
  13. arch/x86/events/amd/uncore.c +2 −0
  14. arch/x86/events/core.c +8 −2
  15. arch/x86/events/intel/Makefile +9 −0
  16. arch/x86/events/intel/bts.c +48 −57
  17. arch/x86/events/intel/core.c +159 −1
  18. arch/x86/events/intel/cstate.c +256 −291
  19. arch/x86/events/intel/ds.c +6 −0
  20. arch/x86/events/intel/lbr.c +30 −1
  21. arch/x86/events/intel/pt.c +250 −68
  22. arch/x86/events/intel/pt.h +68 −0
  23. arch/x86/events/intel/rapl.c +141 −42
  24. arch/x86/events/intel/uncore.c +126 −90
  25. arch/x86/events/msr.c +26 −10
  26. arch/x86/events/perf_event.h +5 −0
  27. arch/x86/include/asm/cpufeatures.h +2 −0
  28. arch/x86/include/asm/msr-index.h +15 −20
  29. arch/x86/kernel/uprobes.c +2 −2
  30. arch/xtensa/kernel/perf_event.c +2 −2
  31. drivers/perf/arm_pmu.c +8 −0
  32. drivers/powercap/intel_rapl.c +69 −0
  33. include/linux/perf_event.h +135 −4
  34. include/uapi/linux/perf_event.h +3 −1
  35. kernel/bpf/stackmap.c +4 −4
  36. kernel/events/callchain.c +33 −2
  37. kernel/events/core.c +857 −54
  38. kernel/events/internal.h +9 −1
  39. kernel/events/ring_buffer.c +87 −31
  40. kernel/sysctl.c +12 −0
  41. kernel/trace/trace_event_perf.c +3 −0
  42. tools/Makefile +2 −1
  43. tools/build/Makefile.feature +7 −1
  44. tools/build/feature/Makefile +23 −0
  45. tools/build/feature/test-bpf.c +1 −2
  46. tools/build/feature/test-libunwind-aarch64.c +26 −0
  47. tools/build/feature/test-libunwind-arm.c +27 −0
  48. tools/build/feature/test-libunwind-debug-frame-aarch64.c +16 −0
  49. tools/build/feature/test-libunwind-debug-frame-arm.c +16 −0
  50. tools/build/feature/test-libunwind-x86.c +27 −0
  51. tools/build/feature/test-libunwind-x86_64.c +27 −0
  52. tools/lib/api/fs/fs.c +13 −0
  53. tools/lib/api/fs/fs.h +2 −0
  54. tools/perf/Documentation/intel-pt.txt +7 −0
  55. tools/perf/Documentation/itrace.txt +8 −0
  56. tools/perf/Documentation/perf-annotate.txt +1 −1
  57. tools/perf/Documentation/perf-diff.txt +1 −1
  58. tools/perf/Documentation/perf-list.txt +106 −1
  59. tools/perf/Documentation/perf-mem.txt +8 −0
  60. tools/perf/Documentation/perf-record.txt +13 −0
  61. tools/perf/Documentation/perf-report.txt +2 −2
  62. tools/perf/Documentation/perf-sched.txt +16 −0
  63. tools/perf/Documentation/perf-script.txt +14 −0
  64. tools/perf/Documentation/perf-top.txt +1 −1
  65. tools/perf/Documentation/perf-trace.txt +32 −0
  66. tools/perf/Makefile.perf +9 −6
  67. tools/perf/arch/powerpc/Makefile +1 −0
  68. tools/perf/arch/powerpc/util/dwarf-regs.c +28 −12
  69. tools/perf/arch/powerpc/util/sym-handling.c +32 −11
  70. tools/perf/arch/x86/Makefile +23 −0
  71. tools/perf/arch/x86/entry/syscalls/syscall_64.tbl +376 −0
  72. tools/perf/arch/x86/entry/syscalls/syscalltbl.sh +39 −0
  73. tools/perf/arch/x86/tests/perf-time-to-tsc.c +1 −1
  74. tools/perf/arch/x86/util/intel-bts.c +5 −0
  75. tools/perf/arch/x86/util/intel-pt.c +5 −0
  76. tools/perf/arch/x86/util/tsc.c +31 −1
  77. tools/perf/arch/x86/util/tsc.h +0 −17
  78. tools/perf/bench/futex-lock-pi.c +1 −1
  79. tools/perf/bench/futex.h +2 −4
  80. tools/perf/bench/mem-functions.c +15 −7
  81. tools/perf/builtin-config.c +32 −7
  82. tools/perf/builtin-diff.c +2 −2
  83. tools/perf/builtin-help.c +10 −8
  84. tools/perf/builtin-inject.c +1 −0
  85. tools/perf/builtin-kmem.c +1 −1
  86. tools/perf/builtin-kvm.c +1 −1
  87. tools/perf/builtin-mem.c +10 −1
  88. tools/perf/builtin-record.c +220 −47
  89. tools/perf/builtin-report.c +10 −9
  90. tools/perf/builtin-sched.c +186 −12
  91. tools/perf/builtin-script.c +35 −21
  92. tools/perf/builtin-stat.c +8 −0
  93. tools/perf/builtin-top.c +19 −20
  94. tools/perf/builtin-trace.c +416 −669
  95. tools/perf/config/Makefile +1 −4
  96. tools/perf/jvmti/jvmti_agent.c +41 −2
  97. tools/perf/perf.c +11 −5
  98. tools/perf/perf.h +0 −1
  99. tools/perf/scripts/python/export-to-postgresql.py +32 −20
  100. tools/perf/tests/Build +2 −0
  101. tools/perf/tests/backward-ring-buffer.c +151 −0
  102. tools/perf/tests/bpf.c +1 −1
  103. tools/perf/tests/builtin-test.c +8 −0
  104. tools/perf/tests/code-reading.c +1 −1
  105. tools/perf/tests/dso-data.c +1 −1
  106. tools/perf/tests/event-times.c +236 −0
  107. tools/perf/tests/event_update.c +1 −1
  108. tools/perf/tests/hists_common.c +1 −1
  109. tools/perf/tests/hists_cumulate.c +2 −2
  110. tools/perf/tests/hists_filter.c +1 −1
  111. tools/perf/tests/hists_link.c +2 −2
  112. tools/perf/tests/hists_output.c +2 −2
  113. tools/perf/tests/keep-tracking.c +1 −1
  114. tools/perf/tests/openat-syscall-tp-fields.c +1 −1
  115. tools/perf/tests/perf-record.c +1 −1
  116. tools/perf/tests/switch-tracking.c +1 −1
  117. tools/perf/tests/tests.h +2 −0
  118. tools/perf/tests/vmlinux-kallsyms.c +10 −1
  119. tools/perf/trace/beauty/eventfd.c +38 −0
  120. tools/perf/trace/beauty/flock.c +31 −0
  121. tools/perf/trace/beauty/futex_op.c +44 −0
  122. tools/perf/trace/beauty/mmap.c +158 −0
  123. tools/perf/trace/beauty/mode_t.c +68 −0
  124. tools/perf/trace/beauty/msg_flags.c +62 −0
  125. tools/perf/trace/beauty/open_flags.c +56 −0
  126. tools/perf/trace/beauty/perf_event_open.c +43 −0
  127. tools/perf/trace/beauty/pid.c +21 −0
  128. tools/perf/trace/beauty/sched_policy.c +44 −0
  129. tools/perf/trace/beauty/seccomp.c +52 −0
  130. tools/perf/trace/beauty/signum.c +53 −0
  131. tools/perf/trace/beauty/socket_type.c +60 −0
  132. tools/perf/trace/beauty/waitid_options.c +26 −0
  133. tools/perf/ui/browsers/hists.c +20 −20
  134. tools/perf/ui/gtk/hists.c +1 −1
  135. tools/perf/ui/hist.c +1 −1
  136. tools/perf/ui/stdio/hist.c +1 −2
  137. tools/perf/util/Build +5 −3
  138. tools/perf/util/annotate.c +2 −2
  139. tools/perf/util/auxtrace.c +7 −0
  140. tools/perf/util/auxtrace.h +2 −0
  141. tools/perf/util/bpf-loader.c +143 −0
  142. tools/perf/util/bpf-loader.h +19 −0
  143. tools/perf/util/build-id.c +7 −29
  144. tools/perf/util/cache.h +0 −19
  145. tools/perf/util/call-path.c +122 −0
  146. tools/perf/util/call-path.h +77 −0
  147. tools/perf/util/callchain.c +6 −3
  148. tools/perf/util/callchain.h +8 −1
  149. tools/perf/util/config.c +191 −31
  150. tools/perf/util/config.h +26 −0
  151. tools/perf/util/cpumap.c +12 −0
  152. tools/perf/util/cpumap.h +2 −0
  153. tools/perf/util/data.c +41 −0
  154. tools/perf/util/data.h +10 −1
  155. tools/perf/util/db-export.c +87 −2
  156. tools/perf/util/db-export.h +3 −0
  157. tools/perf/util/dso.c +2 −2
  158. tools/perf/util/dwarf-aux.c +24 −28
  159. tools/perf/util/event.c +1 −0
  160. tools/perf/util/event.h +9 −0
  161. tools/perf/util/evlist.c +134 −40
  162. tools/perf/util/evlist.h +21 −1
  163. tools/perf/util/evsel.c +38 −101
  164. tools/perf/util/evsel.h +26 −2
  165. tools/perf/util/evsel_fprintf.c +212 −0
  166. tools/perf/util/header.c +21 −12
  167. tools/perf/util/help-unknown-cmd.c +22 −8
  168. tools/perf/util/hist.c +13 −10
  169. tools/perf/util/hist.h +10 −2
  170. tools/perf/util/intel-bts.c +5 −0
  171. tools/perf/util/intel-pt-decoder/intel-pt-decoder.c +1 −1
  172. tools/perf/util/intel-pt.c +20 −2
  173. tools/perf/util/jitdump.c +34 −7
  174. tools/perf/util/jitdump.h +3 −0
  175. tools/perf/util/machine.c +73 −32
  176. tools/perf/util/machine.h +7 −0
  177. tools/perf/util/map.c +15 −1
  178. tools/perf/util/ordered-events.c +9 −0
  179. tools/perf/util/ordered-events.h +1 −0
  180. tools/perf/util/pmu.c +11 −12
  181. tools/perf/util/probe-event.c +215 −191
  182. tools/perf/util/probe-event.h +3 −2
  183. tools/perf/util/probe-file.c +1 −2
  184. tools/perf/util/probe-finder.c +21 −15
  185. tools/perf/util/python-ext-sources +1 −0
  186. tools/perf/util/quote.c +20 −16
  187. tools/perf/util/quote.h +1 −1
  188. tools/perf/util/rb_resort.h +149 −0
  189. tools/perf/util/record.c +3 −2
  190. tools/perf/util/scripting-engines/trace-event-perl.c +118 −8
  191. tools/perf/util/scripting-engines/trace-event-python.c +41 −6
  192. tools/perf/util/session.c +13 −102
  193. tools/perf/util/session.h +1 −11
  194. tools/perf/util/sort.c +14 −21
  195. tools/perf/util/sort.h +0 −7
  196. tools/perf/util/stat.c +3 −1
  197. tools/perf/util/strbuf.c +67 −26
  198. tools/perf/util/strbuf.h +15 −10
  199. tools/perf/util/symbol-elf.c +7 −13
  200. tools/perf/util/symbol.c +37 −71
  201. tools/perf/util/symbol.h +18 −1
  202. tools/perf/util/symbol_fprintf.c +71 −0
  203. tools/perf/util/syscalltbl.c +134 −0
  204. tools/perf/util/syscalltbl.h +20 −0
  205. tools/perf/util/thread-stack.c +1 −138
  206. tools/perf/util/thread-stack.h +10 −21
  207. tools/perf/util/thread.c +20 −1
  208. tools/perf/util/thread.h +8 −0
  209. tools/perf/util/thread_map.c +13 −1
  210. tools/perf/util/thread_map.h +3 −0
  211. tools/perf/util/tool.h +1 −0
  212. tools/perf/util/trigger.h +94 −0
  213. tools/perf/util/tsc.h +20 −1
  214. tools/perf/util/unwind-libunwind.c +9 −16
  215. tools/perf/util/util.c +36 −2
  216. tools/perf/util/util.h +9 −6
  217. tools/perf/util/wrapper.c +0 −29
Documentation/sysctl/kernel.txt+14−0
@@ -60,6 +60,7 @@ show up in /proc/sys/kernel: · 59 unmodified lines
60- panic_on_warn60- panic_on_warn
61- perf_cpu_time_max_percent61- perf_cpu_time_max_percent
62- perf_event_paranoid62- perf_event_paranoid
63- perf_event_max_stack
63- pid_max64- pid_max
64- powersave-nap [ PPC only ]65- powersave-nap [ PPC only ]
65- printk66- printk
@@ -654,6 +655,19 @@ users (without CAP_SYS_ADMIN). The default value is 2. · 588 unmodified lines
654 655
655==============================================================656==============================================================
656 657
658perf_event_max_stack:
659
660Controls maximum number of stack frames to copy for (attr.sample_type &
661PERF_SAMPLE_CALLCHAIN) configured events, for instance, when using
662'perf record -g' or 'perf trace --call-graph fp'.
663
664This can only be done when no events are in use that have callchains
665enabled, otherwise writing to this file will return -EBUSY.
666
667The default value is 127.
668
669==============================================================
670
657pid_max:671pid_max:
658 672
659PID allocation wrap value. When the kernel's next PID value673PID allocation wrap value. When the kernel's next PID value
arch/arm/kernel/hw_breakpoint.c+2−2
@@ -631,7 +631,7 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp) · 630 unmodified lines
631 info->address &= ~alignment_mask;631 info->address &= ~alignment_mask;
632 info->ctrl.len <<= offset;632 info->ctrl.len <<= offset;
633 633
634 if (!bp->overflow_handler) {634 if (is_default_overflow_handler(bp)) {
635 /*635 /*
636 * Mismatch breakpoints are required for single-stepping636 * Mismatch breakpoints are required for single-stepping
637 * breakpoints.637 * breakpoints.
@@ -754,7 +754,7 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr, · 116 unmodified lines
754 * mismatch breakpoint so we can single-step over the754 * mismatch breakpoint so we can single-step over the
755 * watchpoint trigger.755 * watchpoint trigger.
756 */756 */
757 if (!wp->overflow_handler)757 if (is_default_overflow_handler(wp))
758 enable_single_step(wp, instruction_pointer(regs));758 enable_single_step(wp, instruction_pointer(regs));
759 759
760unlock:760unlock:
arch/arm/kernel/perf_callchain.c+1−1
@@ -75,7 +75,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) · 74 unmodified lines
75 75
76 tail = (struct frame_tail __user *)regs->ARM_fp - 1;76 tail = (struct frame_tail __user *)regs->ARM_fp - 1;
77 77
78 while ((entry->nr < PERF_MAX_STACK_DEPTH) &&78 while ((entry->nr < sysctl_perf_event_max_stack) &&
79 tail && !((unsigned long)tail & 0x3))79 tail && !((unsigned long)tail & 0x3))
80 tail = user_backtrace(tail, entry);80 tail = user_backtrace(tail, entry);
81}81}
arch/arm64/kernel/hw_breakpoint.c+2−2
@@ -616,7 +616,7 @@ static int breakpoint_handler(unsigned long unused, unsigned int esr, · 615 unmodified lines
616 perf_bp_event(bp, regs);616 perf_bp_event(bp, regs);
617 617
618 /* Do we need to handle the stepping? */618 /* Do we need to handle the stepping? */
619 if (!bp->overflow_handler)619 if (is_default_overflow_handler(bp))
620 step = 1;620 step = 1;
621unlock:621unlock:
622 rcu_read_unlock();622 rcu_read_unlock();
@@ -712,7 +712,7 @@ static int watchpoint_handler(unsigned long addr, unsigned int esr, · 89 unmodified lines
712 perf_bp_event(wp, regs);712 perf_bp_event(wp, regs);
713 713
714 /* Do we need to handle the stepping? */714 /* Do we need to handle the stepping? */
715 if (!wp->overflow_handler)715 if (is_default_overflow_handler(wp))
716 step = 1;716 step = 1;
717 717
718unlock:718unlock:
arch/arm64/kernel/perf_callchain.c+2−2
@@ -122,7 +122,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, · 121 unmodified lines
122 122
123 tail = (struct frame_tail __user *)regs->regs[29];123 tail = (struct frame_tail __user *)regs->regs[29];
124 124
125 while (entry->nr < PERF_MAX_STACK_DEPTH &&125 while (entry->nr < sysctl_perf_event_max_stack &&
126 tail && !((unsigned long)tail & 0xf))126 tail && !((unsigned long)tail & 0xf))
127 tail = user_backtrace(tail, entry);127 tail = user_backtrace(tail, entry);
128 } else {128 } else {
@@ -132,7 +132,7 @@ void perf_callchain_user(struct perf_callchain_entry *entry, · 3 unmodified lines
132 132
133 tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;133 tail = (struct compat_frame_tail __user *)regs->compat_fp - 1;
134 134
135 while ((entry->nr < PERF_MAX_STACK_DEPTH) &&135 while ((entry->nr < sysctl_perf_event_max_stack) &&
136 tail && !((unsigned long)tail & 0x3))136 tail && !((unsigned long)tail & 0x3))
137 tail = compat_user_backtrace(tail, entry);137 tail = compat_user_backtrace(tail, entry);
138#endif138#endif
arch/metag/kernel/perf_callchain.c+1−1
@@ -65,7 +65,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) · 64 unmodified lines
65 65
66 --frame;66 --frame;
67 67
68 while ((entry->nr < PERF_MAX_STACK_DEPTH) && frame)68 while ((entry->nr < sysctl_perf_event_max_stack) && frame)
69 frame = user_backtrace(frame, entry);69 frame = user_backtrace(frame, entry);
70}70}
71 71
arch/mips/kernel/perf_event.c+2−2
@@ -35,7 +35,7 @@ static void save_raw_perf_callchain(struct perf_callchain_entry *entry, · 34 unmodified lines
35 addr = *sp++;35 addr = *sp++;
36 if (__kernel_text_address(addr)) {36 if (__kernel_text_address(addr)) {
37 perf_callchain_store(entry, addr);37 perf_callchain_store(entry, addr);
38 if (entry->nr >= PERF_MAX_STACK_DEPTH)38 if (entry->nr >= sysctl_perf_event_max_stack)
39 break;39 break;
40 }40 }
41 }41 }
@@ -59,7 +59,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, · 17 unmodified lines
59 }59 }
60 do {60 do {
61 perf_callchain_store(entry, pc);61 perf_callchain_store(entry, pc);
62 if (entry->nr >= PERF_MAX_STACK_DEPTH)62 if (entry->nr >= sysctl_perf_event_max_stack)
63 break;63 break;
64 pc = unwind_stack(current, &sp, pc, &ra);64 pc = unwind_stack(current, &sp, pc, &ra);
65 } while (pc);65 } while (pc);
arch/powerpc/perf/callchain.c+2−2
@@ -247,7 +247,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, · 246 unmodified lines
247 sp = regs->gpr[1];247 sp = regs->gpr[1];
248 perf_callchain_store(entry, next_ip);248 perf_callchain_store(entry, next_ip);
249 249
250 while (entry->nr < PERF_MAX_STACK_DEPTH) {250 while (entry->nr < sysctl_perf_event_max_stack) {
251 fp = (unsigned long __user *) sp;251 fp = (unsigned long __user *) sp;
252 if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))252 if (!valid_user_sp(sp, 1) || read_user_stack_64(fp, &next_sp))
253 return;253 return;
@@ -453,7 +453,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, · 199 unmodified lines
453 sp = regs->gpr[1];453 sp = regs->gpr[1];
454 perf_callchain_store(entry, next_ip);454 perf_callchain_store(entry, next_ip);
455 455
456 while (entry->nr < PERF_MAX_STACK_DEPTH) {456 while (entry->nr < sysctl_perf_event_max_stack) {
457 fp = (unsigned int __user *) (unsigned long) sp;457 fp = (unsigned int __user *) (unsigned long) sp;
458 if (!valid_user_sp(sp, 0) || read_user_stack_32(fp, &next_sp))458 if (!valid_user_sp(sp, 0) || read_user_stack_32(fp, &next_sp))
459 return;459 return;
arch/sparc/kernel/perf_event.c+3−3
@@ -1756,7 +1756,7 @@ void perf_callchain_kernel(struct perf_callchain_entry *entry, · 1755 unmodified lines
1756 }1756 }
1757 }1757 }
1758#endif1758#endif
1759 } while (entry->nr < PERF_MAX_STACK_DEPTH);1759 } while (entry->nr < sysctl_perf_event_max_stack);
1760}1760}
1761 1761
1762static inline int1762static inline int
@@ -1790,7 +1790,7 @@ static void perf_callchain_user_64(struct perf_callchain_entry *entry, · 27 unmodified lines
1790 pc = sf.callers_pc;1790 pc = sf.callers_pc;
1791 ufp = (unsigned long)sf.fp + STACK_BIAS;1791 ufp = (unsigned long)sf.fp + STACK_BIAS;
1792 perf_callchain_store(entry, pc);1792 perf_callchain_store(entry, pc);
1793 } while (entry->nr < PERF_MAX_STACK_DEPTH);1793 } while (entry->nr < sysctl_perf_event_max_stack);
1794}1794}
1795 1795
1796static void perf_callchain_user_32(struct perf_callchain_entry *entry,1796static void perf_callchain_user_32(struct perf_callchain_entry *entry,
@@ -1822,7 +1822,7 @@ static void perf_callchain_user_32(struct perf_callchain_entry *entry, · 25 unmodified lines
1822 ufp = (unsigned long)sf.fp;1822 ufp = (unsigned long)sf.fp;
1823 }1823 }
1824 perf_callchain_store(entry, pc);1824 perf_callchain_store(entry, pc);
1825 } while (entry->nr < PERF_MAX_STACK_DEPTH);1825 } while (entry->nr < sysctl_perf_event_max_stack);
1826}1826}
1827 1827
1828void1828void
arch/x86/Kconfig+2−13
@@ -164,10 +164,6 @@ config INSTRUCTION_DECODER · 163 unmodified lines
164 def_bool y164 def_bool y
165 depends on KPROBES || PERF_EVENTS || UPROBES165 depends on KPROBES || PERF_EVENTS || UPROBES
166 166
167config PERF_EVENTS_INTEL_UNCORE
168 def_bool y
169 depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
170
171config OUTPUT_FORMAT167config OUTPUT_FORMAT
172 string168 string
173 default "elf32-i386" if X86_32169 default "elf32-i386" if X86_32
@@ -1046,6 +1042,8 @@ config X86_THERMAL_VECTOR · 872 unmodified lines
1046 def_bool y1042 def_bool y
1047 depends on X86_MCE_INTEL1043 depends on X86_MCE_INTEL
1048 1044
1045source "arch/x86/events/Kconfig"
1046
1049config X86_LEGACY_VM861047config X86_LEGACY_VM86
1050 bool "Legacy VM86 support"1048 bool "Legacy VM86 support"
1051 default n1049 default n
@@ -1210,15 +1208,6 @@ config MICROCODE_OLD_INTERFACE · 158 unmodified lines
1210 def_bool y1208 def_bool y
1211 depends on MICROCODE1209 depends on MICROCODE
1212 1210
1213config PERF_EVENTS_AMD_POWER
1214 depends on PERF_EVENTS && CPU_SUP_AMD
1215 tristate "AMD Processor Power Reporting Mechanism"
1216 ---help---
1217 Provide power reporting mechanism support for AMD processors.
1218 Currently, it leverages X86_FEATURE_ACC_POWER
1219 (CPUID Fn8000_0007_EDX[12]) interface to calculate the
1220 average power consumption on Family 15h processors.
1221
1222config X86_MSR1211config X86_MSR
1223 tristate "/dev/cpu/*/msr - Model-specific register support"1212 tristate "/dev/cpu/*/msr - Model-specific register support"
1224 ---help---1213 ---help---
arch/x86/events/Kconfig+36−0
@@ -0,0 +1,36 @@
1menu "Performance monitoring"
2
3config PERF_EVENTS_INTEL_UNCORE
4 tristate "Intel uncore performance events"
5 depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
6 default y
7 ---help---
8 Include support for Intel uncore performance events. These are
9 available on NehalemEX and more modern processors.
10
11config PERF_EVENTS_INTEL_RAPL
12 tristate "Intel rapl performance events"
13 depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
14 default y
15 ---help---
16 Include support for Intel rapl performance events for power
17 monitoring on modern processors.
18
19config PERF_EVENTS_INTEL_CSTATE
20 tristate "Intel cstate performance events"
21 depends on PERF_EVENTS && CPU_SUP_INTEL && PCI
22 default y
23 ---help---
24 Include support for Intel cstate performance events for power
25 monitoring on modern processors.
26
27config PERF_EVENTS_AMD_POWER
28 depends on PERF_EVENTS && CPU_SUP_AMD
29 tristate "AMD Processor Power Reporting Mechanism"
30 ---help---
31 Provide power reporting mechanism support for AMD processors.
32 Currently, it leverages X86_FEATURE_ACC_POWER
33 (CPUID Fn8000_0007_EDX[12]) interface to calculate the
34 average power consumption on Family 15h processors.
35
36endmenu
arch/x86/events/Makefile+3−6
@@ -6,9 +6,6 @@ obj-$(CONFIG_X86_LOCAL_APIC) += amd/ibs.o msr.o · 5 unmodified lines
6ifdef CONFIG_AMD_IOMMU6ifdef CONFIG_AMD_IOMMU
7obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o7obj-$(CONFIG_CPU_SUP_AMD) += amd/iommu.o
8endif8endif
9obj-$(CONFIG_CPU_SUP_INTEL) += intel/core.o intel/bts.o intel/cqm.o9
10obj-$(CONFIG_CPU_SUP_INTEL) += intel/cstate.o intel/ds.o intel/knc.o 10obj-$(CONFIG_CPU_SUP_INTEL) += msr.o
11obj-$(CONFIG_CPU_SUP_INTEL) += intel/lbr.o intel/p4.o intel/p6.o intel/pt.o11obj-$(CONFIG_CPU_SUP_INTEL) += intel/
12obj-$(CONFIG_CPU_SUP_INTEL) += intel/rapl.o msr.o
13obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore.o intel/uncore_nhmex.o
14obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel/uncore_snb.o intel/uncore_snbep.o
arch/x86/events/amd/uncore.c+2−0
@@ -263,6 +263,7 @@ static const struct attribute_group *amd_uncore_attr_groups[] = { · 262 unmodified lines
263};263};
264 264
265static struct pmu amd_nb_pmu = {265static struct pmu amd_nb_pmu = {
266 .task_ctx_nr = perf_invalid_context,
266 .attr_groups = amd_uncore_attr_groups,267 .attr_groups = amd_uncore_attr_groups,
267 .name = "amd_nb",268 .name = "amd_nb",
268 .event_init = amd_uncore_event_init,269 .event_init = amd_uncore_event_init,
@@ -274,6 +275,7 @@ static struct pmu amd_nb_pmu = { · 5 unmodified lines
274};275};
275 276
276static struct pmu amd_l2_pmu = {277static struct pmu amd_l2_pmu = {
278 .task_ctx_nr = perf_invalid_context,
277 .attr_groups = amd_uncore_attr_groups,279 .attr_groups = amd_uncore_attr_groups,
278 .name = "amd_l2",280 .name = "amd_l2",
279 .event_init = amd_uncore_event_init,281 .event_init = amd_uncore_event_init,
arch/x86/events/core.c+8−2
@@ -360,6 +360,9 @@ int x86_add_exclusive(unsigned int what) · 359 unmodified lines
360{360{
361 int i;361 int i;
362 362
363 if (x86_pmu.lbr_pt_coexist)
364 return 0;
365
363 if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {366 if (!atomic_inc_not_zero(&x86_pmu.lbr_exclusive[what])) {
364 mutex_lock(&pmc_reserve_mutex);367 mutex_lock(&pmc_reserve_mutex);
365 for (i = 0; i < ARRAY_SIZE(x86_pmu.lbr_exclusive); i++) {368 for (i = 0; i < ARRAY_SIZE(x86_pmu.lbr_exclusive); i++) {
@@ -380,6 +383,9 @@ fail_unlock: · 14 unmodified lines
380 383
381void x86_del_exclusive(unsigned int what)384void x86_del_exclusive(unsigned int what)
382{385{
386 if (x86_pmu.lbr_pt_coexist)
387 return;
388
383 atomic_dec(&x86_pmu.lbr_exclusive[what]);389 atomic_dec(&x86_pmu.lbr_exclusive[what]);
384 atomic_dec(&active_events);390 atomic_dec(&active_events);
385}391}
@@ -2277,7 +2283,7 @@ perf_callchain_user32(struct pt_regs *regs, struct perf_callchain_entry *entry) · 1891 unmodified lines
2277 2283
2278 fp = compat_ptr(ss_base + regs->bp);2284 fp = compat_ptr(ss_base + regs->bp);
2279 pagefault_disable();2285 pagefault_disable();
2280 while (entry->nr < PERF_MAX_STACK_DEPTH) {2286 while (entry->nr < sysctl_perf_event_max_stack) {
2281 unsigned long bytes;2287 unsigned long bytes;
2282 frame.next_frame = 0;2288 frame.next_frame = 0;
2283 frame.return_address = 0;2289 frame.return_address = 0;
@@ -2337,7 +2343,7 @@ perf_callchain_user(struct perf_callchain_entry *entry, struct pt_regs *regs) · 53 unmodified lines
2337 return;2343 return;
2338 2344
2339 pagefault_disable();2345 pagefault_disable();
2340 while (entry->nr < PERF_MAX_STACK_DEPTH) {2346 while (entry->nr < sysctl_perf_event_max_stack) {
2341 unsigned long bytes;2347 unsigned long bytes;
2342 frame.next_frame = NULL;2348 frame.next_frame = NULL;
2343 frame.return_address = 0;2349 frame.return_address = 0;
arch/x86/events/intel/Makefile+9−0
@@ -0,0 +1,9 @@
1obj-$(CONFIG_CPU_SUP_INTEL) += core.o bts.o cqm.o
2obj-$(CONFIG_CPU_SUP_INTEL) += ds.o knc.o
3obj-$(CONFIG_CPU_SUP_INTEL) += lbr.o p4.o p6.o pt.o
4obj-$(CONFIG_PERF_EVENTS_INTEL_RAPL) += intel-rapl.o
5intel-rapl-objs := rapl.o
6obj-$(CONFIG_PERF_EVENTS_INTEL_UNCORE) += intel-uncore.o
7intel-uncore-objs := uncore.o uncore_nhmex.o uncore_snb.o uncore_snbep.o
8obj-$(CONFIG_PERF_EVENTS_INTEL_CSTATE) += intel-cstate.o
9intel-cstate-objs := cstate.o
arch/x86/events/intel/bts.c+48−57
@@ -171,18 +171,6 @@ static void bts_buffer_pad_out(struct bts_phys *phys, unsigned long head) · 170 unmodified lines
171 memset(page_address(phys->page) + index, 0, phys->size - index);171 memset(page_address(phys->page) + index, 0, phys->size - index);
172}172}
173 173
174static bool bts_buffer_is_full(struct bts_buffer *buf, struct bts_ctx *bts)
175{
176 if (buf->snapshot)
177 return false;
178
179 if (local_read(&buf->data_size) >= bts->handle.size ||
180 bts->handle.size - local_read(&buf->data_size) < BTS_RECORD_SIZE)
181 return true;
182
183 return false;
184}
185
186static void bts_update(struct bts_ctx *bts)174static void bts_update(struct bts_ctx *bts)
187{175{
188 int cpu = raw_smp_processor_id();176 int cpu = raw_smp_processor_id();
@@ -213,18 +201,15 @@ static void bts_update(struct bts_ctx *bts) · 24 unmodified lines
213 }201 }
214}202}
215 203
204static int
205bts_buffer_reset(struct bts_buffer *buf, struct perf_output_handle *handle);
206
216static void __bts_event_start(struct perf_event *event)207static void __bts_event_start(struct perf_event *event)
217{208{
218 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);209 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
219 struct bts_buffer *buf = perf_get_aux(&bts->handle);210 struct bts_buffer *buf = perf_get_aux(&bts->handle);
220 u64 config = 0;211 u64 config = 0;
221 212
222 if (!buf || bts_buffer_is_full(buf, bts))
223 return;
224
225 event->hw.itrace_started = 1;
226 event->hw.state = 0;
227
228 if (!buf->snapshot)213 if (!buf->snapshot)
229 config |= ARCH_PERFMON_EVENTSEL_INT;214 config |= ARCH_PERFMON_EVENTSEL_INT;
230 if (!event->attr.exclude_kernel)215 if (!event->attr.exclude_kernel)
@@ -241,16 +226,41 @@ static void __bts_event_start(struct perf_event *event) · 10 unmodified lines
241 wmb();226 wmb();
242 227
243 intel_pmu_enable_bts(config);228 intel_pmu_enable_bts(config);
229
244}230}
245 231
246static void bts_event_start(struct perf_event *event, int flags)232static void bts_event_start(struct perf_event *event, int flags)
247{233{
234 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
248 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);235 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
236 struct bts_buffer *buf;
237
238 buf = perf_aux_output_begin(&bts->handle, event);
239 if (!buf)
240 goto fail_stop;
241
242 if (bts_buffer_reset(buf, &bts->handle))
243 goto fail_end_stop;
244
245 bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
246 bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
247 bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
248
249 event->hw.itrace_started = 1;
250 event->hw.state = 0;
249 251
250 __bts_event_start(event);252 __bts_event_start(event);
251 253
252 /* PMI handler: this counter is running and likely generating PMIs */254 /* PMI handler: this counter is running and likely generating PMIs */
253 ACCESS_ONCE(bts->started) = 1;255 ACCESS_ONCE(bts->started) = 1;
256
257 return;
258
259fail_end_stop:
260 perf_aux_output_end(&bts->handle, 0, false);
261
262fail_stop:
263 event->hw.state = PERF_HES_STOPPED;
254}264}
255 265
256static void __bts_event_stop(struct perf_event *event)266static void __bts_event_stop(struct perf_event *event)
@@ -269,15 +279,32 @@ static void __bts_event_stop(struct perf_event *event) · 12 unmodified lines
269 279
270static void bts_event_stop(struct perf_event *event, int flags)280static void bts_event_stop(struct perf_event *event, int flags)
271{281{
282 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
272 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);283 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
284 struct bts_buffer *buf = perf_get_aux(&bts->handle);
273 285
274 /* PMI handler: don't restart this counter */286 /* PMI handler: don't restart this counter */
275 ACCESS_ONCE(bts->started) = 0;287 ACCESS_ONCE(bts->started) = 0;
276 288
277 __bts_event_stop(event);289 __bts_event_stop(event);
278 290
279 if (flags & PERF_EF_UPDATE)291 if (flags & PERF_EF_UPDATE) {
280 bts_update(bts);292 bts_update(bts);
293
294 if (buf) {
295 if (buf->snapshot)
296 bts->handle.head =
297 local_xchg(&buf->data_size,
298 buf->nr_pages << PAGE_SHIFT);
299 perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
300 !!local_xchg(&buf->lost, 0));
301 }
302
303 cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
304 cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
305 cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
306 cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
307 }
281}308}
282 309
283void intel_bts_enable_local(void)310void intel_bts_enable_local(void)
@@ -417,34 +444,14 @@ int intel_bts_interrupt(void) · 133 unmodified lines
417 444
418static void bts_event_del(struct perf_event *event, int mode)445static void bts_event_del(struct perf_event *event, int mode)
419{446{
420 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
421 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
422 struct bts_buffer *buf = perf_get_aux(&bts->handle);
423
424 bts_event_stop(event, PERF_EF_UPDATE);447 bts_event_stop(event, PERF_EF_UPDATE);
425
426 if (buf) {
427 if (buf->snapshot)
428 bts->handle.head =
429 local_xchg(&buf->data_size,
430 buf->nr_pages << PAGE_SHIFT);
431 perf_aux_output_end(&bts->handle, local_xchg(&buf->data_size, 0),
432 !!local_xchg(&buf->lost, 0));
433 }
434
435 cpuc->ds->bts_index = bts->ds_back.bts_buffer_base;
436 cpuc->ds->bts_buffer_base = bts->ds_back.bts_buffer_base;
437 cpuc->ds->bts_absolute_maximum = bts->ds_back.bts_absolute_maximum;
438 cpuc->ds->bts_interrupt_threshold = bts->ds_back.bts_interrupt_threshold;
439}448}
440 449
441static int bts_event_add(struct perf_event *event, int mode)450static int bts_event_add(struct perf_event *event, int mode)
442{451{
443 struct bts_buffer *buf;
444 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);452 struct bts_ctx *bts = this_cpu_ptr(&bts_ctx);
445 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);453 struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
446 struct hw_perf_event *hwc = &event->hw;454 struct hw_perf_event *hwc = &event->hw;
447 int ret = -EBUSY;
448 455
449 event->hw.state = PERF_HES_STOPPED;456 event->hw.state = PERF_HES_STOPPED;
450 457
@@ -454,26 +461,10 @@ static int bts_event_add(struct perf_event *event, int mode) · 3 unmodified lines
454 if (bts->handle.event)461 if (bts->handle.event)
455 return -EBUSY;462 return -EBUSY;
456 463
457 buf = perf_aux_output_begin(&bts->handle, event);
458 if (!buf)
459 return -EINVAL;
460
461 ret = bts_buffer_reset(buf, &bts->handle);
462 if (ret) {
463 perf_aux_output_end(&bts->handle, 0, false);
464 return ret;
465 }
466
467 bts->ds_back.bts_buffer_base = cpuc->ds->bts_buffer_base;
468 bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
469 bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
470
471 if (mode & PERF_EF_START) {464 if (mode & PERF_EF_START) {
472 bts_event_start(event, 0);465 bts_event_start(event, 0);
473 if (hwc->state & PERF_HES_STOPPED) {466 if (hwc->state & PERF_HES_STOPPED)
474 bts_event_del(event, 0);467 return -EINVAL;
475 return -EBUSY;
476 }
477 }468 }
478 469
479 return 0;470 return 0;
arch/x86/events/intel/core.c+159−1
@@ -1465,6 +1465,140 @@ static __initconst const u64 slm_hw_cache_event_ids · 1464 unmodified lines
1465 },1465 },
1466};1466};
1467 1467
1468static struct extra_reg intel_glm_extra_regs[] __read_mostly = {
1469 /* must define OFFCORE_RSP_X first, see intel_fixup_er() */
1470 INTEL_UEVENT_EXTRA_REG(0x01b7, MSR_OFFCORE_RSP_0, 0x760005ffbfull, RSP_0),
1471 INTEL_UEVENT_EXTRA_REG(0x02b7, MSR_OFFCORE_RSP_1, 0x360005ffbfull, RSP_1),
1472 EVENT_EXTRA_END
1473};
1474
1475#define GLM_DEMAND_DATA_RD BIT_ULL(0)
1476#define GLM_DEMAND_RFO BIT_ULL(1)
1477#define GLM_ANY_RESPONSE BIT_ULL(16)
1478#define GLM_SNP_NONE_OR_MISS BIT_ULL(33)
1479#define GLM_DEMAND_READ GLM_DEMAND_DATA_RD
1480#define GLM_DEMAND_WRITE GLM_DEMAND_RFO
1481#define GLM_DEMAND_PREFETCH (SNB_PF_DATA_RD|SNB_PF_RFO)
1482#define GLM_LLC_ACCESS GLM_ANY_RESPONSE
1483#define GLM_SNP_ANY (GLM_SNP_NONE_OR_MISS|SNB_NO_FWD|SNB_HITM)
1484#define GLM_LLC_MISS (GLM_SNP_ANY|SNB_NON_DRAM)
1485
1486static __initconst const u64 glm_hw_cache_event_ids
1487 [PERF_COUNT_HW_CACHE_MAX]
1488 [PERF_COUNT_HW_CACHE_OP_MAX]
1489 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
1490 [C(L1D)] = {
1491 [C(OP_READ)] = {
1492 [C(RESULT_ACCESS)] = 0x81d0, /* MEM_UOPS_RETIRED.ALL_LOADS */
1493 [C(RESULT_MISS)] = 0x0,
1494 },
1495 [C(OP_WRITE)] = {
1496 [C(RESULT_ACCESS)] = 0x82d0, /* MEM_UOPS_RETIRED.ALL_STORES */
1497 [C(RESULT_MISS)] = 0x0,
1498 },
1499 [C(OP_PREFETCH)] = {
1500 [C(RESULT_ACCESS)] = 0x0,
1501 [C(RESULT_MISS)] = 0x0,
1502 },
1503 },
1504 [C(L1I)] = {
1505 [C(OP_READ)] = {
1506 [C(RESULT_ACCESS)] = 0x0380, /* ICACHE.ACCESSES */
1507 [C(RESULT_MISS)] = 0x0280, /* ICACHE.MISSES */
1508 },
1509 [C(OP_WRITE)] = {
1510 [C(RESULT_ACCESS)] = -1,
1511 [C(RESULT_MISS)] = -1,
1512 },
1513 [C(OP_PREFETCH)] = {
1514 [C(RESULT_ACCESS)] = 0x0,
1515 [C(RESULT_MISS)] = 0x0,
1516 },
1517 },
1518 [C(LL)] = {
1519 [C(OP_READ)] = {
1520 [C(RESULT_ACCESS)] = 0x1b7, /* OFFCORE_RESPONSE */
1521 [C(RESULT_MISS)] = 0x1b7, /* OFFCORE_RESPONSE */
1522 },
1523 [C(OP_WRITE)] = {
1524 [C(RESULT_ACCESS)] = 0x1b7, /* OFFCORE_RESPONSE */
1525 [C(RESULT_MISS)] = 0x1b7, /* OFFCORE_RESPONSE */
1526 },
1527 [C(OP_PREFETCH)] = {
1528 [C(RESULT_ACCESS)] = 0x1b7, /* OFFCORE_RESPONSE */
1529 [C(RESULT_MISS)] = 0x1b7, /* OFFCORE_RESPONSE */
1530 },
1531 },
1532 [C(DTLB)] = {
1533 [C(OP_READ)] = {
1534 [C(RESULT_ACCESS)] = 0x81d0, /* MEM_UOPS_RETIRED.ALL_LOADS */
1535 [C(RESULT_MISS)] = 0x0,
1536 },
1537 [C(OP_WRITE)] = {
1538 [C(RESULT_ACCESS)] = 0x82d0, /* MEM_UOPS_RETIRED.ALL_STORES */
1539 [C(RESULT_MISS)] = 0x0,
1540 },
1541 [C(OP_PREFETCH)] = {
1542 [C(RESULT_ACCESS)] = 0x0,
1543 [C(RESULT_MISS)] = 0x0,
1544 },
1545 },
1546 [C(ITLB)] = {
1547 [C(OP_READ)] = {
1548 [C(RESULT_ACCESS)] = 0x00c0, /* INST_RETIRED.ANY_P */
1549 [C(RESULT_MISS)] = 0x0481, /* ITLB.MISS */
1550 },
1551 [C(OP_WRITE)] = {
1552 [C(RESULT_ACCESS)] = -1,
1553 [C(RESULT_MISS)] = -1,
1554 },
1555 [C(OP_PREFETCH)] = {
1556 [C(RESULT_ACCESS)] = -1,
1557 [C(RESULT_MISS)] = -1,
1558 },
1559 },
1560 [C(BPU)] = {
1561 [C(OP_READ)] = {
1562 [C(RESULT_ACCESS)] = 0x00c4, /* BR_INST_RETIRED.ALL_BRANCHES */
1563 [C(RESULT_MISS)] = 0x00c5, /* BR_MISP_RETIRED.ALL_BRANCHES */
1564 },
1565 [C(OP_WRITE)] = {
1566 [C(RESULT_ACCESS)] = -1,
1567 [C(RESULT_MISS)] = -1,
1568 },
1569 [C(OP_PREFETCH)] = {
1570 [C(RESULT_ACCESS)] = -1,
1571 [C(RESULT_MISS)] = -1,
1572 },
1573 },
1574};
1575
1576static __initconst const u64 glm_hw_cache_extra_regs
1577 [PERF_COUNT_HW_CACHE_MAX]
1578 [PERF_COUNT_HW_CACHE_OP_MAX]
1579 [PERF_COUNT_HW_CACHE_RESULT_MAX] = {
1580 [C(LL)] = {
1581 [C(OP_READ)] = {
1582 [C(RESULT_ACCESS)] = GLM_DEMAND_READ|
1583 GLM_LLC_ACCESS,
1584 [C(RESULT_MISS)] = GLM_DEMAND_READ|
1585 GLM_LLC_MISS,
1586 },
1587 [C(OP_WRITE)] = {
1588 [C(RESULT_ACCESS)] = GLM_DEMAND_WRITE|
1589 GLM_LLC_ACCESS,
1590 [C(RESULT_MISS)] = GLM_DEMAND_WRITE|
1591 GLM_LLC_MISS,
1592 },
1593 [C(OP_PREFETCH)] = {
1594 [C(RESULT_ACCESS)] = GLM_DEMAND_PREFETCH|
1595 GLM_LLC_ACCESS,
1596 [C(RESULT_MISS)] = GLM_DEMAND_PREFETCH|
1597 GLM_LLC_MISS,
1598 },
1599 },
1600};
1601
1468#define KNL_OT_L2_HITE BIT_ULL(19) /* Other Tile L2 Hit */1602#define KNL_OT_L2_HITE BIT_ULL(19) /* Other Tile L2 Hit */
1469#define KNL_OT_L2_HITF BIT_ULL(20) /* Other Tile L2 Hit */1603#define KNL_OT_L2_HITF BIT_ULL(20) /* Other Tile L2 Hit */
1470#define KNL_MCDRAM_LOCAL BIT_ULL(21)1604#define KNL_MCDRAM_LOCAL BIT_ULL(21)
@@ -3447,7 +3581,7 @@ __init int intel_pmu_init(void) · 1976 unmodified lines
3447 memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,3581 memcpy(hw_cache_extra_regs, slm_hw_cache_extra_regs,
3448 sizeof(hw_cache_extra_regs));3582 sizeof(hw_cache_extra_regs));
3449 3583
3450 intel_pmu_lbr_init_atom();3584 intel_pmu_lbr_init_slm();
3451 3585
3452 x86_pmu.event_constraints = intel_slm_event_constraints;3586 x86_pmu.event_constraints = intel_slm_event_constraints;
3453 x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;3587 x86_pmu.pebs_constraints = intel_slm_pebs_event_constraints;
@@ -3456,6 +3590,30 @@ __init int intel_pmu_init(void) · 2 unmodified lines
3456 pr_cont("Silvermont events, ");3590 pr_cont("Silvermont events, ");
3457 break;3591 break;
3458 3592
3593 case 92: /* 14nm Atom "Goldmont" */
3594 case 95: /* 14nm Atom "Goldmont Denverton" */
3595 memcpy(hw_cache_event_ids, glm_hw_cache_event_ids,
3596 sizeof(hw_cache_event_ids));
3597 memcpy(hw_cache_extra_regs, glm_hw_cache_extra_regs,
3598 sizeof(hw_cache_extra_regs));
3599
3600 intel_pmu_lbr_init_skl();
3601
3602 x86_pmu.event_constraints = intel_slm_event_constraints;
3603 x86_pmu.pebs_constraints = intel_glm_pebs_event_constraints;
3604 x86_pmu.extra_regs = intel_glm_extra_regs;
3605 /*
3606 * It's recommended to use CPU_CLK_UNHALTED.CORE_P + NPEBS
3607 * for precise cycles.
3608 * :pp is identical to :ppp
3609 */
3610 x86_pmu.pebs_aliases = NULL;
3611 x86_pmu.pebs_prec_dist = true;
3612 x86_pmu.lbr_pt_coexist = true;
3613 x86_pmu.flags |= PMU_FL_HAS_RSP_1;
3614 pr_cont("Goldmont events, ");
3615 break;
3616
3459 case 37: /* 32nm Westmere */3617 case 37: /* 32nm Westmere */
3460 case 44: /* 32nm Westmere-EP */3618 case 44: /* 32nm Westmere-EP */
3461 case 47: /* 32nm Westmere-EX */3619 case 47: /* 32nm Westmere-EX */
arch/x86/events/intel/cstate.c+256−291
@@ -91,6 +91,8 @@ · 90 unmodified lines
91#include <asm/cpu_device_id.h>91#include <asm/cpu_device_id.h>
92#include "../perf_event.h"92#include "../perf_event.h"
93 93
94MODULE_LICENSE("GPL");
95
94#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \96#define DEFINE_CSTATE_FORMAT_ATTR(_var, _name, _format) \
95static ssize_t __cstate_##_var##_show(struct kobject *kobj, \97static ssize_t __cstate_##_var##_show(struct kobject *kobj, \
96 struct kobj_attribute *attr, \98 struct kobj_attribute *attr, \
@@ -106,22 +108,27 @@ static ssize_t cstate_get_attr_cpumask(struct device *dev, · 9 unmodified lines
106 struct device_attribute *attr,108 struct device_attribute *attr,
107 char *buf);109 char *buf);
108 110
111/* Model -> events mapping */
112struct cstate_model {
113 unsigned long core_events;
114 unsigned long pkg_events;
115 unsigned long quirks;
116};
117
118/* Quirk flags */
119#define SLM_PKG_C6_USE_C7_MSR (1UL << 0)
120
109struct perf_cstate_msr {121struct perf_cstate_msr {
110 u64 msr;122 u64 msr;
111 struct perf_pmu_events_attr *attr;123 struct perf_pmu_events_attr *attr;
112 bool (*test)(int idx);
113};124};
114 125
115 126
116/* cstate_core PMU */127/* cstate_core PMU */
117
118static struct pmu cstate_core_pmu;128static struct pmu cstate_core_pmu;
119static bool has_cstate_core;129static bool has_cstate_core;
120 130
121enum perf_cstate_core_id {131enum perf_cstate_core_events {
122 /*
123 * cstate_core events
124 */
125 PERF_CSTATE_CORE_C1_RES = 0,132 PERF_CSTATE_CORE_C1_RES = 0,
126 PERF_CSTATE_CORE_C3_RES,133 PERF_CSTATE_CORE_C3_RES,
127 PERF_CSTATE_CORE_C6_RES,134 PERF_CSTATE_CORE_C6_RES,
@@ -130,69 +137,16 @@ enum perf_cstate_core_id { · 2 unmodified lines
130 PERF_CSTATE_CORE_EVENT_MAX,137 PERF_CSTATE_CORE_EVENT_MAX,
131};138};
132 139
133bool test_core(int idx)
134{
135 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
136 boot_cpu_data.x86 != 6)
137 return false;
138
139 switch (boot_cpu_data.x86_model) {
140 case 30: /* 45nm Nehalem */
141 case 26: /* 45nm Nehalem-EP */
142 case 46: /* 45nm Nehalem-EX */
143
144 case 37: /* 32nm Westmere */
145 case 44: /* 32nm Westmere-EP */
146 case 47: /* 32nm Westmere-EX */
147 if (idx == PERF_CSTATE_CORE_C3_RES ||
148 idx == PERF_CSTATE_CORE_C6_RES)
149 return true;
150 break;
151 case 42: /* 32nm SandyBridge */
152 case 45: /* 32nm SandyBridge-E/EN/EP */
153
154 case 58: /* 22nm IvyBridge */
155 case 62: /* 22nm IvyBridge-EP/EX */
156
157 case 60: /* 22nm Haswell Core */
158 case 63: /* 22nm Haswell Server */
159 case 69: /* 22nm Haswell ULT */
160 case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
161
162 case 61: /* 14nm Broadwell Core-M */
163 case 86: /* 14nm Broadwell Xeon D */
164 case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
165 case 79: /* 14nm Broadwell Server */
166
167 case 78: /* 14nm Skylake Mobile */
168 case 94: /* 14nm Skylake Desktop */
169 if (idx == PERF_CSTATE_CORE_C3_RES ||
170 idx == PERF_CSTATE_CORE_C6_RES ||
171 idx == PERF_CSTATE_CORE_C7_RES)
172 return true;
173 break;
174 case 55: /* 22nm Atom "Silvermont" */
175 case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
176 case 76: /* 14nm Atom "Airmont" */
177 if (idx == PERF_CSTATE_CORE_C1_RES ||
178 idx == PERF_CSTATE_CORE_C6_RES)
179 return true;
180 break;
181 }
182
183 return false;
184}
185
186PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00");140PMU_EVENT_ATTR_STRING(c1-residency, evattr_cstate_core_c1, "event=0x00");
187PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01");141PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_core_c3, "event=0x01");
188PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02");142PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_core_c6, "event=0x02");
189PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03");143PMU_EVENT_ATTR_STRING(c7-residency, evattr_cstate_core_c7, "event=0x03");
190 144
191static struct perf_cstate_msr core_msr[] = {145static struct perf_cstate_msr core_msr[] = {
192 [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &evattr_cstate_core_c1, test_core, },146 [PERF_CSTATE_CORE_C1_RES] = { MSR_CORE_C1_RES, &evattr_cstate_core_c1 },
193 [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &evattr_cstate_core_c3, test_core, },147 [PERF_CSTATE_CORE_C3_RES] = { MSR_CORE_C3_RESIDENCY, &evattr_cstate_core_c3 },
194 [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &evattr_cstate_core_c6, test_core, },148 [PERF_CSTATE_CORE_C6_RES] = { MSR_CORE_C6_RESIDENCY, &evattr_cstate_core_c6 },
195 [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &evattr_cstate_core_c7, test_core, },149 [PERF_CSTATE_CORE_C7_RES] = { MSR_CORE_C7_RESIDENCY, &evattr_cstate_core_c7 },
196};150};
197 151
198static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = {152static struct attribute *core_events_attrs[PERF_CSTATE_CORE_EVENT_MAX + 1] = {
@@ -234,18 +188,11 @@ static const struct attribute_group *core_attr_groups[] = { · 35 unmodified lines
234 NULL,188 NULL,
235};189};
236 190
237/* cstate_core PMU end */
238
239
240/* cstate_pkg PMU */191/* cstate_pkg PMU */
241
242static struct pmu cstate_pkg_pmu;192static struct pmu cstate_pkg_pmu;
243static bool has_cstate_pkg;193static bool has_cstate_pkg;
244 194
245enum perf_cstate_pkg_id {195enum perf_cstate_pkg_events {
246 /*
247 * cstate_pkg events
248 */
249 PERF_CSTATE_PKG_C2_RES = 0,196 PERF_CSTATE_PKG_C2_RES = 0,
250 PERF_CSTATE_PKG_C3_RES,197 PERF_CSTATE_PKG_C3_RES,
251 PERF_CSTATE_PKG_C6_RES,198 PERF_CSTATE_PKG_C6_RES,
@@ -257,69 +204,6 @@ enum perf_cstate_pkg_id { · 5 unmodified lines
257 PERF_CSTATE_PKG_EVENT_MAX,204 PERF_CSTATE_PKG_EVENT_MAX,
258};205};
259 206
260bool test_pkg(int idx)
261{
262 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
263 boot_cpu_data.x86 != 6)
264 return false;
265
266 switch (boot_cpu_data.x86_model) {
267 case 30: /* 45nm Nehalem */
268 case 26: /* 45nm Nehalem-EP */
269 case 46: /* 45nm Nehalem-EX */
270
271 case 37: /* 32nm Westmere */
272 case 44: /* 32nm Westmere-EP */
273 case 47: /* 32nm Westmere-EX */
274 if (idx == PERF_CSTATE_CORE_C3_RES ||
275 idx == PERF_CSTATE_CORE_C6_RES ||
276 idx == PERF_CSTATE_CORE_C7_RES)
277 return true;
278 break;
279 case 42: /* 32nm SandyBridge */
280 case 45: /* 32nm SandyBridge-E/EN/EP */
281
282 case 58: /* 22nm IvyBridge */
283 case 62: /* 22nm IvyBridge-EP/EX */
284
285 case 60: /* 22nm Haswell Core */
286 case 63: /* 22nm Haswell Server */
287 case 70: /* 22nm Haswell + GT3e (Intel Iris Pro graphics) */
288
289 case 61: /* 14nm Broadwell Core-M */
290 case 86: /* 14nm Broadwell Xeon D */
291 case 71: /* 14nm Broadwell + GT3e (Intel Iris Pro graphics) */
292 case 79: /* 14nm Broadwell Server */
293
294 case 78: /* 14nm Skylake Mobile */
295 case 94: /* 14nm Skylake Desktop */
296 if (idx == PERF_CSTATE_PKG_C2_RES ||
297 idx == PERF_CSTATE_PKG_C3_RES ||
298 idx == PERF_CSTATE_PKG_C6_RES ||
299 idx == PERF_CSTATE_PKG_C7_RES)
300 return true;
301 break;
302 case 55: /* 22nm Atom "Silvermont" */
303 case 77: /* 22nm Atom "Silvermont Avoton/Rangely" */
304 case 76: /* 14nm Atom "Airmont" */
305 if (idx == PERF_CSTATE_CORE_C6_RES)
306 return true;
307 break;
308 case 69: /* 22nm Haswell ULT */
309 if (idx == PERF_CSTATE_PKG_C2_RES ||
310 idx == PERF_CSTATE_PKG_C3_RES ||
311 idx == PERF_CSTATE_PKG_C6_RES ||
312 idx == PERF_CSTATE_PKG_C7_RES ||
313 idx == PERF_CSTATE_PKG_C8_RES ||
314 idx == PERF_CSTATE_PKG_C9_RES ||
315 idx == PERF_CSTATE_PKG_C10_RES)
316 return true;
317 break;
318 }
319
320 return false;
321}
322
323PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00");207PMU_EVENT_ATTR_STRING(c2-residency, evattr_cstate_pkg_c2, "event=0x00");
324PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01");208PMU_EVENT_ATTR_STRING(c3-residency, evattr_cstate_pkg_c3, "event=0x01");
325PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02");209PMU_EVENT_ATTR_STRING(c6-residency, evattr_cstate_pkg_c6, "event=0x02");
@@ -329,13 +213,13 @@ PMU_EVENT_ATTR_STRING(c9-residency, evattr_cstate_pkg_c9, "event=0x05"); · 3 unmodified lines
329PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06");213PMU_EVENT_ATTR_STRING(c10-residency, evattr_cstate_pkg_c10, "event=0x06");
330 214
331static struct perf_cstate_msr pkg_msr[] = {215static struct perf_cstate_msr pkg_msr[] = {
332 [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &evattr_cstate_pkg_c2, test_pkg, },216 [PERF_CSTATE_PKG_C2_RES] = { MSR_PKG_C2_RESIDENCY, &evattr_cstate_pkg_c2 },
333 [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &evattr_cstate_pkg_c3, test_pkg, },217 [PERF_CSTATE_PKG_C3_RES] = { MSR_PKG_C3_RESIDENCY, &evattr_cstate_pkg_c3 },
334 [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &evattr_cstate_pkg_c6, test_pkg, },218 [PERF_CSTATE_PKG_C6_RES] = { MSR_PKG_C6_RESIDENCY, &evattr_cstate_pkg_c6 },
335 [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &evattr_cstate_pkg_c7, test_pkg, },219 [PERF_CSTATE_PKG_C7_RES] = { MSR_PKG_C7_RESIDENCY, &evattr_cstate_pkg_c7 },
336 [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &evattr_cstate_pkg_c8, test_pkg, },220 [PERF_CSTATE_PKG_C8_RES] = { MSR_PKG_C8_RESIDENCY, &evattr_cstate_pkg_c8 },
337 [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &evattr_cstate_pkg_c9, test_pkg, },221 [PERF_CSTATE_PKG_C9_RES] = { MSR_PKG_C9_RESIDENCY, &evattr_cstate_pkg_c9 },
338 [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &evattr_cstate_pkg_c10, test_pkg, },222 [PERF_CSTATE_PKG_C10_RES] = { MSR_PKG_C10_RESIDENCY, &evattr_cstate_pkg_c10 },
339};223};
340 224
341static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = {225static struct attribute *pkg_events_attrs[PERF_CSTATE_PKG_EVENT_MAX + 1] = {
@@ -366,8 +250,6 @@ static const struct attribute_group *pkg_attr_groups[] = { · 24 unmodified lines
366 NULL,250 NULL,
367};251};
368 252
369/* cstate_pkg PMU end*/
370
371static ssize_t cstate_get_attr_cpumask(struct device *dev,253static ssize_t cstate_get_attr_cpumask(struct device *dev,
372 struct device_attribute *attr,254 struct device_attribute *attr,
373 char *buf)255 char *buf)
@@ -385,7 +267,7 @@ static ssize_t cstate_get_attr_cpumask(struct device *dev, · 11 unmodified lines
385static int cstate_pmu_event_init(struct perf_event *event)267static int cstate_pmu_event_init(struct perf_event *event)
386{268{
387 u64 cfg = event->attr.config;269 u64 cfg = event->attr.config;
388 int ret = 0;270 int cpu;
389 271
390 if (event->attr.type != event->pmu->type)272 if (event->attr.type != event->pmu->type)
391 return -ENOENT;273 return -ENOENT;
@@ -400,26 +282,36 @@ static int cstate_pmu_event_init(struct perf_event *event) · 8 unmodified lines
400 event->attr.sample_period) /* no sampling */282 event->attr.sample_period) /* no sampling */
401 return -EINVAL;283 return -EINVAL;
402 284
285 if (event->cpu < 0)
286 return -EINVAL;
287
403 if (event->pmu == &cstate_core_pmu) {288 if (event->pmu == &cstate_core_pmu) {
404 if (cfg >= PERF_CSTATE_CORE_EVENT_MAX)289 if (cfg >= PERF_CSTATE_CORE_EVENT_MAX)
405 return -EINVAL;290 return -EINVAL;
406 if (!core_msr[cfg].attr)291 if (!core_msr[cfg].attr)
407 return -EINVAL;292 return -EINVAL;
408 event->hw.event_base = core_msr[cfg].msr;293 event->hw.event_base = core_msr[cfg].msr;
294 cpu = cpumask_any_and(&cstate_core_cpu_mask,
295 topology_sibling_cpumask(event->cpu));
409 } else if (event->pmu == &cstate_pkg_pmu) {296 } else if (event->pmu == &cstate_pkg_pmu) {
410 if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)297 if (cfg >= PERF_CSTATE_PKG_EVENT_MAX)
411 return -EINVAL;298 return -EINVAL;
412 if (!pkg_msr[cfg].attr)299 if (!pkg_msr[cfg].attr)
413 return -EINVAL;300 return -EINVAL;
414 event->hw.event_base = pkg_msr[cfg].msr;301 event->hw.event_base = pkg_msr[cfg].msr;
415 } else302 cpu = cpumask_any_and(&cstate_pkg_cpu_mask,
303 topology_core_cpumask(event->cpu));
304 } else {
416 return -ENOENT;305 return -ENOENT;
306 }
307
308 if (cpu >= nr_cpu_ids)
309 return -ENODEV;
417 310
418 /* must be done before validate_group */311 event->cpu = cpu;
419 event->hw.config = cfg;312 event->hw.config = cfg;
420 event->hw.idx = -1;313 event->hw.idx = -1;
421 314 return 0;
422 return ret;
423}315}
424 316
425static inline u64 cstate_pmu_read_counter(struct perf_event *event)317static inline u64 cstate_pmu_read_counter(struct perf_event *event)
@@ -469,172 +361,91 @@ static int cstate_pmu_event_add(struct perf_event *event, int mode) · 43 unmodified lines
469 return 0;361 return 0;
470}362}
471 363
364/*
365 * Check if exiting cpu is the designated reader. If so migrate the
366 * events when there is a valid target available
367 */
472static void cstate_cpu_exit(int cpu)368static void cstate_cpu_exit(int cpu)
473{369{
474 int i, id, target;370 unsigned int target;
475 371
476 /* cpu exit for cstate core */372 if (has_cstate_core &&
477 if (has_cstate_core) {373 cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask)) {
478 id = topology_core_id(cpu);374
479 target = -1;375 target = cpumask_any_but(topology_sibling_cpumask(cpu), cpu);
480 376 /* Migrate events if there is a valid target */
481 for_each_online_cpu(i) {377 if (target < nr_cpu_ids) {
482 if (i == cpu)
483 continue;
484 if (id == topology_core_id(i)) {
485 target = i;
486 break;
487 }
488 }
489 if (cpumask_test_and_clear_cpu(cpu, &cstate_core_cpu_mask) && target >= 0)
490 cpumask_set_cpu(target, &cstate_core_cpu_mask);378 cpumask_set_cpu(target, &cstate_core_cpu_mask);
491 WARN_ON(cpumask_empty(&cstate_core_cpu_mask));
492 if (target >= 0)
493 perf_pmu_migrate_context(&cstate_core_pmu, cpu, target);379 perf_pmu_migrate_context(&cstate_core_pmu, cpu, target);
380 }
494 }381 }
495 382
496 /* cpu exit for cstate pkg */383 if (has_cstate_pkg &&
497 if (has_cstate_pkg) {384 cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask)) {
498 id = topology_physical_package_id(cpu);385
499 target = -1;386 target = cpumask_any_but(topology_core_cpumask(cpu), cpu);
500 387 /* Migrate events if there is a valid target */
501 for_each_online_cpu(i) {388 if (target < nr_cpu_ids) {
502 if (i == cpu)
503 continue;
504 if (id == topology_physical_package_id(i)) {
505 target = i;
506 break;
507 }
508 }
509 if (cpumask_test_and_clear_cpu(cpu, &cstate_pkg_cpu_mask) && target >= 0)
510 cpumask_set_cpu(target, &cstate_pkg_cpu_mask);389 cpumask_set_cpu(target, &cstate_pkg_cpu_mask);
511 WARN_ON(cpumask_empty(&cstate_pkg_cpu_mask));
512 if (target >= 0)
513 perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target);390 perf_pmu_migrate_context(&cstate_pkg_pmu, cpu, target);
391 }
514 }392 }
515}393}
516 394
517static void cstate_cpu_init(int cpu)395static void cstate_cpu_init(int cpu)
518{396{
519 int i, id;397 unsigned int target;
520 398
521 /* cpu init for cstate core */399 /*
522 if (has_cstate_core) {400 * If this is the first online thread of that core, set it in
523 id = topology_core_id(cpu);401 * the core cpu mask as the designated reader.
524 for_each_cpu(i, &cstate_core_cpu_mask) {402 */
525 if (id == topology_core_id(i))403 target = cpumask_any_and(&cstate_core_cpu_mask,
526 break;404 topology_sibling_cpumask(cpu));
527 }
528 if (i >= nr_cpu_ids)
529 cpumask_set_cpu(cpu, &cstate_core_cpu_mask);
530 }
531 405
532 /* cpu init for cstate pkg */406 if (has_cstate_core && target >= nr_cpu_ids)
533 if (has_cstate_pkg) {407 cpumask_set_cpu(cpu, &cstate_core_cpu_mask);
534 id = topology_physical_package_id(cpu);408
535 for_each_cpu(i, &cstate_pkg_cpu_mask) {409 /*
536 if (id == topology_physical_package_id(i))410 * If this is the first online thread of that package, set it
537 break;411 * in the package cpu mask as the designated reader.
538 }412 */
539 if (i >= nr_cpu_ids)413 target = cpumask_any_and(&cstate_pkg_cpu_mask,
540 cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);414 topology_core_cpumask(cpu));
541 }415 if (has_cstate_pkg && target >= nr_cpu_ids)
416 cpumask_set_cpu(cpu, &cstate_pkg_cpu_mask);
542}417}
543 418
544static int cstate_cpu_notifier(struct notifier_block *self,419static int cstate_cpu_notifier(struct notifier_block *self,
545 unsigned long action, void *hcpu)420 unsigned long action, void *hcpu)
546{421{
547 unsigned int cpu = (long)hcpu;422 unsigned int cpu = (long)hcpu;
548 423
549 switch (action & ~CPU_TASKS_FROZEN) {424 switch (action & ~CPU_TASKS_FROZEN) {
550 case CPU_UP_PREPARE:
551 break;
552 case CPU_STARTING:425 case CPU_STARTING:
553 cstate_cpu_init(cpu);426 cstate_cpu_init(cpu);
554 break;427 break;
555 case CPU_UP_CANCELED:
556 case CPU_DYING:
557 break;
558 case CPU_ONLINE:
559 case CPU_DEAD:
560 break;
561 case CPU_DOWN_PREPARE:428 case CPU_DOWN_PREPARE:
562 cstate_cpu_exit(cpu);429 cstate_cpu_exit(cpu);
563 break;430 break;
564 default:431 default:
565 break;432 break;
566 }433 }
567
568 return NOTIFY_OK;434 return NOTIFY_OK;
569}435}
570 436
571/*437static struct notifier_block cstate_cpu_nb = {
572 * Probe the cstate events and insert the available one into sysfs attrs438 .notifier_call = cstate_cpu_notifier,
573 * Return false if there is no available events.439 .priority = CPU_PRI_PERF + 1,
574 */440};
575static bool cstate_probe_msr(struct perf_cstate_msr *msr,
576 struct attribute **events_attrs,
577 int max_event_nr)
578{
579 int i, j = 0;
580 u64 val;
581
582 /* Probe the cstate events. */
583 for (i = 0; i < max_event_nr; i++) {
584 if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
585 msr[i].attr = NULL;
586 }
587
588 /* List remaining events in the sysfs attrs. */
589 for (i = 0; i < max_event_nr; i++) {
590 if (msr[i].attr)
591 events_attrs[j++] = &msr[i].attr->attr.attr;
592 }
593 events_attrs[j] = NULL;
594
595 return (j > 0) ? true : false;
596}
597
598static int __init cstate_init(void)
599{
600 /* SLM has different MSR for PKG C6 */
601 switch (boot_cpu_data.x86_model) {
602 case 55:
603 case 76:
604 case 77:
605 pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
606 }
607
608 if (cstate_probe_msr(core_msr, core_events_attrs, PERF_CSTATE_CORE_EVENT_MAX))
609 has_cstate_core = true;
610
611 if (cstate_probe_msr(pkg_msr, pkg_events_attrs, PERF_CSTATE_PKG_EVENT_MAX))
612 has_cstate_pkg = true;
613
614 return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
615}
616
617static void __init cstate_cpumask_init(void)
618{
619 int cpu;
620
621 cpu_notifier_register_begin();
622
623 for_each_online_cpu(cpu)
624 cstate_cpu_init(cpu);
625
626 __perf_cpu_notifier(cstate_cpu_notifier);
627
628 cpu_notifier_register_done();
629}
630 441
631static struct pmu cstate_core_pmu = {442static struct pmu cstate_core_pmu = {
632 .attr_groups = core_attr_groups,443 .attr_groups = core_attr_groups,
633 .name = "cstate_core",444 .name = "cstate_core",
634 .task_ctx_nr = perf_invalid_context,445 .task_ctx_nr = perf_invalid_context,
635 .event_init = cstate_pmu_event_init,446 .event_init = cstate_pmu_event_init,
636 .add = cstate_pmu_event_add, /* must have */447 .add = cstate_pmu_event_add,
637 .del = cstate_pmu_event_del, /* must have */448 .del = cstate_pmu_event_del,
638 .start = cstate_pmu_event_start,449 .start = cstate_pmu_event_start,
639 .stop = cstate_pmu_event_stop,450 .stop = cstate_pmu_event_stop,
640 .read = cstate_pmu_event_update,451 .read = cstate_pmu_event_update,
@@ -646,49 +457,203 @@ static struct pmu cstate_pkg_pmu = { · 5 unmodified lines
646 .name = "cstate_pkg",457 .name = "cstate_pkg",
647 .task_ctx_nr = perf_invalid_context,458 .task_ctx_nr = perf_invalid_context,
648 .event_init = cstate_pmu_event_init,459 .event_init = cstate_pmu_event_init,
649 .add = cstate_pmu_event_add, /* must have */460 .add = cstate_pmu_event_add,
650 .del = cstate_pmu_event_del, /* must have */461 .del = cstate_pmu_event_del,
651 .start = cstate_pmu_event_start,462 .start = cstate_pmu_event_start,
652 .stop = cstate_pmu_event_stop,463 .stop = cstate_pmu_event_stop,
653 .read = cstate_pmu_event_update,464 .read = cstate_pmu_event_update,
654 .capabilities = PERF_PMU_CAP_NO_INTERRUPT,465 .capabilities = PERF_PMU_CAP_NO_INTERRUPT,
655};466};
656 467
657static void __init cstate_pmus_register(void)468static const struct cstate_model nhm_cstates __initconst = {
469 .core_events = BIT(PERF_CSTATE_CORE_C3_RES) |
470 BIT(PERF_CSTATE_CORE_C6_RES),
471
472 .pkg_events = BIT(PERF_CSTATE_PKG_C3_RES) |
473 BIT(PERF_CSTATE_PKG_C6_RES) |
474 BIT(PERF_CSTATE_PKG_C7_RES),
475};
476
477static const struct cstate_model snb_cstates __initconst = {
478 .core_events = BIT(PERF_CSTATE_CORE_C3_RES) |
479 BIT(PERF_CSTATE_CORE_C6_RES) |
480 BIT(PERF_CSTATE_CORE_C7_RES),
481
482 .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
483 BIT(PERF_CSTATE_PKG_C3_RES) |
484 BIT(PERF_CSTATE_PKG_C6_RES) |
485 BIT(PERF_CSTATE_PKG_C7_RES),
486};
487
488static const struct cstate_model hswult_cstates __initconst = {
489 .core_events = BIT(PERF_CSTATE_CORE_C3_RES) |
490 BIT(PERF_CSTATE_CORE_C6_RES) |
491 BIT(PERF_CSTATE_CORE_C7_RES),
492
493 .pkg_events = BIT(PERF_CSTATE_PKG_C2_RES) |
494 BIT(PERF_CSTATE_PKG_C3_RES) |
495 BIT(PERF_CSTATE_PKG_C6_RES) |
496 BIT(PERF_CSTATE_PKG_C7_RES) |
497 BIT(PERF_CSTATE_PKG_C8_RES) |
498 BIT(PERF_CSTATE_PKG_C9_RES) |
499 BIT(PERF_CSTATE_PKG_C10_RES),
500};
501
502static const struct cstate_model slm_cstates __initconst = {
503 .core_events = BIT(PERF_CSTATE_CORE_C1_RES) |
504 BIT(PERF_CSTATE_CORE_C6_RES),
505
506 .pkg_events = BIT(PERF_CSTATE_PKG_C6_RES),
507 .quirks = SLM_PKG_C6_USE_C7_MSR,
508};
509
510#define X86_CSTATES_MODEL(model, states) \
511 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long) &(states) }
512
513static const struct x86_cpu_id intel_cstates_match[] __initconst = {
514 X86_CSTATES_MODEL(30, nhm_cstates), /* 45nm Nehalem */
515 X86_CSTATES_MODEL(26, nhm_cstates), /* 45nm Nehalem-EP */
516 X86_CSTATES_MODEL(46, nhm_cstates), /* 45nm Nehalem-EX */
517
518 X86_CSTATES_MODEL(37, nhm_cstates), /* 32nm Westmere */
519 X86_CSTATES_MODEL(44, nhm_cstates), /* 32nm Westmere-EP */
520 X86_CSTATES_MODEL(47, nhm_cstates), /* 32nm Westmere-EX */
521
522 X86_CSTATES_MODEL(42, snb_cstates), /* 32nm SandyBridge */
523 X86_CSTATES_MODEL(45, snb_cstates), /* 32nm SandyBridge-E/EN/EP */
524
525 X86_CSTATES_MODEL(58, snb_cstates), /* 22nm IvyBridge */
526 X86_CSTATES_MODEL(62, snb_cstates), /* 22nm IvyBridge-EP/EX */
527
528 X86_CSTATES_MODEL(60, snb_cstates), /* 22nm Haswell Core */
529 X86_CSTATES_MODEL(63, snb_cstates), /* 22nm Haswell Server */
530 X86_CSTATES_MODEL(70, snb_cstates), /* 22nm Haswell + GT3e */
531
532 X86_CSTATES_MODEL(69, hswult_cstates), /* 22nm Haswell ULT */
533
534 X86_CSTATES_MODEL(55, slm_cstates), /* 22nm Atom Silvermont */
535 X86_CSTATES_MODEL(77, slm_cstates), /* 22nm Atom Avoton/Rangely */
536 X86_CSTATES_MODEL(76, slm_cstates), /* 22nm Atom Airmont */
537
538 X86_CSTATES_MODEL(61, snb_cstates), /* 14nm Broadwell Core-M */
539 X86_CSTATES_MODEL(86, snb_cstates), /* 14nm Broadwell Xeon D */
540 X86_CSTATES_MODEL(71, snb_cstates), /* 14nm Broadwell + GT3e */
541 X86_CSTATES_MODEL(79, snb_cstates), /* 14nm Broadwell Server */
542
543 X86_CSTATES_MODEL(78, snb_cstates), /* 14nm Skylake Mobile */
544 X86_CSTATES_MODEL(94, snb_cstates), /* 14nm Skylake Desktop */
545 { },
546};
547MODULE_DEVICE_TABLE(x86cpu, intel_cstates_match);
548
549/*
550 * Probe the cstate events and insert the available one into sysfs attrs
551 * Return false if there are no available events.
552 */
553static bool __init cstate_probe_msr(const unsigned long evmsk, int max,
554 struct perf_cstate_msr *msr,
555 struct attribute **attrs)
658{556{
659 int err;557 bool found = false;
558 unsigned int bit;
559 u64 val;
560
561 for (bit = 0; bit < max; bit++) {
562 if (test_bit(bit, &evmsk) && !rdmsrl_safe(msr[bit].msr, &val)) {
563 *attrs++ = &msr[bit].attr->attr.attr;
564 found = true;
565 } else {
566 msr[bit].attr = NULL;
567 }
568 }
569 *attrs = NULL;
570
571 return found;
572}
573
574static int __init cstate_probe(const struct cstate_model *cm)
575{
576 /* SLM has different MSR for PKG C6 */
577 if (cm->quirks & SLM_PKG_C6_USE_C7_MSR)
578 pkg_msr[PERF_CSTATE_PKG_C6_RES].msr = MSR_PKG_C7_RESIDENCY;
579
580 has_cstate_core = cstate_probe_msr(cm->core_events,
581 PERF_CSTATE_CORE_EVENT_MAX,
582 core_msr, core_events_attrs);
583
584 has_cstate_pkg = cstate_probe_msr(cm->pkg_events,
585 PERF_CSTATE_PKG_EVENT_MAX,
586 pkg_msr, pkg_events_attrs);
587
588 return (has_cstate_core || has_cstate_pkg) ? 0 : -ENODEV;
589}
590
591static inline void cstate_cleanup(void)
592{
593 if (has_cstate_core)
594 perf_pmu_unregister(&cstate_core_pmu);
595
596 if (has_cstate_pkg)
597 perf_pmu_unregister(&cstate_pkg_pmu);
598}
599
600static int __init cstate_init(void)
601{
602 int cpu, err;
603
604 cpu_notifier_register_begin();
605 for_each_online_cpu(cpu)
606 cstate_cpu_init(cpu);
660 607
661 if (has_cstate_core) {608 if (has_cstate_core) {
662 err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);609 err = perf_pmu_register(&cstate_core_pmu, cstate_core_pmu.name, -1);
663 if (WARN_ON(err))610 if (err) {
664 pr_info("Failed to register PMU %s error %d\n",611 has_cstate_core = false;
665 cstate_core_pmu.name, err);612 pr_info("Failed to register cstate core pmu\n");
613 goto out;
614 }
666 }615 }
667 616
668 if (has_cstate_pkg) {617 if (has_cstate_pkg) {
669 err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1);618 err = perf_pmu_register(&cstate_pkg_pmu, cstate_pkg_pmu.name, -1);
670 if (WARN_ON(err))619 if (err) {
671 pr_info("Failed to register PMU %s error %d\n",620 has_cstate_pkg = false;
672 cstate_pkg_pmu.name, err);621 pr_info("Failed to register cstate pkg pmu\n");
622 cstate_cleanup();
623 goto out;
624 }
673 }625 }
626 __register_cpu_notifier(&cstate_cpu_nb);
627out:
628 cpu_notifier_register_done();
629 return err;
674}630}
675 631
676static int __init cstate_pmu_init(void)632static int __init cstate_pmu_init(void)
677{633{
634 const struct x86_cpu_id *id;
678 int err;635 int err;
679 636
680 if (cpu_has_hypervisor)637 if (boot_cpu_has(X86_FEATURE_HYPERVISOR))
638 return -ENODEV;
639
640 id = x86_match_cpu(intel_cstates_match);
641 if (!id)
681 return -ENODEV;642 return -ENODEV;
682 643
683 err = cstate_init();644 err = cstate_probe((const struct cstate_model *) id->driver_data);
684 if (err)645 if (err)
685 return err;646 return err;
686 647
687 cstate_cpumask_init();648 return cstate_init();
688
689 cstate_pmus_register();
690
691 return 0;
692}649}
650module_init(cstate_pmu_init);
693 651
694device_initcall(cstate_pmu_init);652static void __exit cstate_pmu_exit(void)
653{
654 cpu_notifier_register_begin();
655 __unregister_cpu_notifier(&cstate_cpu_nb);
656 cstate_cleanup();
657 cpu_notifier_register_done();
658}
659module_exit(cstate_pmu_exit);
arch/x86/events/intel/ds.c+6−0
@@ -645,6 +645,12 @@ struct event_constraint intel_slm_pebs_event_constraints[] = { · 644 unmodified lines
645 EVENT_CONSTRAINT_END645 EVENT_CONSTRAINT_END
646};646};
647 647
648struct event_constraint intel_glm_pebs_event_constraints[] = {
649 /* Allow all events as PEBS with no flags */
650 INTEL_ALL_EVENT_CONSTRAINT(0, 0x1),
651 EVENT_CONSTRAINT_END
652};
653
648struct event_constraint intel_nehalem_pebs_event_constraints[] = {654struct event_constraint intel_nehalem_pebs_event_constraints[] = {
649 INTEL_PLD_CONSTRAINT(0x100b, 0xf), /* MEM_INST_RETIRED.* */655 INTEL_PLD_CONSTRAINT(0x100b, 0xf), /* MEM_INST_RETIRED.* */
650 INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */656 INTEL_FLAGS_EVENT_CONSTRAINT(0x0f, 0xf), /* MEM_UNCORE_RETIRED.* */
arch/x86/events/intel/lbr.c+30−1
@@ -14,7 +14,8 @@ enum { · 13 unmodified lines
14 LBR_FORMAT_EIP_FLAGS = 0x03,14 LBR_FORMAT_EIP_FLAGS = 0x03,
15 LBR_FORMAT_EIP_FLAGS2 = 0x04,15 LBR_FORMAT_EIP_FLAGS2 = 0x04,
16 LBR_FORMAT_INFO = 0x05,16 LBR_FORMAT_INFO = 0x05,
17 LBR_FORMAT_MAX_KNOWN = LBR_FORMAT_INFO,17 LBR_FORMAT_TIME = 0x06,
18 LBR_FORMAT_MAX_KNOWN = LBR_FORMAT_TIME,
18};19};
19 20
20static enum {21static enum {
@@ -464,6 +465,16 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc) · 443 unmodified lines
464 abort = !!(info & LBR_INFO_ABORT);465 abort = !!(info & LBR_INFO_ABORT);
465 cycles = (info & LBR_INFO_CYCLES);466 cycles = (info & LBR_INFO_CYCLES);
466 }467 }
468
469 if (lbr_format == LBR_FORMAT_TIME) {
470 mis = !!(from & LBR_FROM_FLAG_MISPRED);
471 pred = !mis;
472 skip = 1;
473 cycles = ((to >> 48) & LBR_INFO_CYCLES);
474
475 to = (u64)((((s64)to) << 16) >> 16);
476 }
477
467 if (lbr_flags & LBR_EIP_FLAGS) {478 if (lbr_flags & LBR_EIP_FLAGS) {
468 mis = !!(from & LBR_FROM_FLAG_MISPRED);479 mis = !!(from & LBR_FROM_FLAG_MISPRED);
469 pred = !mis;480 pred = !mis;
@@ -1049,6 +1060,24 @@ void __init intel_pmu_lbr_init_atom(void) · 579 unmodified lines
1049 pr_cont("8-deep LBR, ");1060 pr_cont("8-deep LBR, ");
1050}1061}
1051 1062
1063/* slm */
1064void __init intel_pmu_lbr_init_slm(void)
1065{
1066 x86_pmu.lbr_nr = 8;
1067 x86_pmu.lbr_tos = MSR_LBR_TOS;
1068 x86_pmu.lbr_from = MSR_LBR_CORE_FROM;
1069 x86_pmu.lbr_to = MSR_LBR_CORE_TO;
1070
1071 x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
1072 x86_pmu.lbr_sel_map = nhm_lbr_sel_map;
1073
1074 /*
1075 * SW branch filter usage:
1076 * - compensate for lack of HW filter
1077 */
1078 pr_cont("8-deep LBR, ");
1079}
1080
1052/* Knights Landing */1081/* Knights Landing */
1053void intel_pmu_lbr_init_knl(void)1082void intel_pmu_lbr_init_knl(void)
1054{1083{
arch/x86/events/intel/pt.c+250−68
@@ -67,11 +67,13 @@ static struct pt_cap_desc { · 66 unmodified lines
67 PT_CAP(max_subleaf, 0, CR_EAX, 0xffffffff),67 PT_CAP(max_subleaf, 0, CR_EAX, 0xffffffff),
68 PT_CAP(cr3_filtering, 0, CR_EBX, BIT(0)),68 PT_CAP(cr3_filtering, 0, CR_EBX, BIT(0)),
69 PT_CAP(psb_cyc, 0, CR_EBX, BIT(1)),69 PT_CAP(psb_cyc, 0, CR_EBX, BIT(1)),
70 PT_CAP(ip_filtering, 0, CR_EBX, BIT(2)),
70 PT_CAP(mtc, 0, CR_EBX, BIT(3)),71 PT_CAP(mtc, 0, CR_EBX, BIT(3)),
71 PT_CAP(topa_output, 0, CR_ECX, BIT(0)),72 PT_CAP(topa_output, 0, CR_ECX, BIT(0)),
72 PT_CAP(topa_multiple_entries, 0, CR_ECX, BIT(1)),73 PT_CAP(topa_multiple_entries, 0, CR_ECX, BIT(1)),
73 PT_CAP(single_range_output, 0, CR_ECX, BIT(2)),74 PT_CAP(single_range_output, 0, CR_ECX, BIT(2)),
74 PT_CAP(payloads_lip, 0, CR_ECX, BIT(31)),75 PT_CAP(payloads_lip, 0, CR_ECX, BIT(31)),
76 PT_CAP(num_address_ranges, 1, CR_EAX, 0x3),
75 PT_CAP(mtc_periods, 1, CR_EAX, 0xffff0000),77 PT_CAP(mtc_periods, 1, CR_EAX, 0xffff0000),
76 PT_CAP(cycle_thresholds, 1, CR_EBX, 0xffff),78 PT_CAP(cycle_thresholds, 1, CR_EBX, 0xffff),
77 PT_CAP(psb_periods, 1, CR_EBX, 0xffff0000),79 PT_CAP(psb_periods, 1, CR_EBX, 0xffff0000),
@@ -125,9 +127,46 @@ static struct attribute_group pt_format_group = { · 47 unmodified lines
125 .attrs = pt_formats_attr,127 .attrs = pt_formats_attr,
126};128};
127 129
130static ssize_t
131pt_timing_attr_show(struct device *dev, struct device_attribute *attr,
132 char *page)
133{
134 struct perf_pmu_events_attr *pmu_attr =
135 container_of(attr, struct perf_pmu_events_attr, attr);
136
137 switch (pmu_attr->id) {
138 case 0:
139 return sprintf(page, "%lu\n", pt_pmu.max_nonturbo_ratio);
140 case 1:
141 return sprintf(page, "%u:%u\n",
142 pt_pmu.tsc_art_num,
143 pt_pmu.tsc_art_den);
144 default:
145 break;
146 }
147
148 return -EINVAL;
149}
150
151PMU_EVENT_ATTR(max_nonturbo_ratio, timing_attr_max_nonturbo_ratio, 0,
152 pt_timing_attr_show);
153PMU_EVENT_ATTR(tsc_art_ratio, timing_attr_tsc_art_ratio, 1,
154 pt_timing_attr_show);
155
156static struct attribute *pt_timing_attr[] = {
157 &timing_attr_max_nonturbo_ratio.attr.attr,
158 &timing_attr_tsc_art_ratio.attr.attr,
159 NULL,
160};
161
162static struct attribute_group pt_timing_group = {
163 .attrs = pt_timing_attr,
164};
165
128static const struct attribute_group *pt_attr_groups[] = {166static const struct attribute_group *pt_attr_groups[] = {
129 &pt_cap_group,167 &pt_cap_group,
130 &pt_format_group,168 &pt_format_group,
169 &pt_timing_group,
131 NULL,170 NULL,
132};171};
133 172
@@ -140,6 +179,23 @@ static int __init pt_pmu_hw_init(void) · 6 unmodified lines
140 int ret;179 int ret;
141 long i;180 long i;
142 181
182 rdmsrl(MSR_PLATFORM_INFO, reg);
183 pt_pmu.max_nonturbo_ratio = (reg & 0xff00) >> 8;
184
185 /*
186 * if available, read in TSC to core crystal clock ratio,
187 * otherwise, zero for numerator stands for "not enumerated"
188 * as per SDM
189 */
190 if (boot_cpu_data.cpuid_level >= CPUID_TSC_LEAF) {
191 u32 eax, ebx, ecx, edx;
192
193 cpuid(CPUID_TSC_LEAF, &eax, &ebx, &ecx, &edx);
194
195 pt_pmu.tsc_art_num = ebx;
196 pt_pmu.tsc_art_den = eax;
197 }
198
143 if (boot_cpu_has(X86_FEATURE_VMX)) {199 if (boot_cpu_has(X86_FEATURE_VMX)) {
144 /*200 /*
145 * Intel SDM, 36.5 "Tracing post-VMXON" says that201 * Intel SDM, 36.5 "Tracing post-VMXON" says that
@@ -263,6 +319,75 @@ static bool pt_event_valid(struct perf_event *event) · 117 unmodified lines
263 * These all are cpu affine and operate on a local PT319 * These all are cpu affine and operate on a local PT
264 */320 */
265 321
322/* Address ranges and their corresponding msr configuration registers */
323static const struct pt_address_range {
324 unsigned long msr_a;
325 unsigned long msr_b;
326 unsigned int reg_off;
327} pt_address_ranges[] = {
328 {
329 .msr_a = MSR_IA32_RTIT_ADDR0_A,
330 .msr_b = MSR_IA32_RTIT_ADDR0_B,
331 .reg_off = RTIT_CTL_ADDR0_OFFSET,
332 },
333 {
334 .msr_a = MSR_IA32_RTIT_ADDR1_A,
335 .msr_b = MSR_IA32_RTIT_ADDR1_B,
336 .reg_off = RTIT_CTL_ADDR1_OFFSET,
337 },
338 {
339 .msr_a = MSR_IA32_RTIT_ADDR2_A,
340 .msr_b = MSR_IA32_RTIT_ADDR2_B,
341 .reg_off = RTIT_CTL_ADDR2_OFFSET,
342 },
343 {
344 .msr_a = MSR_IA32_RTIT_ADDR3_A,
345 .msr_b = MSR_IA32_RTIT_ADDR3_B,
346 .reg_off = RTIT_CTL_ADDR3_OFFSET,
347 }
348};
349
350static u64 pt_config_filters(struct perf_event *event)
351{
352 struct pt_filters *filters = event->hw.addr_filters;
353 struct pt *pt = this_cpu_ptr(&pt_ctx);
354 unsigned int range = 0;
355 u64 rtit_ctl = 0;
356
357 if (!filters)
358 return 0;
359
360 perf_event_addr_filters_sync(event);
361
362 for (range = 0; range < filters->nr_filters; range++) {
363 struct pt_filter *filter = &filters->filter[range];
364
365 /*
366 * Note, if the range has zero start/end addresses due
367 * to its dynamic object not being loaded yet, we just
368 * go ahead and program zeroed range, which will simply
369 * produce no data. Note^2: if executable code at 0x0
370 * is a concern, we can set up an "invalid" configuration
371 * such as msr_b < msr_a.
372 */
373
374 /* avoid redundant msr writes */
375 if (pt->filters.filter[range].msr_a != filter->msr_a) {
376 wrmsrl(pt_address_ranges[range].msr_a, filter->msr_a);
377 pt->filters.filter[range].msr_a = filter->msr_a;
378 }
379
380 if (pt->filters.filter[range].msr_b != filter->msr_b) {
381 wrmsrl(pt_address_ranges[range].msr_b, filter->msr_b);
382 pt->filters.filter[range].msr_b = filter->msr_b;
383 }
384
385 rtit_ctl |= filter->config << pt_address_ranges[range].reg_off;
386 }
387
388 return rtit_ctl;
389}
390
266static void pt_config(struct perf_event *event)391static void pt_config(struct perf_event *event)
267{392{
268 u64 reg;393 u64 reg;
@@ -272,7 +397,8 @@ static void pt_config(struct perf_event *event) · 3 unmodified lines
272 wrmsrl(MSR_IA32_RTIT_STATUS, 0);397 wrmsrl(MSR_IA32_RTIT_STATUS, 0);
273 }398 }
274 399
275 reg = RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;400 reg = pt_config_filters(event);
401 reg |= RTIT_CTL_TOPA | RTIT_CTL_BRANCH_EN | RTIT_CTL_TRACEEN;
276 402
277 if (!event->attr.exclude_kernel)403 if (!event->attr.exclude_kernel)
278 reg |= RTIT_CTL_OS;404 reg |= RTIT_CTL_OS;
@@ -921,24 +1047,80 @@ static void pt_buffer_free_aux(void *data) · 642 unmodified lines
921 kfree(buf);1047 kfree(buf);
922}1048}
923 1049
924/**1050static int pt_addr_filters_init(struct perf_event *event)
925 * pt_buffer_is_full() - check if the buffer is full
926 * @buf: PT buffer.
927 * @pt: Per-cpu pt handle.
928 *
929 * If the user hasn't read data from the output region that aux_head
930 * points to, the buffer is considered full: the user needs to read at
931 * least this region and update aux_tail to point past it.
932 */
933static bool pt_buffer_is_full(struct pt_buffer *buf, struct pt *pt)
934{1051{
935 if (buf->snapshot)1052 struct pt_filters *filters;
936 return false;1053 int node = event->cpu == -1 ? -1 : cpu_to_node(event->cpu);
1054
1055 if (!pt_cap_get(PT_CAP_num_address_ranges))
1056 return 0;
1057
1058 filters = kzalloc_node(sizeof(struct pt_filters), GFP_KERNEL, node);
1059 if (!filters)
1060 return -ENOMEM;
1061
1062 if (event->parent)
1063 memcpy(filters, event->parent->hw.addr_filters,
1064 sizeof(*filters));
1065
1066 event->hw.addr_filters = filters;
1067
1068 return 0;
1069}
1070
1071static void pt_addr_filters_fini(struct perf_event *event)
1072{
1073 kfree(event->hw.addr_filters);
1074 event->hw.addr_filters = NULL;
1075}
1076
1077static int pt_event_addr_filters_validate(struct list_head *filters)
1078{
1079 struct perf_addr_filter *filter;
1080 int range = 0;
1081
1082 list_for_each_entry(filter, filters, entry) {
1083 /* PT doesn't support single address triggers */
1084 if (!filter->range)
1085 return -EOPNOTSUPP;
1086
1087 if (!filter->inode && !kernel_ip(filter->offset))
1088 return -EINVAL;
1089
1090 if (++range > pt_cap_get(PT_CAP_num_address_ranges))
1091 return -EOPNOTSUPP;
1092 }
1093
1094 return 0;
1095}
1096
1097static void pt_event_addr_filters_sync(struct perf_event *event)
1098{
1099 struct perf_addr_filters_head *head = perf_event_addr_filters(event);
1100 unsigned long msr_a, msr_b, *offs = event->addr_filters_offs;
1101 struct pt_filters *filters = event->hw.addr_filters;
1102 struct perf_addr_filter *filter;
1103 int range = 0;
1104
1105 if (!filters)
1106 return;
937 1107
938 if (local_read(&buf->data_size) >= pt->handle.size)1108 list_for_each_entry(filter, &head->list, entry) {
939 return true;1109 if (filter->inode && !offs[range]) {
1110 msr_a = msr_b = 0;
1111 } else {
1112 /* apply the offset */
1113 msr_a = filter->offset + offs[range];
1114 msr_b = filter->size + msr_a;
1115 }
1116
1117 filters->filter[range].msr_a = msr_a;
1118 filters->filter[range].msr_b = msr_b;
1119 filters->filter[range].config = filter->filter ? 1 : 2;
1120 range++;
1121 }
940 1122
941 return false;1123 filters->nr_filters = range;
942}1124}
943 1125
944/**1126/**
@@ -955,7 +1137,7 @@ void intel_pt_interrupt(void) · 10 unmodified lines
955 * after PT has been disabled by pt_event_stop(). Make sure we don't1137 * after PT has been disabled by pt_event_stop(). Make sure we don't
956 * do anything (particularly, re-enable) for this event here.1138 * do anything (particularly, re-enable) for this event here.
957 */1139 */
958 if (!ACCESS_ONCE(pt->handle_nmi))1140 if (!READ_ONCE(pt->handle_nmi))
959 return;1141 return;
960 1142
961 /*1143 /*
@@ -1040,23 +1222,36 @@ EXPORT_SYMBOL_GPL(intel_pt_handle_vmx); · 78 unmodified lines
1040 1222
1041static void pt_event_start(struct perf_event *event, int mode)1223static void pt_event_start(struct perf_event *event, int mode)
1042{1224{
1225 struct hw_perf_event *hwc = &event->hw;
1043 struct pt *pt = this_cpu_ptr(&pt_ctx);1226 struct pt *pt = this_cpu_ptr(&pt_ctx);
1044 struct pt_buffer *buf = perf_get_aux(&pt->handle);1227 struct pt_buffer *buf;
1045 1228
1046 if (READ_ONCE(pt->vmx_on))1229 if (READ_ONCE(pt->vmx_on))
1047 return;1230 return;
1048 1231
1049 if (!buf || pt_buffer_is_full(buf, pt)) {1232 buf = perf_aux_output_begin(&pt->handle, event);
1050 event->hw.state = PERF_HES_STOPPED;1233 if (!buf)
1051 return;1234 goto fail_stop;
1235
1236 pt_buffer_reset_offsets(buf, pt->handle.head);
1237 if (!buf->snapshot) {
1238 if (pt_buffer_reset_markers(buf, &pt->handle))
1239 goto fail_end_stop;
1052 }1240 }
1053 1241
1054 ACCESS_ONCE(pt->handle_nmi) = 1;1242 WRITE_ONCE(pt->handle_nmi, 1);
1055 event->hw.state = 0;1243 hwc->state = 0;
1056 1244
1057 pt_config_buffer(buf->cur->table, buf->cur_idx,1245 pt_config_buffer(buf->cur->table, buf->cur_idx,
1058 buf->output_off);1246 buf->output_off);
1059 pt_config(event);1247 pt_config(event);
1248
1249 return;
1250
1251fail_end_stop:
1252 perf_aux_output_end(&pt->handle, 0, true);
1253fail_stop:
1254 hwc->state = PERF_HES_STOPPED;
1060}1255}
1061 1256
1062static void pt_event_stop(struct perf_event *event, int mode)1257static void pt_event_stop(struct perf_event *event, int mode)
@@ -1067,7 +1262,7 @@ static void pt_event_stop(struct perf_event *event, int mode) · 4 unmodified lines
1067 * Protect against the PMI racing with disabling wrmsr,1262 * Protect against the PMI racing with disabling wrmsr,
1068 * see comment in intel_pt_interrupt().1263 * see comment in intel_pt_interrupt().
1069 */1264 */
1070 ACCESS_ONCE(pt->handle_nmi) = 0;1265 WRITE_ONCE(pt->handle_nmi, 0);
1071 1266
1072 pt_config_stop(event);1267 pt_config_stop(event);
1073 1268
@@ -1090,19 +1285,7 @@ static void pt_event_stop(struct perf_event *event, int mode) · 16 unmodified lines
1090 pt_handle_status(pt);1285 pt_handle_status(pt);
1091 1286
1092 pt_update_head(pt);1287 pt_update_head(pt);
1093 }
1094}
1095
1096static void pt_event_del(struct perf_event *event, int mode)
1097{
1098 struct pt *pt = this_cpu_ptr(&pt_ctx);
1099 struct pt_buffer *buf;
1100 1288
1101 pt_event_stop(event, PERF_EF_UPDATE);
1102
1103 buf = perf_get_aux(&pt->handle);
1104
1105 if (buf) {
1106 if (buf->snapshot)1289 if (buf->snapshot)
1107 pt->handle.head =1290 pt->handle.head =
1108 local_xchg(&buf->data_size,1291 local_xchg(&buf->data_size,
@@ -1112,9 +1295,13 @@ static void pt_event_del(struct perf_event *event, int mode) · 3 unmodified lines
1112 }1295 }
1113}1296}
1114 1297
1298static void pt_event_del(struct perf_event *event, int mode)
1299{
1300 pt_event_stop(event, PERF_EF_UPDATE);
1301}
1302
1115static int pt_event_add(struct perf_event *event, int mode)1303static int pt_event_add(struct perf_event *event, int mode)
1116{1304{
1117 struct pt_buffer *buf;
1118 struct pt *pt = this_cpu_ptr(&pt_ctx);1305 struct pt *pt = this_cpu_ptr(&pt_ctx);
1119 struct hw_perf_event *hwc = &event->hw;1306 struct hw_perf_event *hwc = &event->hw;
1120 int ret = -EBUSY;1307 int ret = -EBUSY;
@@ -1122,34 +1309,18 @@ static int pt_event_add(struct perf_event *event, int mode) · 1 unmodified line
1122 if (pt->handle.event)1309 if (pt->handle.event)
1123 goto fail;1310 goto fail;
1124 1311
1125 buf = perf_aux_output_begin(&pt->handle, event);
1126 ret = -EINVAL;
1127 if (!buf)
1128 goto fail_stop;
1129
1130 pt_buffer_reset_offsets(buf, pt->handle.head);
1131 if (!buf->snapshot) {
1132 ret = pt_buffer_reset_markers(buf, &pt->handle);
1133 if (ret)
1134 goto fail_end_stop;
1135 }
1136
1137 if (mode & PERF_EF_START) {1312 if (mode & PERF_EF_START) {
1138 pt_event_start(event, 0);1313 pt_event_start(event, 0);
1139 ret = -EBUSY;1314 ret = -EINVAL;
1140 if (hwc->state == PERF_HES_STOPPED)1315 if (hwc->state == PERF_HES_STOPPED)
1141 goto fail_end_stop;1316 goto fail;
1142 } else {1317 } else {
1143 hwc->state = PERF_HES_STOPPED;1318 hwc->state = PERF_HES_STOPPED;
1144 }1319 }
1145 1320
1146 return 0;1321 ret = 0;
1147
1148fail_end_stop:
1149 perf_aux_output_end(&pt->handle, 0, true);
1150fail_stop:
1151 hwc->state = PERF_HES_STOPPED;
1152fail:1322fail:
1323
1153 return ret;1324 return ret;
1154}1325}
1155 1326
@@ -1159,6 +1330,7 @@ static void pt_event_read(struct perf_event *event) · 3 unmodified lines
1159 1330
1160static void pt_event_destroy(struct perf_event *event)1331static void pt_event_destroy(struct perf_event *event)
1161{1332{
1333 pt_addr_filters_fini(event);
1162 x86_del_exclusive(x86_lbr_exclusive_pt);1334 x86_del_exclusive(x86_lbr_exclusive_pt);
1163}1335}
1164 1336
@@ -1173,6 +1345,11 @@ static int pt_event_init(struct perf_event *event) · 8 unmodified lines
1173 if (x86_add_exclusive(x86_lbr_exclusive_pt))1345 if (x86_add_exclusive(x86_lbr_exclusive_pt))
1174 return -EBUSY;1346 return -EBUSY;
1175 1347
1348 if (pt_addr_filters_init(event)) {
1349 x86_del_exclusive(x86_lbr_exclusive_pt);
1350 return -ENOMEM;
1351 }
1352
1176 event->destroy = pt_event_destroy;1353 event->destroy = pt_event_destroy;
1177 1354
1178 return 0;1355 return 0;
@@ -1192,7 +1369,7 @@ static __init int pt_init(void) · 13 unmodified lines
1192 1369
1193 BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE);1370 BUILD_BUG_ON(sizeof(struct topa) > PAGE_SIZE);
1194 1371
1195 if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT))1372 if (!boot_cpu_has(X86_FEATURE_INTEL_PT))
1196 return -ENODEV;1373 return -ENODEV;
1197 1374
1198 get_online_cpus();1375 get_online_cpus();
@@ -1226,16 +1403,21 @@ static __init int pt_init(void) · 27 unmodified lines
1226 PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF;1403 PERF_PMU_CAP_AUX_NO_SG | PERF_PMU_CAP_AUX_SW_DOUBLEBUF;
1227 1404
1228 pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE;1405 pt_pmu.pmu.capabilities |= PERF_PMU_CAP_EXCLUSIVE | PERF_PMU_CAP_ITRACE;
1229 pt_pmu.pmu.attr_groups = pt_attr_groups;1406 pt_pmu.pmu.attr_groups = pt_attr_groups;
1230 pt_pmu.pmu.task_ctx_nr = perf_sw_context;1407 pt_pmu.pmu.task_ctx_nr = perf_sw_context;
1231 pt_pmu.pmu.event_init = pt_event_init;1408 pt_pmu.pmu.event_init = pt_event_init;
1232 pt_pmu.pmu.add = pt_event_add;1409 pt_pmu.pmu.add = pt_event_add;
1233 pt_pmu.pmu.del = pt_event_del;1410 pt_pmu.pmu.del = pt_event_del;
1234 pt_pmu.pmu.start = pt_event_start;1411 pt_pmu.pmu.start = pt_event_start;
1235 pt_pmu.pmu.stop = pt_event_stop;1412 pt_pmu.pmu.stop = pt_event_stop;
1236 pt_pmu.pmu.read = pt_event_read;1413 pt_pmu.pmu.read = pt_event_read;
1237 pt_pmu.pmu.setup_aux = pt_buffer_setup_aux;1414 pt_pmu.pmu.setup_aux = pt_buffer_setup_aux;
1238 pt_pmu.pmu.free_aux = pt_buffer_free_aux;1415 pt_pmu.pmu.free_aux = pt_buffer_free_aux;
1416 pt_pmu.pmu.addr_filters_sync = pt_event_addr_filters_sync;
1417 pt_pmu.pmu.addr_filters_validate = pt_event_addr_filters_validate;
1418 pt_pmu.pmu.nr_addr_filters =
1419 pt_cap_get(PT_CAP_num_address_ranges);
1420
1239 ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);1421 ret = perf_pmu_register(&pt_pmu.pmu, "intel_pt", -1);
1240 1422
1241 return ret;1423 return ret;
arch/x86/events/intel/pt.h+68−0
@@ -19,6 +19,40 @@ · 18 unmodified lines
19#ifndef __INTEL_PT_H__19#ifndef __INTEL_PT_H__
20#define __INTEL_PT_H__20#define __INTEL_PT_H__
21 21
22/*
23 * PT MSR bit definitions
24 */
25#define RTIT_CTL_TRACEEN BIT(0)
26#define RTIT_CTL_CYCLEACC BIT(1)
27#define RTIT_CTL_OS BIT(2)
28#define RTIT_CTL_USR BIT(3)
29#define RTIT_CTL_CR3EN BIT(7)
30#define RTIT_CTL_TOPA BIT(8)
31#define RTIT_CTL_MTC_EN BIT(9)
32#define RTIT_CTL_TSC_EN BIT(10)
33#define RTIT_CTL_DISRETC BIT(11)
34#define RTIT_CTL_BRANCH_EN BIT(13)
35#define RTIT_CTL_MTC_RANGE_OFFSET 14
36#define RTIT_CTL_MTC_RANGE (0x0full << RTIT_CTL_MTC_RANGE_OFFSET)
37#define RTIT_CTL_CYC_THRESH_OFFSET 19
38#define RTIT_CTL_CYC_THRESH (0x0full << RTIT_CTL_CYC_THRESH_OFFSET)
39#define RTIT_CTL_PSB_FREQ_OFFSET 24
40#define RTIT_CTL_PSB_FREQ (0x0full << RTIT_CTL_PSB_FREQ_OFFSET)
41#define RTIT_CTL_ADDR0_OFFSET 32
42#define RTIT_CTL_ADDR0 (0x0full << RTIT_CTL_ADDR0_OFFSET)
43#define RTIT_CTL_ADDR1_OFFSET 36
44#define RTIT_CTL_ADDR1 (0x0full << RTIT_CTL_ADDR1_OFFSET)
45#define RTIT_CTL_ADDR2_OFFSET 40
46#define RTIT_CTL_ADDR2 (0x0full << RTIT_CTL_ADDR2_OFFSET)
47#define RTIT_CTL_ADDR3_OFFSET 44
48#define RTIT_CTL_ADDR3 (0x0full << RTIT_CTL_ADDR3_OFFSET)
49#define RTIT_STATUS_FILTEREN BIT(0)
50#define RTIT_STATUS_CONTEXTEN BIT(1)
51#define RTIT_STATUS_TRIGGEREN BIT(2)
52#define RTIT_STATUS_BUFFOVF BIT(3)
53#define RTIT_STATUS_ERROR BIT(4)
54#define RTIT_STATUS_STOPPED BIT(5)
55
22/*56/*
23 * Single-entry ToPA: when this close to region boundary, switch57 * Single-entry ToPA: when this close to region boundary, switch
24 * buffers to avoid losing data.58 * buffers to avoid losing data.
@@ -48,15 +82,20 @@ struct topa_entry { · 23 unmodified lines
48#define PT_CPUID_LEAVES 282#define PT_CPUID_LEAVES 2
49#define PT_CPUID_REGS_NUM 4 /* number of regsters (eax, ebx, ecx, edx) */83#define PT_CPUID_REGS_NUM 4 /* number of regsters (eax, ebx, ecx, edx) */
50 84
85/* TSC to Core Crystal Clock Ratio */
86#define CPUID_TSC_LEAF 0x15
87
51enum pt_capabilities {88enum pt_capabilities {
52 PT_CAP_max_subleaf = 0,89 PT_CAP_max_subleaf = 0,
53 PT_CAP_cr3_filtering,90 PT_CAP_cr3_filtering,
54 PT_CAP_psb_cyc,91 PT_CAP_psb_cyc,
92 PT_CAP_ip_filtering,
55 PT_CAP_mtc,93 PT_CAP_mtc,
56 PT_CAP_topa_output,94 PT_CAP_topa_output,
57 PT_CAP_topa_multiple_entries,95 PT_CAP_topa_multiple_entries,
58 PT_CAP_single_range_output,96 PT_CAP_single_range_output,
59 PT_CAP_payloads_lip,97 PT_CAP_payloads_lip,
98 PT_CAP_num_address_ranges,
60 PT_CAP_mtc_periods,99 PT_CAP_mtc_periods,
61 PT_CAP_cycle_thresholds,100 PT_CAP_cycle_thresholds,
62 PT_CAP_psb_periods,101 PT_CAP_psb_periods,
@@ -66,6 +105,9 @@ struct pt_pmu { · 3 unmodified lines
66 struct pmu pmu;105 struct pmu pmu;
67 u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];106 u32 caps[PT_CPUID_REGS_NUM * PT_CPUID_LEAVES];
68 bool vmx;107 bool vmx;
108 unsigned long max_nonturbo_ratio;
109 unsigned int tsc_art_num;
110 unsigned int tsc_art_den;
69};111};
70 112
71/**113/**
@@ -104,14 +146,40 @@ struct pt_buffer { · 32 unmodified lines
104 struct topa_entry *topa_index[0];146 struct topa_entry *topa_index[0];
105};147};
106 148
149#define PT_FILTERS_NUM 4
150
151/**
152 * struct pt_filter - IP range filter configuration
153 * @msr_a: range start, goes to RTIT_ADDRn_A
154 * @msr_b: range end, goes to RTIT_ADDRn_B
155 * @config: 4-bit field in RTIT_CTL
156 */
157struct pt_filter {
158 unsigned long msr_a;
159 unsigned long msr_b;
160 unsigned long config;
161};
162
163/**
164 * struct pt_filters - IP range filtering context
165 * @filter: filters defined for this context
166 * @nr_filters: number of defined filters in the @filter array
167 */
168struct pt_filters {
169 struct pt_filter filter[PT_FILTERS_NUM];
170 unsigned int nr_filters;
171};
172
107/**173/**
108 * struct pt - per-cpu pt context174 * struct pt - per-cpu pt context
109 * @handle: perf output handle175 * @handle: perf output handle
176 * @filters: last configured filters
110 * @handle_nmi: do handle PT PMI on this cpu, there's an active event177 * @handle_nmi: do handle PT PMI on this cpu, there's an active event
111 * @vmx_on: 1 if VMX is ON on this cpu178 * @vmx_on: 1 if VMX is ON on this cpu
112 */179 */
113struct pt {180struct pt {
114 struct perf_output_handle handle;181 struct perf_output_handle handle;
182 struct pt_filters filters;
115 int handle_nmi;183 int handle_nmi;
116 int vmx_on;184 int vmx_on;
117};185};
arch/x86/events/intel/rapl.c+141−42
@@ -27,10 +27,14 @@ · 26 unmodified lines
27 * event: rapl_energy_dram27 * event: rapl_energy_dram
28 * perf code: 0x328 * perf code: 0x3
29 *29 *
30 * dram counter: consumption of the builtin-gpu domain (client only)30 * gpu counter: consumption of the builtin-gpu domain (client only)
31 * event: rapl_energy_gpu31 * event: rapl_energy_gpu
32 * perf code: 0x432 * perf code: 0x4
33 *33 *
34 * psys counter: consumption of the builtin-psys domain (client only)
35 * event: rapl_energy_psys
36 * perf code: 0x5
37 *
34 * We manage those counters as free running (read-only). They may be38 * We manage those counters as free running (read-only). They may be
35 * use simultaneously by other tools, such as turbostat.39 * use simultaneously by other tools, such as turbostat.
36 *40 *
@@ -53,6 +57,8 @@ · 16 unmodified lines
53#include <asm/cpu_device_id.h>57#include <asm/cpu_device_id.h>
54#include "../perf_event.h"58#include "../perf_event.h"
55 59
60MODULE_LICENSE("GPL");
61
56/*62/*
57 * RAPL energy status counters63 * RAPL energy status counters
58 */64 */
@@ -64,13 +70,16 @@ · 5 unmodified lines
64#define INTEL_RAPL_RAM 0x3 /* pseudo-encoding */70#define INTEL_RAPL_RAM 0x3 /* pseudo-encoding */
65#define RAPL_IDX_PP1_NRG_STAT 3 /* gpu */71#define RAPL_IDX_PP1_NRG_STAT 3 /* gpu */
66#define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */72#define INTEL_RAPL_PP1 0x4 /* pseudo-encoding */
73#define RAPL_IDX_PSYS_NRG_STAT 4 /* psys */
74#define INTEL_RAPL_PSYS 0x5 /* pseudo-encoding */
67 75
68#define NR_RAPL_DOMAINS 0x476#define NR_RAPL_DOMAINS 0x5
69static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {77static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = {
70 "pp0-core",78 "pp0-core",
71 "package",79 "package",
72 "dram",80 "dram",
73 "pp1-gpu",81 "pp1-gpu",
82 "psys",
74};83};
75 84
76/* Clients have PP0, PKG */85/* Clients have PP0, PKG */
@@ -89,6 +98,13 @@ static const char *const rapl_domain_names[NR_RAPL_DOMAINS] __initconst = { · 12 unmodified lines
89 1<<RAPL_IDX_RAM_NRG_STAT|\98 1<<RAPL_IDX_RAM_NRG_STAT|\
90 1<<RAPL_IDX_PP1_NRG_STAT)99 1<<RAPL_IDX_PP1_NRG_STAT)
91 100
101/* SKL clients have PP0, PKG, RAM, PP1, PSYS */
102#define RAPL_IDX_SKL_CLN (1<<RAPL_IDX_PP0_NRG_STAT|\
103 1<<RAPL_IDX_PKG_NRG_STAT|\
104 1<<RAPL_IDX_RAM_NRG_STAT|\
105 1<<RAPL_IDX_PP1_NRG_STAT|\
106 1<<RAPL_IDX_PSYS_NRG_STAT)
107
92/* Knights Landing has PKG, RAM */108/* Knights Landing has PKG, RAM */
93#define RAPL_IDX_KNL (1<<RAPL_IDX_PKG_NRG_STAT|\109#define RAPL_IDX_KNL (1<<RAPL_IDX_PKG_NRG_STAT|\
94 1<<RAPL_IDX_RAM_NRG_STAT)110 1<<RAPL_IDX_RAM_NRG_STAT)
@@ -360,6 +376,10 @@ static int rapl_pmu_event_init(struct perf_event *event) · 265 unmodified lines
360 bit = RAPL_IDX_PP1_NRG_STAT;376 bit = RAPL_IDX_PP1_NRG_STAT;
361 msr = MSR_PP1_ENERGY_STATUS;377 msr = MSR_PP1_ENERGY_STATUS;
362 break;378 break;
379 case INTEL_RAPL_PSYS:
380 bit = RAPL_IDX_PSYS_NRG_STAT;
381 msr = MSR_PLATFORM_ENERGY_STATUS;
382 break;
363 default:383 default:
364 return -EINVAL;384 return -EINVAL;
365 }385 }
@@ -414,11 +434,13 @@ RAPL_EVENT_ATTR_STR(energy-cores, rapl_cores, "event=0x01"); · 48 unmodified lines
414RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");434RAPL_EVENT_ATTR_STR(energy-pkg , rapl_pkg, "event=0x02");
415RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");435RAPL_EVENT_ATTR_STR(energy-ram , rapl_ram, "event=0x03");
416RAPL_EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04");436RAPL_EVENT_ATTR_STR(energy-gpu , rapl_gpu, "event=0x04");
437RAPL_EVENT_ATTR_STR(energy-psys, rapl_psys, "event=0x05");
417 438
418RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");439RAPL_EVENT_ATTR_STR(energy-cores.unit, rapl_cores_unit, "Joules");
419RAPL_EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules");440RAPL_EVENT_ATTR_STR(energy-pkg.unit , rapl_pkg_unit, "Joules");
420RAPL_EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules");441RAPL_EVENT_ATTR_STR(energy-ram.unit , rapl_ram_unit, "Joules");
421RAPL_EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules");442RAPL_EVENT_ATTR_STR(energy-gpu.unit , rapl_gpu_unit, "Joules");
443RAPL_EVENT_ATTR_STR(energy-psys.unit, rapl_psys_unit, "Joules");
422 444
423/*445/*
424 * we compute in 0.23 nJ increments regardless of MSR446 * we compute in 0.23 nJ increments regardless of MSR
@@ -427,6 +449,7 @@ RAPL_EVENT_ATTR_STR(energy-cores.scale, rapl_cores_scale, "2.3283064365386962890 · 2 unmodified lines
427RAPL_EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10");449RAPL_EVENT_ATTR_STR(energy-pkg.scale, rapl_pkg_scale, "2.3283064365386962890625e-10");
428RAPL_EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10");450RAPL_EVENT_ATTR_STR(energy-ram.scale, rapl_ram_scale, "2.3283064365386962890625e-10");
429RAPL_EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10");451RAPL_EVENT_ATTR_STR(energy-gpu.scale, rapl_gpu_scale, "2.3283064365386962890625e-10");
452RAPL_EVENT_ATTR_STR(energy-psys.scale, rapl_psys_scale, "2.3283064365386962890625e-10");
430 453
431static struct attribute *rapl_events_srv_attr[] = {454static struct attribute *rapl_events_srv_attr[] = {
432 EVENT_PTR(rapl_cores),455 EVENT_PTR(rapl_cores),
@@ -476,6 +499,27 @@ static struct attribute *rapl_events_hsw_attr[] = { · 43 unmodified lines
476 NULL,499 NULL,
477};500};
478 501
502static struct attribute *rapl_events_skl_attr[] = {
503 EVENT_PTR(rapl_cores),
504 EVENT_PTR(rapl_pkg),
505 EVENT_PTR(rapl_gpu),
506 EVENT_PTR(rapl_ram),
507 EVENT_PTR(rapl_psys),
508
509 EVENT_PTR(rapl_cores_unit),
510 EVENT_PTR(rapl_pkg_unit),
511 EVENT_PTR(rapl_gpu_unit),
512 EVENT_PTR(rapl_ram_unit),
513 EVENT_PTR(rapl_psys_unit),
514
515 EVENT_PTR(rapl_cores_scale),
516 EVENT_PTR(rapl_pkg_scale),
517 EVENT_PTR(rapl_gpu_scale),
518 EVENT_PTR(rapl_ram_scale),
519 EVENT_PTR(rapl_psys_scale),
520 NULL,
521};
522
479static struct attribute *rapl_events_knl_attr[] = {523static struct attribute *rapl_events_knl_attr[] = {
480 EVENT_PTR(rapl_pkg),524 EVENT_PTR(rapl_pkg),
481 EVENT_PTR(rapl_ram),525 EVENT_PTR(rapl_ram),
@@ -592,6 +636,11 @@ static int rapl_cpu_notifier(struct notifier_block *self, · 110 unmodified lines
592 return NOTIFY_OK;636 return NOTIFY_OK;
593}637}
594 638
639static struct notifier_block rapl_cpu_nb = {
640 .notifier_call = rapl_cpu_notifier,
641 .priority = CPU_PRI_PERF + 1,
642};
643
595static int rapl_check_hw_unit(bool apply_quirk)644static int rapl_check_hw_unit(bool apply_quirk)
596{645{
597 u64 msr_rapl_power_unit_bits;646 u64 msr_rapl_power_unit_bits;
@@ -660,7 +709,7 @@ static int __init rapl_prepare_cpus(void) · 62 unmodified lines
660 return 0;709 return 0;
661}710}
662 711
663static void __init cleanup_rapl_pmus(void)712static void cleanup_rapl_pmus(void)
664{713{
665 int i;714 int i;
666 715
@@ -691,52 +740,92 @@ static int __init init_rapl_pmus(void) · 24 unmodified lines
691 return 0;740 return 0;
692}741}
693 742
743#define X86_RAPL_MODEL_MATCH(model, init) \
744 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
745
746struct intel_rapl_init_fun {
747 bool apply_quirk;
748 int cntr_mask;
749 struct attribute **attrs;
750};
751
752static const struct intel_rapl_init_fun snb_rapl_init __initconst = {
753 .apply_quirk = false,
754 .cntr_mask = RAPL_IDX_CLN,
755 .attrs = rapl_events_cln_attr,
756};
757
758static const struct intel_rapl_init_fun hsx_rapl_init __initconst = {
759 .apply_quirk = true,
760 .cntr_mask = RAPL_IDX_SRV,
761 .attrs = rapl_events_srv_attr,
762};
763
764static const struct intel_rapl_init_fun hsw_rapl_init __initconst = {
765 .apply_quirk = false,
766 .cntr_mask = RAPL_IDX_HSW,
767 .attrs = rapl_events_hsw_attr,
768};
769
770static const struct intel_rapl_init_fun snbep_rapl_init __initconst = {
771 .apply_quirk = false,
772 .cntr_mask = RAPL_IDX_SRV,
773 .attrs = rapl_events_srv_attr,
774};
775
776static const struct intel_rapl_init_fun knl_rapl_init __initconst = {
777 .apply_quirk = true,
778 .cntr_mask = RAPL_IDX_KNL,
779 .attrs = rapl_events_knl_attr,
780};
781
782static const struct intel_rapl_init_fun skl_rapl_init __initconst = {
783 .apply_quirk = false,
784 .cntr_mask = RAPL_IDX_SKL_CLN,
785 .attrs = rapl_events_skl_attr,
786};
787
694static const struct x86_cpu_id rapl_cpu_match[] __initconst = {788static const struct x86_cpu_id rapl_cpu_match[] __initconst = {
695 [0] = { .vendor = X86_VENDOR_INTEL, .family = 6 },789 X86_RAPL_MODEL_MATCH(42, snb_rapl_init), /* Sandy Bridge */
696 [1] = {},790 X86_RAPL_MODEL_MATCH(45, snbep_rapl_init), /* Sandy Bridge-EP */
791
792 X86_RAPL_MODEL_MATCH(58, snb_rapl_init), /* Ivy Bridge */
793 X86_RAPL_MODEL_MATCH(62, snbep_rapl_init), /* IvyTown */
794
795 X86_RAPL_MODEL_MATCH(60, hsw_rapl_init), /* Haswell */
796 X86_RAPL_MODEL_MATCH(63, hsx_rapl_init), /* Haswell-Server */
797 X86_RAPL_MODEL_MATCH(69, hsw_rapl_init), /* Haswell-Celeron */
798 X86_RAPL_MODEL_MATCH(70, hsw_rapl_init), /* Haswell GT3e */
799
800 X86_RAPL_MODEL_MATCH(61, hsw_rapl_init), /* Broadwell */
801 X86_RAPL_MODEL_MATCH(71, hsw_rapl_init), /* Broadwell-H */
802 X86_RAPL_MODEL_MATCH(79, hsx_rapl_init), /* Broadwell-Server */
803 X86_RAPL_MODEL_MATCH(86, hsx_rapl_init), /* Broadwell Xeon D */
804
805 X86_RAPL_MODEL_MATCH(87, knl_rapl_init), /* Knights Landing */
806
807 X86_RAPL_MODEL_MATCH(78, skl_rapl_init), /* Skylake */
808 X86_RAPL_MODEL_MATCH(94, skl_rapl_init), /* Skylake H/S */
809 {},
697};810};
698 811
812MODULE_DEVICE_TABLE(x86cpu, rapl_cpu_match);
813
699static int __init rapl_pmu_init(void)814static int __init rapl_pmu_init(void)
700{815{
701 bool apply_quirk = false;816 const struct x86_cpu_id *id;
817 struct intel_rapl_init_fun *rapl_init;
818 bool apply_quirk;
702 int ret;819 int ret;
703 820
704 if (!x86_match_cpu(rapl_cpu_match))821 id = x86_match_cpu(rapl_cpu_match);
822 if (!id)
705 return -ENODEV;823 return -ENODEV;
706 824
707 switch (boot_cpu_data.x86_model) {825 rapl_init = (struct intel_rapl_init_fun *)id->driver_data;
708 case 42: /* Sandy Bridge */826 apply_quirk = rapl_init->apply_quirk;
709 case 58: /* Ivy Bridge */827 rapl_cntr_mask = rapl_init->cntr_mask;
710 rapl_cntr_mask = RAPL_IDX_CLN;828 rapl_pmu_events_group.attrs = rapl_init->attrs;
711 rapl_pmu_events_group.attrs = rapl_events_cln_attr;
712 break;
713 case 63: /* Haswell-Server */
714 case 79: /* Broadwell-Server */
715 apply_quirk = true;
716 rapl_cntr_mask = RAPL_IDX_SRV;
717 rapl_pmu_events_group.attrs = rapl_events_srv_attr;
718 break;
719 case 60: /* Haswell */
720 case 69: /* Haswell-Celeron */
721 case 70: /* Haswell GT3e */
722 case 61: /* Broadwell */
723 case 71: /* Broadwell-H */
724 rapl_cntr_mask = RAPL_IDX_HSW;
725 rapl_pmu_events_group.attrs = rapl_events_hsw_attr;
726 break;
727 case 45: /* Sandy Bridge-EP */
728 case 62: /* IvyTown */
729 rapl_cntr_mask = RAPL_IDX_SRV;
730 rapl_pmu_events_group.attrs = rapl_events_srv_attr;
731 break;
732 case 87: /* Knights Landing */
733 apply_quirk = true;
734 rapl_cntr_mask = RAPL_IDX_KNL;
735 rapl_pmu_events_group.attrs = rapl_events_knl_attr;
736 break;
737 default:
738 return -ENODEV;
739 }
740 829
741 ret = rapl_check_hw_unit(apply_quirk);830 ret = rapl_check_hw_unit(apply_quirk);
742 if (ret)831 if (ret)
@@ -756,7 +845,7 @@ static int __init rapl_pmu_init(void) · 13 unmodified lines
756 if (ret)845 if (ret)
757 goto out;846 goto out;
758 847
759 __perf_cpu_notifier(rapl_cpu_notifier);848 __register_cpu_notifier(&rapl_cpu_nb);
760 cpu_notifier_register_done();849 cpu_notifier_register_done();
761 rapl_advertise();850 rapl_advertise();
762 return 0;851 return 0;
@@ -767,4 +856,14 @@ out: · 4 unmodified lines
767 cpu_notifier_register_done();856 cpu_notifier_register_done();
768 return ret;857 return ret;
769}858}
770device_initcall(rapl_pmu_init);859module_init(rapl_pmu_init);
860
861static void __exit intel_rapl_exit(void)
862{
863 cpu_notifier_register_begin();
864 __unregister_cpu_notifier(&rapl_cpu_nb);
865 perf_pmu_unregister(&rapl_pmus->pmu);
866 cleanup_rapl_pmus();
867 cpu_notifier_register_done();
868}
869module_exit(intel_rapl_exit);
arch/x86/events/intel/uncore.c+126−90
@@ -1,3 +1,4 @@
1#include <asm/cpu_device_id.h>
1#include "uncore.h"2#include "uncore.h"
2 3
3static struct intel_uncore_type *empty_uncore[] = { NULL, };4static struct intel_uncore_type *empty_uncore[] = { NULL, };
@@ -21,6 +22,8 @@ static struct event_constraint uncore_constraint_fixed = · 17 unmodified lines
21struct event_constraint uncore_constraint_empty =22struct event_constraint uncore_constraint_empty =
22 EVENT_CONSTRAINT(0, 0, 0);23 EVENT_CONSTRAINT(0, 0, 0);
23 24
25MODULE_LICENSE("GPL");
26
24static int uncore_pcibus_to_physid(struct pci_bus *bus)27static int uncore_pcibus_to_physid(struct pci_bus *bus)
25{28{
26 struct pci2phy_map *map;29 struct pci2phy_map *map;
@@ -754,7 +757,7 @@ static void uncore_pmu_unregister(struct intel_uncore_pmu *pmu) · 727 unmodified lines
754 pmu->registered = false;757 pmu->registered = false;
755}758}
756 759
757static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)760static void __uncore_exit_boxes(struct intel_uncore_type *type, int cpu)
758{761{
759 struct intel_uncore_pmu *pmu = type->pmus;762 struct intel_uncore_pmu *pmu = type->pmus;
760 struct intel_uncore_box *box;763 struct intel_uncore_box *box;
@@ -770,7 +773,7 @@ static void __init __uncore_exit_boxes(struct intel_uncore_type *type, int cpu) · 9 unmodified lines
770 }773 }
771}774}
772 775
773static void __init uncore_exit_boxes(void *dummy)776static void uncore_exit_boxes(void *dummy)
774{777{
775 struct intel_uncore_type **types;778 struct intel_uncore_type **types;
776 779
@@ -787,7 +790,7 @@ static void uncore_free_boxes(struct intel_uncore_pmu *pmu) · 10 unmodified lines
787 kfree(pmu->boxes);790 kfree(pmu->boxes);
788}791}
789 792
790static void __init uncore_type_exit(struct intel_uncore_type *type)793static void uncore_type_exit(struct intel_uncore_type *type)
791{794{
792 struct intel_uncore_pmu *pmu = type->pmus;795 struct intel_uncore_pmu *pmu = type->pmus;
793 int i;796 int i;
@@ -804,7 +807,7 @@ static void __init uncore_type_exit(struct intel_uncore_type *type) · 10 unmodified lines
804 type->events_group = NULL;807 type->events_group = NULL;
805}808}
806 809
807static void __init uncore_types_exit(struct intel_uncore_type **types)810static void uncore_types_exit(struct intel_uncore_type **types)
808{811{
809 for (; *types; types++)812 for (; *types; types++)
810 uncore_type_exit(*types);813 uncore_type_exit(*types);
@@ -989,46 +992,6 @@ static int __init uncore_pci_init(void) · 178 unmodified lines
989 size_t size;992 size_t size;
990 int ret;993 int ret;
991 994
992 switch (boot_cpu_data.x86_model) {
993 case 45: /* Sandy Bridge-EP */
994 ret = snbep_uncore_pci_init();
995 break;
996 case 62: /* Ivy Bridge-EP */
997 ret = ivbep_uncore_pci_init();
998 break;
999 case 63: /* Haswell-EP */
1000 ret = hswep_uncore_pci_init();
1001 break;
1002 case 79: /* BDX-EP */
1003 case 86: /* BDX-DE */
1004 ret = bdx_uncore_pci_init();
1005 break;
1006 case 42: /* Sandy Bridge */
1007 ret = snb_uncore_pci_init();
1008 break;
1009 case 58: /* Ivy Bridge */
1010 ret = ivb_uncore_pci_init();
1011 break;
1012 case 60: /* Haswell */
1013 case 69: /* Haswell Celeron */
1014 ret = hsw_uncore_pci_init();
1015 break;
1016 case 61: /* Broadwell */
1017 ret = bdw_uncore_pci_init();
1018 break;
1019 case 87: /* Knights Landing */
1020 ret = knl_uncore_pci_init();
1021 break;
1022 case 94: /* SkyLake */
1023 ret = skl_uncore_pci_init();
1024 break;
1025 default:
1026 return -ENODEV;
1027 }
1028
1029 if (ret)
1030 return ret;
1031
1032 size = max_packages * sizeof(struct pci_extra_dev);995 size = max_packages * sizeof(struct pci_extra_dev);
1033 uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL);996 uncore_extra_pci_dev = kzalloc(size, GFP_KERNEL);
1034 if (!uncore_extra_pci_dev) {997 if (!uncore_extra_pci_dev) {
@@ -1060,7 +1023,7 @@ err: · 25 unmodified lines
1060 return ret;1023 return ret;
1061}1024}
1062 1025
1063static void __init uncore_pci_exit(void)1026static void uncore_pci_exit(void)
1064{1027{
1065 if (pcidrv_registered) {1028 if (pcidrv_registered) {
1066 pcidrv_registered = false;1029 pcidrv_registered = false;
@@ -1287,46 +1250,6 @@ static int __init uncore_cpu_init(void) · 220 unmodified lines
1287{1250{
1288 int ret;1251 int ret;
1289 1252
1290 switch (boot_cpu_data.x86_model) {
1291 case 26: /* Nehalem */
1292 case 30:
1293 case 37: /* Westmere */
1294 case 44:
1295 nhm_uncore_cpu_init();
1296 break;
1297 case 42: /* Sandy Bridge */
1298 case 58: /* Ivy Bridge */
1299 case 60: /* Haswell */
1300 case 69: /* Haswell */
1301 case 70: /* Haswell */
1302 case 61: /* Broadwell */
1303 case 71: /* Broadwell */
1304 snb_uncore_cpu_init();
1305 break;
1306 case 45: /* Sandy Bridge-EP */
1307 snbep_uncore_cpu_init();
1308 break;
1309 case 46: /* Nehalem-EX */
1310 case 47: /* Westmere-EX aka. Xeon E7 */
1311 nhmex_uncore_cpu_init();
1312 break;
1313 case 62: /* Ivy Bridge-EP */
1314 ivbep_uncore_cpu_init();
1315 break;
1316 case 63: /* Haswell-EP */
1317 hswep_uncore_cpu_init();
1318 break;
1319 case 79: /* BDX-EP */
1320 case 86: /* BDX-DE */
1321 bdx_uncore_cpu_init();
1322 break;
1323 case 87: /* Knights Landing */
1324 knl_uncore_cpu_init();
1325 break;
1326 default:
1327 return -ENODEV;
1328 }
1329
1330 ret = uncore_types_init(uncore_msr_uncores, true);1253 ret = uncore_types_init(uncore_msr_uncores, true);
1331 if (ret)1254 if (ret)
1332 goto err;1255 goto err;
@@ -1376,11 +1299,105 @@ static int __init uncore_cpumask_init(bool msr) · 43 unmodified lines
1376 return 0;1299 return 0;
1377}1300}
1378 1301
1302#define X86_UNCORE_MODEL_MATCH(model, init) \
1303 { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
1304
1305struct intel_uncore_init_fun {
1306 void (*cpu_init)(void);
1307 int (*pci_init)(void);
1308};
1309
1310static const struct intel_uncore_init_fun nhm_uncore_init __initconst = {
1311 .cpu_init = nhm_uncore_cpu_init,
1312};
1313
1314static const struct intel_uncore_init_fun snb_uncore_init __initconst = {
1315 .cpu_init = snb_uncore_cpu_init,
1316 .pci_init = snb_uncore_pci_init,
1317};
1318
1319static const struct intel_uncore_init_fun ivb_uncore_init __initconst = {
1320 .cpu_init = snb_uncore_cpu_init,
1321 .pci_init = ivb_uncore_pci_init,
1322};
1323
1324static const struct intel_uncore_init_fun hsw_uncore_init __initconst = {
1325 .cpu_init = snb_uncore_cpu_init,
1326 .pci_init = hsw_uncore_pci_init,
1327};
1328
1329static const struct intel_uncore_init_fun bdw_uncore_init __initconst = {
1330 .cpu_init = snb_uncore_cpu_init,
1331 .pci_init = bdw_uncore_pci_init,
1332};
1333
1334static const struct intel_uncore_init_fun snbep_uncore_init __initconst = {
1335 .cpu_init = snbep_uncore_cpu_init,
1336 .pci_init = snbep_uncore_pci_init,
1337};
1338
1339static const struct intel_uncore_init_fun nhmex_uncore_init __initconst = {
1340 .cpu_init = nhmex_uncore_cpu_init,
1341};
1342
1343static const struct intel_uncore_init_fun ivbep_uncore_init __initconst = {
1344 .cpu_init = ivbep_uncore_cpu_init,
1345 .pci_init = ivbep_uncore_pci_init,
1346};
1347
1348static const struct intel_uncore_init_fun hswep_uncore_init __initconst = {
1349 .cpu_init = hswep_uncore_cpu_init,
1350 .pci_init = hswep_uncore_pci_init,
1351};
1352
1353static const struct intel_uncore_init_fun bdx_uncore_init __initconst = {
1354 .cpu_init = bdx_uncore_cpu_init,
1355 .pci_init = bdx_uncore_pci_init,
1356};
1357
1358static const struct intel_uncore_init_fun knl_uncore_init __initconst = {
1359 .cpu_init = knl_uncore_cpu_init,
1360 .pci_init = knl_uncore_pci_init,
1361};
1362
1363static const struct intel_uncore_init_fun skl_uncore_init __initconst = {
1364 .pci_init = skl_uncore_pci_init,
1365};
1366
1367static const struct x86_cpu_id intel_uncore_match[] __initconst = {
1368 X86_UNCORE_MODEL_MATCH(26, nhm_uncore_init), /* Nehalem */
1369 X86_UNCORE_MODEL_MATCH(30, nhm_uncore_init),
1370 X86_UNCORE_MODEL_MATCH(37, nhm_uncore_init), /* Westmere */
1371 X86_UNCORE_MODEL_MATCH(44, nhm_uncore_init),
1372 X86_UNCORE_MODEL_MATCH(42, snb_uncore_init), /* Sandy Bridge */
1373 X86_UNCORE_MODEL_MATCH(58, ivb_uncore_init), /* Ivy Bridge */
1374 X86_UNCORE_MODEL_MATCH(60, hsw_uncore_init), /* Haswell */
1375 X86_UNCORE_MODEL_MATCH(69, hsw_uncore_init), /* Haswell Celeron */
1376 X86_UNCORE_MODEL_MATCH(70, hsw_uncore_init), /* Haswell */
1377 X86_UNCORE_MODEL_MATCH(61, bdw_uncore_init), /* Broadwell */
1378 X86_UNCORE_MODEL_MATCH(71, bdw_uncore_init), /* Broadwell */
1379 X86_UNCORE_MODEL_MATCH(45, snbep_uncore_init), /* Sandy Bridge-EP */
1380 X86_UNCORE_MODEL_MATCH(46, nhmex_uncore_init), /* Nehalem-EX */
1381 X86_UNCORE_MODEL_MATCH(47, nhmex_uncore_init), /* Westmere-EX aka. Xeon E7 */
1382 X86_UNCORE_MODEL_MATCH(62, ivbep_uncore_init), /* Ivy Bridge-EP */
1383 X86_UNCORE_MODEL_MATCH(63, hswep_uncore_init), /* Haswell-EP */
1384 X86_UNCORE_MODEL_MATCH(79, bdx_uncore_init), /* BDX-EP */
1385 X86_UNCORE_MODEL_MATCH(86, bdx_uncore_init), /* BDX-DE */
1386 X86_UNCORE_MODEL_MATCH(87, knl_uncore_init), /* Knights Landing */
1387 X86_UNCORE_MODEL_MATCH(94, skl_uncore_init), /* SkyLake */
1388 {},
1389};
1390
1391MODULE_DEVICE_TABLE(x86cpu, intel_uncore_match);
1392
1379static int __init intel_uncore_init(void)1393static int __init intel_uncore_init(void)
1380{1394{
1381 int pret, cret, ret;1395 const struct x86_cpu_id *id;
1396 struct intel_uncore_init_fun *uncore_init;
1397 int pret = 0, cret = 0, ret;
1382 1398
1383 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL)1399 id = x86_match_cpu(intel_uncore_match);
1400 if (!id)
1384 return -ENODEV;1401 return -ENODEV;
1385 1402
1386 if (cpu_has_hypervisor)1403 if (cpu_has_hypervisor)
@@ -1388,8 +1405,17 @@ static int __init intel_uncore_init(void) · 1 unmodified line
1388 1405
1389 max_packages = topology_max_packages();1406 max_packages = topology_max_packages();
1390 1407
1391 pret = uncore_pci_init();1408 uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
1392 cret = uncore_cpu_init();1409 if (uncore_init->pci_init) {
1410 pret = uncore_init->pci_init();
1411 if (!pret)
1412 pret = uncore_pci_init();
1413 }
1414
1415 if (uncore_init->cpu_init) {
1416 uncore_init->cpu_init();
1417 cret = uncore_cpu_init();
1418 }
1393 1419
1394 if (cret && pret)1420 if (cret && pret)
1395 return -ENODEV;1421 return -ENODEV;
@@ -1409,4 +1435,14 @@ err: · 13 unmodified lines
1409 cpu_notifier_register_done();1435 cpu_notifier_register_done();
1410 return ret;1436 return ret;
1411}1437}
1412device_initcall(intel_uncore_init);1438module_init(intel_uncore_init);
1439
1440static void __exit intel_uncore_exit(void)
1441{
1442 cpu_notifier_register_begin();
1443 __unregister_cpu_notifier(&uncore_cpu_nb);
1444 uncore_types_exit(uncore_msr_uncores);
1445 uncore_pci_exit();
1446 cpu_notifier_register_done();
1447}
1448module_exit(intel_uncore_exit);
arch/x86/events/msr.c+26−10
@@ -6,6 +6,8 @@ enum perf_msr_id { · 5 unmodified lines
6 PERF_MSR_MPERF = 2,6 PERF_MSR_MPERF = 2,
7 PERF_MSR_PPERF = 3,7 PERF_MSR_PPERF = 3,
8 PERF_MSR_SMI = 4,8 PERF_MSR_SMI = 4,
9 PERF_MSR_PTSC = 5,
10 PERF_MSR_IRPERF = 6,
9 11
10 PERF_MSR_EVENT_MAX,12 PERF_MSR_EVENT_MAX,
11};13};
@@ -15,6 +17,16 @@ static bool test_aperfmperf(int idx) · 3 unmodified lines
15 return boot_cpu_has(X86_FEATURE_APERFMPERF);17 return boot_cpu_has(X86_FEATURE_APERFMPERF);
16}18}
17 19
20static bool test_ptsc(int idx)
21{
22 return boot_cpu_has(X86_FEATURE_PTSC);
23}
24
25static bool test_irperf(int idx)
26{
27 return boot_cpu_has(X86_FEATURE_IRPERF);
28}
29
18static bool test_intel(int idx)30static bool test_intel(int idx)
19{31{
20 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||32 if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
@@ -69,18 +81,22 @@ struct perf_msr { · 48 unmodified lines
69 bool (*test)(int idx);81 bool (*test)(int idx);
70};82};
71 83
72PMU_EVENT_ATTR_STRING(tsc, evattr_tsc, "event=0x00");84PMU_EVENT_ATTR_STRING(tsc, evattr_tsc, "event=0x00");
73PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01");85PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01");
74PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02");86PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02");
75PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");87PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");
76PMU_EVENT_ATTR_STRING(smi, evattr_smi, "event=0x04");88PMU_EVENT_ATTR_STRING(smi, evattr_smi, "event=0x04");
89PMU_EVENT_ATTR_STRING(ptsc, evattr_ptsc, "event=0x05");
90PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
77 91
78static struct perf_msr msr[] = {92static struct perf_msr msr[] = {
79 [PERF_MSR_TSC] = { 0, &evattr_tsc, NULL, },93 [PERF_MSR_TSC] = { 0, &evattr_tsc, NULL, },
80 [PERF_MSR_APERF] = { MSR_IA32_APERF, &evattr_aperf, test_aperfmperf, },94 [PERF_MSR_APERF] = { MSR_IA32_APERF, &evattr_aperf, test_aperfmperf, },
81 [PERF_MSR_MPERF] = { MSR_IA32_MPERF, &evattr_mperf, test_aperfmperf, },95 [PERF_MSR_MPERF] = { MSR_IA32_MPERF, &evattr_mperf, test_aperfmperf, },
82 [PERF_MSR_PPERF] = { MSR_PPERF, &evattr_pperf, test_intel, },96 [PERF_MSR_PPERF] = { MSR_PPERF, &evattr_pperf, test_intel, },
83 [PERF_MSR_SMI] = { MSR_SMI_COUNT, &evattr_smi, test_intel, },97 [PERF_MSR_SMI] = { MSR_SMI_COUNT, &evattr_smi, test_intel, },
98 [PERF_MSR_PTSC] = { MSR_F15H_PTSC, &evattr_ptsc, test_ptsc, },
99 [PERF_MSR_IRPERF] = { MSR_F17H_IRPERF, &evattr_irperf, test_irperf, },
84};100};
85 101
86static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {102static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
arch/x86/events/perf_event.h+5−0
@@ -601,6 +601,7 @@ struct x86_pmu { · 600 unmodified lines
601 u64 lbr_sel_mask; /* LBR_SELECT valid bits */601 u64 lbr_sel_mask; /* LBR_SELECT valid bits */
602 const int *lbr_sel_map; /* lbr_select mappings */602 const int *lbr_sel_map; /* lbr_select mappings */
603 bool lbr_double_abort; /* duplicated lbr aborts */603 bool lbr_double_abort; /* duplicated lbr aborts */
604 bool lbr_pt_coexist; /* LBR may coexist with PT */
604 605
605 /*606 /*
606 * Intel PT/LBR/BTS are exclusive607 * Intel PT/LBR/BTS are exclusive
@@ -859,6 +860,8 @@ extern struct event_constraint intel_atom_pebs_event_constraints[]; · 252 unmodified lines
859 860
860extern struct event_constraint intel_slm_pebs_event_constraints[];861extern struct event_constraint intel_slm_pebs_event_constraints[];
861 862
863extern struct event_constraint intel_glm_pebs_event_constraints[];
864
862extern struct event_constraint intel_nehalem_pebs_event_constraints[];865extern struct event_constraint intel_nehalem_pebs_event_constraints[];
863 866
864extern struct event_constraint intel_westmere_pebs_event_constraints[];867extern struct event_constraint intel_westmere_pebs_event_constraints[];
@@ -907,6 +910,8 @@ void intel_pmu_lbr_init_nhm(void); · 42 unmodified lines
907 910
908void intel_pmu_lbr_init_atom(void);911void intel_pmu_lbr_init_atom(void);
909 912
913void intel_pmu_lbr_init_slm(void);
914
910void intel_pmu_lbr_init_snb(void);915void intel_pmu_lbr_init_snb(void);
911 916
912void intel_pmu_lbr_init_hsw(void);917void intel_pmu_lbr_init_hsw(void);
arch/x86/include/asm/cpufeatures.h+2−0
@@ -177,6 +177,7 @@ · 176 unmodified lines
177#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */177#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
178#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */178#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
179#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */179#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */
180#define X86_FEATURE_PTSC ( 6*32+27) /* performance time-stamp counter */
180#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */181#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */
181#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */182#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
182 183
@@ -250,6 +251,7 @@ · 67 unmodified lines
250 251
251/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */252/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */
252#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */253#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */
254#define X86_FEATURE_IRPERF (13*32+1) /* Instructions Retired Count */
253 255
254/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */256/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */
255#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */257#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */
arch/x86/include/asm/msr-index.h+15−20
@@ -89,27 +89,16 @@ · 88 unmodified lines
89#define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f689#define MSR_PEBS_LD_LAT_THRESHOLD 0x000003f6
90 90
91#define MSR_IA32_RTIT_CTL 0x0000057091#define MSR_IA32_RTIT_CTL 0x00000570
92#define RTIT_CTL_TRACEEN BIT(0)
93#define RTIT_CTL_CYCLEACC BIT(1)
94#define RTIT_CTL_OS BIT(2)
95#define RTIT_CTL_USR BIT(3)
96#define RTIT_CTL_CR3EN BIT(7)
97#define RTIT_CTL_TOPA BIT(8)
98#define RTIT_CTL_MTC_EN BIT(9)
99#define RTIT_CTL_TSC_EN BIT(10)
100#define RTIT_CTL_DISRETC BIT(11)
101#define RTIT_CTL_BRANCH_EN BIT(13)
102#define RTIT_CTL_MTC_RANGE_OFFSET 14
103#define RTIT_CTL_MTC_RANGE (0x0full << RTIT_CTL_MTC_RANGE_OFFSET)
104#define RTIT_CTL_CYC_THRESH_OFFSET 19
105#define RTIT_CTL_CYC_THRESH (0x0full << RTIT_CTL_CYC_THRESH_OFFSET)
106#define RTIT_CTL_PSB_FREQ_OFFSET 24
107#define RTIT_CTL_PSB_FREQ (0x0full << RTIT_CTL_PSB_FREQ_OFFSET)
108#define MSR_IA32_RTIT_STATUS 0x0000057192#define MSR_IA32_RTIT_STATUS 0x00000571
109#define RTIT_STATUS_CONTEXTEN BIT(1)93#define MSR_IA32_RTIT_STATUS 0x00000571
110#define RTIT_STATUS_TRIGGEREN BIT(2)94#define MSR_IA32_RTIT_ADDR0_A 0x00000580
111#define RTIT_STATUS_ERROR BIT(4)95#define MSR_IA32_RTIT_ADDR0_B 0x00000581
112#define RTIT_STATUS_STOPPED BIT(5)96#define MSR_IA32_RTIT_ADDR1_A 0x00000582
97#define MSR_IA32_RTIT_ADDR1_B 0x00000583
98#define MSR_IA32_RTIT_ADDR2_A 0x00000584
99#define MSR_IA32_RTIT_ADDR2_B 0x00000585
100#define MSR_IA32_RTIT_ADDR3_A 0x00000586
101#define MSR_IA32_RTIT_ADDR3_B 0x00000587
113#define MSR_IA32_RTIT_CR3_MATCH 0x00000572102#define MSR_IA32_RTIT_CR3_MATCH 0x00000572
114#define MSR_IA32_RTIT_OUTPUT_BASE 0x00000560103#define MSR_IA32_RTIT_OUTPUT_BASE 0x00000560
115#define MSR_IA32_RTIT_OUTPUT_MASK 0x00000561104#define MSR_IA32_RTIT_OUTPUT_MASK 0x00000561
@@ -205,6 +194,8 @@ · 89 unmodified lines
205#define MSR_CONFIG_TDP_CONTROL 0x0000064B194#define MSR_CONFIG_TDP_CONTROL 0x0000064B
206#define MSR_TURBO_ACTIVATION_RATIO 0x0000064C195#define MSR_TURBO_ACTIVATION_RATIO 0x0000064C
207 196
197#define MSR_PLATFORM_ENERGY_STATUS 0x0000064D
198
208#define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658199#define MSR_PKG_WEIGHTED_CORE_C0_RES 0x00000658
209#define MSR_PKG_ANY_CORE_C0_RES 0x00000659200#define MSR_PKG_ANY_CORE_C0_RES 0x00000659
210#define MSR_PKG_ANY_GFXE_C0_RES 0x0000065A201#define MSR_PKG_ANY_GFXE_C0_RES 0x0000065A
@@ -315,6 +306,9 @@ · 104 unmodified lines
315#define MSR_AMD64_IBSOPDATA4 0xc001103d306#define MSR_AMD64_IBSOPDATA4 0xc001103d
316#define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */307#define MSR_AMD64_IBS_REG_COUNT_MAX 8 /* includes MSR_AMD64_IBSBRTARGET */
317 308
309/* Fam 17h MSRs */
310#define MSR_F17H_IRPERF 0xc00000e9
311
318/* Fam 16h MSRs */312/* Fam 16h MSRs */
319#define MSR_F16H_L2I_PERF_CTL 0xc0010230313#define MSR_F16H_L2I_PERF_CTL 0xc0010230
320#define MSR_F16H_L2I_PERF_CTR 0xc0010231314#define MSR_F16H_L2I_PERF_CTR 0xc0010231
@@ -328,6 +322,7 @@ · 7 unmodified lines
328#define MSR_F15H_PERF_CTR 0xc0010201322#define MSR_F15H_PERF_CTR 0xc0010201
329#define MSR_F15H_NB_PERF_CTL 0xc0010240323#define MSR_F15H_NB_PERF_CTL 0xc0010240
330#define MSR_F15H_NB_PERF_CTR 0xc0010241324#define MSR_F15H_NB_PERF_CTR 0xc0010241
325#define MSR_F15H_PTSC 0xc0010280
331#define MSR_F15H_IC_CFG 0xc0011021326#define MSR_F15H_IC_CFG 0xc0011021
332 327
333/* Fam 10h MSRs */328/* Fam 10h MSRs */
arch/x86/kernel/uprobes.c+2−2
@@ -578,7 +578,7 @@ static void default_abort_op(struct arch_uprobe *auprobe, struct pt_regs *regs) · 577 unmodified lines
578 riprel_post_xol(auprobe, regs);578 riprel_post_xol(auprobe, regs);
579}579}
580 580
581static struct uprobe_xol_ops default_xol_ops = {581static const struct uprobe_xol_ops default_xol_ops = {
582 .pre_xol = default_pre_xol_op,582 .pre_xol = default_pre_xol_op,
583 .post_xol = default_post_xol_op,583 .post_xol = default_post_xol_op,
584 .abort = default_abort_op,584 .abort = default_abort_op,
@@ -695,7 +695,7 @@ static void branch_clear_offset(struct arch_uprobe *auprobe, struct insn *insn) · 110 unmodified lines
695 0, insn->immediate.nbytes);695 0, insn->immediate.nbytes);
696}696}
697 697
698static struct uprobe_xol_ops branch_xol_ops = {698static const struct uprobe_xol_ops branch_xol_ops = {
699 .emulate = branch_emulate_op,699 .emulate = branch_emulate_op,
700 .post_xol = branch_post_xol_op,700 .post_xol = branch_post_xol_op,
701};701};
arch/xtensa/kernel/perf_event.c+2−2
@@ -332,14 +332,14 @@ static int callchain_trace(struct stackframe *frame, void *data) · 331 unmodified lines
332void perf_callchain_kernel(struct perf_callchain_entry *entry,332void perf_callchain_kernel(struct perf_callchain_entry *entry,
333 struct pt_regs *regs)333 struct pt_regs *regs)
334{334{
335 xtensa_backtrace_kernel(regs, PERF_MAX_STACK_DEPTH,335 xtensa_backtrace_kernel(regs, sysctl_perf_event_max_stack,
336 callchain_trace, NULL, entry);336 callchain_trace, NULL, entry);
337}337}
338 338
339void perf_callchain_user(struct perf_callchain_entry *entry,339void perf_callchain_user(struct perf_callchain_entry *entry,
340 struct pt_regs *regs)340 struct pt_regs *regs)
341{341{
342 xtensa_backtrace_user(regs, PERF_MAX_STACK_DEPTH,342 xtensa_backtrace_user(regs, sysctl_perf_event_max_stack,
343 callchain_trace, entry);343 callchain_trace, entry);
344}344}
345 345
drivers/perf/arm_pmu.c+8−0
@@ -847,6 +847,14 @@ static int cpu_pmu_init(struct arm_pmu *cpu_pmu) · 846 unmodified lines
847 if (!platform_get_irq(cpu_pmu->plat_device, 0))847 if (!platform_get_irq(cpu_pmu->plat_device, 0))
848 cpu_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;848 cpu_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
849 849
850 /*
851 * This is a CPU PMU potentially in a heterogeneous configuration (e.g.
852 * big.LITTLE). This is not an uncore PMU, and we have taken ctx
853 * sharing into account (e.g. with our pmu::filter_match callback and
854 * pmu::event_init group validation).
855 */
856 cpu_pmu->pmu.capabilities |= PERF_PMU_CAP_HETEROGENEOUS_CPUS;
857
850 return 0;858 return 0;
851 859
852out_unregister:860out_unregister:
drivers/powercap/intel_rapl.c+69−0
@@ -34,6 +34,9 @@ · 33 unmodified lines
34#include <asm/processor.h>34#include <asm/processor.h>
35#include <asm/cpu_device_id.h>35#include <asm/cpu_device_id.h>
36 36
37/* Local defines */
38#define MSR_PLATFORM_POWER_LIMIT 0x0000065C
39
37/* bitmasks for RAPL MSRs, used by primitive access functions */40/* bitmasks for RAPL MSRs, used by primitive access functions */
38#define ENERGY_STATUS_MASK 0xffffffff41#define ENERGY_STATUS_MASK 0xffffffff
39 42
@@ -86,6 +89,7 @@ enum rapl_domain_type { · 46 unmodified lines
86 RAPL_DOMAIN_PP0, /* core power plane */89 RAPL_DOMAIN_PP0, /* core power plane */
87 RAPL_DOMAIN_PP1, /* graphics uncore */90 RAPL_DOMAIN_PP1, /* graphics uncore */
88 RAPL_DOMAIN_DRAM,/* DRAM control_type */91 RAPL_DOMAIN_DRAM,/* DRAM control_type */
92 RAPL_DOMAIN_PLATFORM, /* PSys control_type */
89 RAPL_DOMAIN_MAX,93 RAPL_DOMAIN_MAX,
90};94};
91 95
@@ -251,9 +255,11 @@ static const char * const rapl_domain_names[] = { · 159 unmodified lines
251 "core",255 "core",
252 "uncore",256 "uncore",
253 "dram",257 "dram",
258 "psys",
254};259};
255 260
256static struct powercap_control_type *control_type; /* PowerCap Controller */261static struct powercap_control_type *control_type; /* PowerCap Controller */
262static struct rapl_domain *platform_rapl_domain; /* Platform (PSys) domain */
257 263
258/* caller to ensure CPU hotplug lock is held */264/* caller to ensure CPU hotplug lock is held */
259static struct rapl_package *find_package_by_id(int id)265static struct rapl_package *find_package_by_id(int id)
@@ -409,6 +415,14 @@ static const struct powercap_zone_ops zone_ops[] = { · 149 unmodified lines
409 .set_enable = set_domain_enable,415 .set_enable = set_domain_enable,
410 .get_enable = get_domain_enable,416 .get_enable = get_domain_enable,
411 },417 },
418 /* RAPL_DOMAIN_PLATFORM */
419 {
420 .get_energy_uj = get_energy_counter,
421 .get_max_energy_range_uj = get_max_energy_counter,
422 .release = release_zone,
423 .set_enable = set_domain_enable,
424 .get_enable = get_domain_enable,
425 },
412};426};
413 427
414static int set_power_limit(struct powercap_zone *power_zone, int id,428static int set_power_limit(struct powercap_zone *power_zone, int id,
@@ -1160,6 +1174,13 @@ static int rapl_unregister_powercap(void) · 745 unmodified lines
1160 powercap_unregister_zone(control_type,1174 powercap_unregister_zone(control_type,
1161 &rd_package->power_zone);1175 &rd_package->power_zone);
1162 }1176 }
1177
1178 if (platform_rapl_domain) {
1179 powercap_unregister_zone(control_type,
1180 &platform_rapl_domain->power_zone);
1181 kfree(platform_rapl_domain);
1182 }
1183
1163 powercap_unregister_control_type(control_type);1184 powercap_unregister_control_type(control_type);
1164 1185
1165 return 0;1186 return 0;
@@ -1239,6 +1260,47 @@ err_cleanup: · 73 unmodified lines
1239 return ret;1260 return ret;
1240}1261}
1241 1262
1263static int rapl_register_psys(void)
1264{
1265 struct rapl_domain *rd;
1266 struct powercap_zone *power_zone;
1267 u64 val;
1268
1269 if (rdmsrl_safe_on_cpu(0, MSR_PLATFORM_ENERGY_STATUS, &val) || !val)
1270 return -ENODEV;
1271
1272 if (rdmsrl_safe_on_cpu(0, MSR_PLATFORM_POWER_LIMIT, &val) || !val)
1273 return -ENODEV;
1274
1275 rd = kzalloc(sizeof(*rd), GFP_KERNEL);
1276 if (!rd)
1277 return -ENOMEM;
1278
1279 rd->name = rapl_domain_names[RAPL_DOMAIN_PLATFORM];
1280 rd->id = RAPL_DOMAIN_PLATFORM;
1281 rd->msrs[0] = MSR_PLATFORM_POWER_LIMIT;
1282 rd->msrs[1] = MSR_PLATFORM_ENERGY_STATUS;
1283 rd->rpl[0].prim_id = PL1_ENABLE;
1284 rd->rpl[0].name = pl1_name;
1285 rd->rpl[1].prim_id = PL2_ENABLE;
1286 rd->rpl[1].name = pl2_name;
1287 rd->rp = find_package_by_id(0);
1288
1289 power_zone = powercap_register_zone(&rd->power_zone, control_type,
1290 "psys", NULL,
1291 &zone_ops[RAPL_DOMAIN_PLATFORM],
1292 2, &constraint_ops);
1293
1294 if (IS_ERR(power_zone)) {
1295 kfree(rd);
1296 return PTR_ERR(power_zone);
1297 }
1298
1299 platform_rapl_domain = rd;
1300
1301 return 0;
1302}
1303
1242static int rapl_register_powercap(void)1304static int rapl_register_powercap(void)
1243{1305{
1244 struct rapl_domain *rd;1306 struct rapl_domain *rd;
@@ -1255,6 +1317,10 @@ static int rapl_register_powercap(void) · 10 unmodified lines
1255 list_for_each_entry(rp, &rapl_packages, plist)1317 list_for_each_entry(rp, &rapl_packages, plist)
1256 if (rapl_package_register_powercap(rp))1318 if (rapl_package_register_powercap(rp))
1257 goto err_cleanup_package;1319 goto err_cleanup_package;
1320
1321 /* Don't bail out if PSys is not supported */
1322 rapl_register_psys();
1323
1258 return ret;1324 return ret;
1259 1325
1260err_cleanup_package:1326err_cleanup_package:
@@ -1289,6 +1355,9 @@ static int rapl_check_domain(int cpu, int domain) · 28 unmodified lines
1289 case RAPL_DOMAIN_DRAM:1355 case RAPL_DOMAIN_DRAM:
1290 msr = MSR_DRAM_ENERGY_STATUS;1356 msr = MSR_DRAM_ENERGY_STATUS;
1291 break;1357 break;
1358 case RAPL_DOMAIN_PLATFORM:
1359 /* PSYS(PLATFORM) is not a CPU domain, so avoid printng error */
1360 return -EINVAL;
1292 default:1361 default:
1293 pr_err("invalid domain id %d\n", domain);1362 pr_err("invalid domain id %d\n", domain);
1294 return -EINVAL;1363 return -EINVAL;
include/linux/perf_event.h+135−4
@@ -58,7 +58,7 @@ struct perf_guest_info_callbacks { · 57 unmodified lines
58 58
59struct perf_callchain_entry {59struct perf_callchain_entry {
60 __u64 nr;60 __u64 nr;
61 __u64 ip[PERF_MAX_STACK_DEPTH];61 __u64 ip[0]; /* /proc/sys/kernel/perf_event_max_stack */
62};62};
63 63
64struct perf_raw_record {64struct perf_raw_record {
@@ -151,6 +151,15 @@ struct hw_perf_event { · 86 unmodified lines
151 */151 */
152 struct task_struct *target;152 struct task_struct *target;
153 153
154 /*
155 * PMU would store hardware filter configuration
156 * here.
157 */
158 void *addr_filters;
159
160 /* Last sync'ed generation of filters */
161 unsigned long addr_filters_gen;
162
154/*163/*
155 * hw_perf_event::state flags; used to track the PERF_EF_* state.164 * hw_perf_event::state flags; used to track the PERF_EF_* state.
156 */165 */
@@ -216,6 +225,7 @@ struct perf_event; · 59 unmodified lines
216#define PERF_PMU_CAP_AUX_SW_DOUBLEBUF 0x08225#define PERF_PMU_CAP_AUX_SW_DOUBLEBUF 0x08
217#define PERF_PMU_CAP_EXCLUSIVE 0x10226#define PERF_PMU_CAP_EXCLUSIVE 0x10
218#define PERF_PMU_CAP_ITRACE 0x20227#define PERF_PMU_CAP_ITRACE 0x20
228#define PERF_PMU_CAP_HETEROGENEOUS_CPUS 0x40
219 229
220/**230/**
221 * struct pmu - generic performance monitoring unit231 * struct pmu - generic performance monitoring unit
@@ -240,6 +250,9 @@ struct pmu { · 18 unmodified lines
240 int task_ctx_nr;250 int task_ctx_nr;
241 int hrtimer_interval_ms;251 int hrtimer_interval_ms;
242 252
253 /* number of address filters this PMU can do */
254 unsigned int nr_addr_filters;
255
243 /*256 /*
244 * Fully disable/enable this PMU, can be used to protect from the PMI257 * Fully disable/enable this PMU, can be used to protect from the PMI
245 * as well as for lazy/batch writing of the MSRs.258 * as well as for lazy/batch writing of the MSRs.
@@ -392,12 +405,71 @@ struct pmu { · 146 unmodified lines
392 */405 */
393 void (*free_aux) (void *aux); /* optional */406 void (*free_aux) (void *aux); /* optional */
394 407
408 /*
409 * Validate address range filters: make sure the HW supports the
410 * requested configuration and number of filters; return 0 if the
411 * supplied filters are valid, -errno otherwise.
412 *
413 * Runs in the context of the ioctl()ing process and is not serialized
414 * with the rest of the PMU callbacks.
415 */
416 int (*addr_filters_validate) (struct list_head *filters);
417 /* optional */
418
419 /*
420 * Synchronize address range filter configuration:
421 * translate hw-agnostic filters into hardware configuration in
422 * event::hw::addr_filters.
423 *
424 * Runs as a part of filter sync sequence that is done in ->start()
425 * callback by calling perf_event_addr_filters_sync().
426 *
427 * May (and should) traverse event::addr_filters::list, for which its
428 * caller provides necessary serialization.
429 */
430 void (*addr_filters_sync) (struct perf_event *event);
431 /* optional */
432
395 /*433 /*
396 * Filter events for PMU-specific reasons.434 * Filter events for PMU-specific reasons.
397 */435 */
398 int (*filter_match) (struct perf_event *event); /* optional */436 int (*filter_match) (struct perf_event *event); /* optional */
399};437};
400 438
439/**
440 * struct perf_addr_filter - address range filter definition
441 * @entry: event's filter list linkage
442 * @inode: object file's inode for file-based filters
443 * @offset: filter range offset
444 * @size: filter range size
445 * @range: 1: range, 0: address
446 * @filter: 1: filter/start, 0: stop
447 *
448 * This is a hardware-agnostic filter configuration as specified by the user.
449 */
450struct perf_addr_filter {
451 struct list_head entry;
452 struct inode *inode;
453 unsigned long offset;
454 unsigned long size;
455 unsigned int range : 1,
456 filter : 1;
457};
458
459/**
460 * struct perf_addr_filters_head - container for address range filters
461 * @list: list of filters for this event
462 * @lock: spinlock that serializes accesses to the @list and event's
463 * (and its children's) filter generations.
464 *
465 * A child event will use parent's @list (and therefore @lock), so they are
466 * bundled together; see perf_event_addr_filters().
467 */
468struct perf_addr_filters_head {
469 struct list_head list;
470 raw_spinlock_t lock;
471};
472
401/**473/**
402 * enum perf_event_active_state - the states of a event474 * enum perf_event_active_state - the states of a event
403 */475 */
@@ -566,6 +638,12 @@ struct perf_event { · 162 unmodified lines
566 638
567 atomic_t event_limit;639 atomic_t event_limit;
568 640
641 /* address range filters */
642 struct perf_addr_filters_head addr_filters;
643 /* vma address array for file-based filders */
644 unsigned long *addr_filters_offs;
645 unsigned long addr_filters_gen;
646
569 void (*destroy)(struct perf_event *);647 void (*destroy)(struct perf_event *);
570 struct rcu_head rcu_head;648 struct rcu_head rcu_head;
571 649
@@ -834,9 +912,25 @@ extern int perf_event_overflow(struct perf_event *event, · 262 unmodified lines
834 struct perf_sample_data *data,912 struct perf_sample_data *data,
835 struct pt_regs *regs);913 struct pt_regs *regs);
836 914
915extern void perf_event_output_forward(struct perf_event *event,
916 struct perf_sample_data *data,
917 struct pt_regs *regs);
918extern void perf_event_output_backward(struct perf_event *event,
919 struct perf_sample_data *data,
920 struct pt_regs *regs);
837extern void perf_event_output(struct perf_event *event,921extern void perf_event_output(struct perf_event *event,
838 struct perf_sample_data *data,922 struct perf_sample_data *data,
839 struct pt_regs *regs);923 struct pt_regs *regs);
924
925static inline bool
926is_default_overflow_handler(struct perf_event *event)
927{
928 if (likely(event->overflow_handler == perf_event_output_forward))
929 return true;
930 if (unlikely(event->overflow_handler == perf_event_output_backward))
931 return true;
932 return false;
933}
840 934
841extern void935extern void
842perf_event_header__init_id(struct perf_event_header *header,936perf_event_header__init_id(struct perf_event_header *header,
@@ -977,9 +1071,11 @@ get_perf_callchain(struct pt_regs *regs, u32 init_nr, bool kernel, bool user, · 134 unmodified lines
977extern int get_callchain_buffers(void);1071extern int get_callchain_buffers(void);
978extern void put_callchain_buffers(void);1072extern void put_callchain_buffers(void);
979 1073
1074extern int sysctl_perf_event_max_stack;
1075
980static inline int perf_callchain_store(struct perf_callchain_entry *entry, u64 ip)1076static inline int perf_callchain_store(struct perf_callchain_entry *entry, u64 ip)
981{1077{
982 if (entry->nr < PERF_MAX_STACK_DEPTH) {1078 if (entry->nr < sysctl_perf_event_max_stack) {
983 entry->ip[entry->nr++] = ip;1079 entry->ip[entry->nr++] = ip;
984 return 0;1080 return 0;
985 } else {1081 } else {
@@ -1001,6 +1097,8 @@ extern int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, · 15 unmodified lines
1001 void __user *buffer, size_t *lenp,1097 void __user *buffer, size_t *lenp,
1002 loff_t *ppos);1098 loff_t *ppos);
1003 1099
1100int perf_event_max_stack_handler(struct ctl_table *table, int write,
1101 void __user *buffer, size_t *lenp, loff_t *ppos);
1004 1102
1005static inline bool perf_paranoid_tracepoint_raw(void)1103static inline bool perf_paranoid_tracepoint_raw(void)
1006{1104{
@@ -1045,8 +1143,41 @@ static inline bool has_aux(struct perf_event *event) · 38 unmodified lines
1045 return event->pmu->setup_aux;1143 return event->pmu->setup_aux;
1046}1144}
1047 1145
1146static inline bool is_write_backward(struct perf_event *event)
1147{
1148 return !!event->attr.write_backward;
1149}
1150
1151static inline bool has_addr_filter(struct perf_event *event)
1152{
1153 return event->pmu->nr_addr_filters;
1154}
1155
1156/*
1157 * An inherited event uses parent's filters
1158 */
1159static inline struct perf_addr_filters_head *
1160perf_event_addr_filters(struct perf_event *event)
1161{
1162 struct perf_addr_filters_head *ifh = &event->addr_filters;
1163
1164 if (event->parent)
1165 ifh = &event->parent->addr_filters;
1166
1167 return ifh;
1168}
1169
1170extern void perf_event_addr_filters_sync(struct perf_event *event);
1171
1048extern int perf_output_begin(struct perf_output_handle *handle,1172extern int perf_output_begin(struct perf_output_handle *handle,
1049 struct perf_event *event, unsigned int size);1173 struct perf_event *event, unsigned int size);
1174extern int perf_output_begin_forward(struct perf_output_handle *handle,
1175 struct perf_event *event,
1176 unsigned int size);
1177extern int perf_output_begin_backward(struct perf_output_handle *handle,
1178 struct perf_event *event,
1179 unsigned int size);
1180
1050extern void perf_output_end(struct perf_output_handle *handle);1181extern void perf_output_end(struct perf_output_handle *handle);
1051extern unsigned int perf_output_copy(struct perf_output_handle *handle,1182extern unsigned int perf_output_copy(struct perf_output_handle *handle,
1052 const void *buf, unsigned int len);1183 const void *buf, unsigned int len);
include/uapi/linux/perf_event.h+3−1
@@ -340,7 +340,8 @@ struct perf_event_attr { · 339 unmodified lines
340 comm_exec : 1, /* flag comm events that are due to an exec */340 comm_exec : 1, /* flag comm events that are due to an exec */
341 use_clockid : 1, /* use @clockid for time fields */341 use_clockid : 1, /* use @clockid for time fields */
342 context_switch : 1, /* context switch data */342 context_switch : 1, /* context switch data */
343 __reserved_1 : 37;343 write_backward : 1, /* Write ring buffer from end to beginning */
344 __reserved_1 : 36;
344 345
345 union {346 union {
346 __u32 wakeup_events; /* wakeup every n events */347 __u32 wakeup_events; /* wakeup every n events */
@@ -401,6 +402,7 @@ struct perf_event_attr { · 54 unmodified lines
401#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)402#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
402#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)403#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
403#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)404#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
405#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
404 406
405enum perf_event_ioc_flags {407enum perf_event_ioc_flags {
406 PERF_IOC_FLAG_GROUP = 1U << 0,408 PERF_IOC_FLAG_GROUP = 1U << 0,
kernel/bpf/stackmap.c+4−4
@@ -66,7 +66,7 @@ static struct bpf_map *stack_map_alloc(union bpf_attr *attr) · 65 unmodified lines
66 /* check sanity of attributes */66 /* check sanity of attributes */
67 if (attr->max_entries == 0 || attr->key_size != 4 ||67 if (attr->max_entries == 0 || attr->key_size != 4 ||
68 value_size < 8 || value_size % 8 ||68 value_size < 8 || value_size % 8 ||
69 value_size / 8 > PERF_MAX_STACK_DEPTH)69 value_size / 8 > sysctl_perf_event_max_stack)
70 return ERR_PTR(-EINVAL);70 return ERR_PTR(-EINVAL);
71 71
72 /* hash table size must be power of 2 */72 /* hash table size must be power of 2 */
@@ -124,8 +124,8 @@ static u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) · 51 unmodified lines
124 struct perf_callchain_entry *trace;124 struct perf_callchain_entry *trace;
125 struct stack_map_bucket *bucket, *new_bucket, *old_bucket;125 struct stack_map_bucket *bucket, *new_bucket, *old_bucket;
126 u32 max_depth = map->value_size / 8;126 u32 max_depth = map->value_size / 8;
127 /* stack_map_alloc() checks that max_depth <= PERF_MAX_STACK_DEPTH */127 /* stack_map_alloc() checks that max_depth <= sysctl_perf_event_max_stack */
128 u32 init_nr = PERF_MAX_STACK_DEPTH - max_depth;128 u32 init_nr = sysctl_perf_event_max_stack - max_depth;
129 u32 skip = flags & BPF_F_SKIP_FIELD_MASK;129 u32 skip = flags & BPF_F_SKIP_FIELD_MASK;
130 u32 hash, id, trace_nr, trace_len;130 u32 hash, id, trace_nr, trace_len;
131 bool user = flags & BPF_F_USER_STACK;131 bool user = flags & BPF_F_USER_STACK;
@@ -143,7 +143,7 @@ static u64 bpf_get_stackid(u64 r1, u64 r2, u64 flags, u64 r4, u64 r5) · 11 unmodified lines
143 return -EFAULT;143 return -EFAULT;
144 144
145 /* get_perf_callchain() guarantees that trace->nr >= init_nr145 /* get_perf_callchain() guarantees that trace->nr >= init_nr
146 * and trace-nr <= PERF_MAX_STACK_DEPTH, so trace_nr <= max_depth146 * and trace-nr <= sysctl_perf_event_max_stack, so trace_nr <= max_depth
147 */147 */
148 trace_nr = trace->nr - init_nr;148 trace_nr = trace->nr - init_nr;
149 149
kernel/events/callchain.c+33−2
@@ -18,6 +18,14 @@ struct callchain_cpus_entries { · 17 unmodified lines
18 struct perf_callchain_entry *cpu_entries[0];18 struct perf_callchain_entry *cpu_entries[0];
19};19};
20 20
21int sysctl_perf_event_max_stack __read_mostly = PERF_MAX_STACK_DEPTH;
22
23static inline size_t perf_callchain_entry__sizeof(void)
24{
25 return (sizeof(struct perf_callchain_entry) +
26 sizeof(__u64) * sysctl_perf_event_max_stack);
27}
28
21static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]);29static DEFINE_PER_CPU(int, callchain_recursion[PERF_NR_CONTEXTS]);
22static atomic_t nr_callchain_events;30static atomic_t nr_callchain_events;
23static DEFINE_MUTEX(callchain_mutex);31static DEFINE_MUTEX(callchain_mutex);
@@ -73,7 +81,7 @@ static int alloc_callchain_buffers(void) · 49 unmodified lines
73 if (!entries)81 if (!entries)
74 return -ENOMEM;82 return -ENOMEM;
75 83
76 size = sizeof(struct perf_callchain_entry) * PERF_NR_CONTEXTS;84 size = perf_callchain_entry__sizeof() * PERF_NR_CONTEXTS;
77 85
78 for_each_possible_cpu(cpu) {86 for_each_possible_cpu(cpu) {
79 entries->cpu_entries[cpu] = kmalloc_node(size, GFP_KERNEL,87 entries->cpu_entries[cpu] = kmalloc_node(size, GFP_KERNEL,
@@ -147,7 +155,8 @@ static struct perf_callchain_entry *get_callchain_entry(int *rctx) · 67 unmodified lines
147 155
148 cpu = smp_processor_id();156 cpu = smp_processor_id();
149 157
150 return &entries->cpu_entries[cpu][*rctx];158 return (((void *)entries->cpu_entries[cpu]) +
159 (*rctx * perf_callchain_entry__sizeof()));
151}160}
152 161
153static void162static void
@@ -215,3 +224,25 @@ exit_put: · 61 unmodified lines
215 224
216 return entry;225 return entry;
217}226}
227
228int perf_event_max_stack_handler(struct ctl_table *table, int write,
229 void __user *buffer, size_t *lenp, loff_t *ppos)
230{
231 int new_value = sysctl_perf_event_max_stack, ret;
232 struct ctl_table new_table = *table;
233
234 new_table.data = &new_value;
235 ret = proc_dointvec_minmax(&new_table, write, buffer, lenp, ppos);
236 if (ret || !write)
237 return ret;
238
239 mutex_lock(&callchain_mutex);
240 if (atomic_read(&nr_callchain_events))
241 ret = -EBUSY;
242 else
243 sysctl_perf_event_max_stack = new_value;
244
245 mutex_unlock(&callchain_mutex);
246
247 return ret;
248}
kernel/events/core.c+857−54
@@ -44,6 +44,8 @@ · 43 unmodified lines
44#include <linux/compat.h>44#include <linux/compat.h>
45#include <linux/bpf.h>45#include <linux/bpf.h>
46#include <linux/filter.h>46#include <linux/filter.h>
47#include <linux/namei.h>
48#include <linux/parser.h>
47 49
48#include "internal.h"50#include "internal.h"
49 51
@@ -1927,8 +1929,13 @@ event_sched_in(struct perf_event *event, · 1877 unmodified lines
1927 if (event->state <= PERF_EVENT_STATE_OFF)1929 if (event->state <= PERF_EVENT_STATE_OFF)
1928 return 0;1930 return 0;
1929 1931
1930 event->state = PERF_EVENT_STATE_ACTIVE;1932 WRITE_ONCE(event->oncpu, smp_processor_id());
1931 event->oncpu = smp_processor_id();1933 /*
1934 * Order event::oncpu write to happen before the ACTIVE state
1935 * is visible.
1936 */
1937 smp_wmb();
1938 WRITE_ONCE(event->state, PERF_EVENT_STATE_ACTIVE);
1932 1939
1933 /*1940 /*
1934 * Unthrottle events, since we scheduled we might have missed several1941 * Unthrottle events, since we scheduled we might have missed several
@@ -2360,6 +2367,112 @@ void perf_event_enable(struct perf_event *event) · 425 unmodified lines
2360}2367}
2361EXPORT_SYMBOL_GPL(perf_event_enable);2368EXPORT_SYMBOL_GPL(perf_event_enable);
2362 2369
2370struct stop_event_data {
2371 struct perf_event *event;
2372 unsigned int restart;
2373};
2374
2375static int __perf_event_stop(void *info)
2376{
2377 struct stop_event_data *sd = info;
2378 struct perf_event *event = sd->event;
2379
2380 /* if it's already INACTIVE, do nothing */
2381 if (READ_ONCE(event->state) != PERF_EVENT_STATE_ACTIVE)
2382 return 0;
2383
2384 /* matches smp_wmb() in event_sched_in() */
2385 smp_rmb();
2386
2387 /*
2388 * There is a window with interrupts enabled before we get here,
2389 * so we need to check again lest we try to stop another CPU's event.
2390 */
2391 if (READ_ONCE(event->oncpu) != smp_processor_id())
2392 return -EAGAIN;
2393
2394 event->pmu->stop(event, PERF_EF_UPDATE);
2395
2396 /*
2397 * May race with the actual stop (through perf_pmu_output_stop()),
2398 * but it is only used for events with AUX ring buffer, and such
2399 * events will refuse to restart because of rb::aux_mmap_count==0,
2400 * see comments in perf_aux_output_begin().
2401 *
2402 * Since this is happening on a event-local CPU, no trace is lost
2403 * while restarting.
2404 */
2405 if (sd->restart)
2406 event->pmu->start(event, PERF_EF_START);
2407
2408 return 0;
2409}
2410
2411static int perf_event_restart(struct perf_event *event)
2412{
2413 struct stop_event_data sd = {
2414 .event = event,
2415 .restart = 1,
2416 };
2417 int ret = 0;
2418
2419 do {
2420 if (READ_ONCE(event->state) != PERF_EVENT_STATE_ACTIVE)
2421 return 0;
2422
2423 /* matches smp_wmb() in event_sched_in() */
2424 smp_rmb();
2425
2426 /*
2427 * We only want to restart ACTIVE events, so if the event goes
2428 * inactive here (event->oncpu==-1), there's nothing more to do;
2429 * fall through with ret==-ENXIO.
2430 */
2431 ret = cpu_function_call(READ_ONCE(event->oncpu),
2432 __perf_event_stop, &sd);
2433 } while (ret == -EAGAIN);
2434
2435 return ret;
2436}
2437
2438/*
2439 * In order to contain the amount of racy and tricky in the address filter
2440 * configuration management, it is a two part process:
2441 *
2442 * (p1) when userspace mappings change as a result of (1) or (2) or (3) below,
2443 * we update the addresses of corresponding vmas in
2444 * event::addr_filters_offs array and bump the event::addr_filters_gen;
2445 * (p2) when an event is scheduled in (pmu::add), it calls
2446 * perf_event_addr_filters_sync() which calls pmu::addr_filters_sync()
2447 * if the generation has changed since the previous call.
2448 *
2449 * If (p1) happens while the event is active, we restart it to force (p2).
2450 *
2451 * (1) perf_addr_filters_apply(): adjusting filters' offsets based on
2452 * pre-existing mappings, called once when new filters arrive via SET_FILTER
2453 * ioctl;
2454 * (2) perf_addr_filters_adjust(): adjusting filters' offsets based on newly
2455 * registered mapping, called for every new mmap(), with mm::mmap_sem down
2456 * for reading;
2457 * (3) perf_event_addr_filters_exec(): clearing filters' offsets in the process
2458 * of exec.
2459 */
2460void perf_event_addr_filters_sync(struct perf_event *event)
2461{
2462 struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);
2463
2464 if (!has_addr_filter(event))
2465 return;
2466
2467 raw_spin_lock(&ifh->lock);
2468 if (event->addr_filters_gen != event->hw.addr_filters_gen) {
2469 event->pmu->addr_filters_sync(event);
2470 event->hw.addr_filters_gen = event->addr_filters_gen;
2471 }
2472 raw_spin_unlock(&ifh->lock);
2473}
2474EXPORT_SYMBOL_GPL(perf_event_addr_filters_sync);
2475
2363static int _perf_event_refresh(struct perf_event *event, int refresh)2476static int _perf_event_refresh(struct perf_event *event, int refresh)
2364{2477{
2365 /*2478 /*
@@ -3209,16 +3322,6 @@ out: · 843 unmodified lines
3209 put_ctx(clone_ctx);3322 put_ctx(clone_ctx);
3210}3323}
3211 3324
3212void perf_event_exec(void)
3213{
3214 int ctxn;
3215
3216 rcu_read_lock();
3217 for_each_task_context_nr(ctxn)
3218 perf_event_enable_on_exec(ctxn);
3219 rcu_read_unlock();
3220}
3221
3222struct perf_read_data {3325struct perf_read_data {
3223 struct perf_event *event;3326 struct perf_event *event;
3224 bool group;3327 bool group;
@@ -3720,6 +3823,9 @@ static bool exclusive_event_installable(struct perf_event *event, · 495 unmodified lines
3720 return true;3823 return true;
3721}3824}
3722 3825
3826static void perf_addr_filters_splice(struct perf_event *event,
3827 struct list_head *head);
3828
3723static void _free_event(struct perf_event *event)3829static void _free_event(struct perf_event *event)
3724{3830{
3725 irq_work_sync(&event->pending);3831 irq_work_sync(&event->pending);
@@ -3747,6 +3853,8 @@ static void _free_event(struct perf_event *event) · 21 unmodified lines
3747 }3853 }
3748 3854
3749 perf_event_free_bpf_prog(event);3855 perf_event_free_bpf_prog(event);
3856 perf_addr_filters_splice(event, NULL);
3857 kfree(event->addr_filters_offs);
3750 3858
3751 if (event->destroy)3859 if (event->destroy)
3752 event->destroy(event);3860 event->destroy(event);
@@ -4343,6 +4451,19 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lon · 590 unmodified lines
4343 case PERF_EVENT_IOC_SET_BPF:4451 case PERF_EVENT_IOC_SET_BPF:
4344 return perf_event_set_bpf_prog(event, arg);4452 return perf_event_set_bpf_prog(event, arg);
4345 4453
4454 case PERF_EVENT_IOC_PAUSE_OUTPUT: {
4455 struct ring_buffer *rb;
4456
4457 rcu_read_lock();
4458 rb = rcu_dereference(event->rb);
4459 if (!rb || !rb->nr_pages) {
4460 rcu_read_unlock();
4461 return -EINVAL;
4462 }
4463 rb_toggle_paused(rb, !!arg);
4464 rcu_read_unlock();
4465 return 0;
4466 }
4346 default:4467 default:
4347 return -ENOTTY;4468 return -ENOTTY;
4348 }4469 }
@@ -4659,6 +4780,8 @@ static void perf_mmap_open(struct vm_area_struct *vma) · 310 unmodified lines
4659 event->pmu->event_mapped(event);4780 event->pmu->event_mapped(event);
4660}4781}
4661 4782
4783static void perf_pmu_output_stop(struct perf_event *event);
4784
4662/*4785/*
4663 * A buffer can be mmap()ed multiple times; either directly through the same4786 * A buffer can be mmap()ed multiple times; either directly through the same
4664 * event, or through other events by use of perf_event_set_output().4787 * event, or through other events by use of perf_event_set_output().
@@ -4686,10 +4809,22 @@ static void perf_mmap_close(struct vm_area_struct *vma) · 21 unmodified lines
4686 */4809 */
4687 if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff &&4810 if (rb_has_aux(rb) && vma->vm_pgoff == rb->aux_pgoff &&
4688 atomic_dec_and_mutex_lock(&rb->aux_mmap_count, &event->mmap_mutex)) {4811 atomic_dec_and_mutex_lock(&rb->aux_mmap_count, &event->mmap_mutex)) {
4812 /*
4813 * Stop all AUX events that are writing to this buffer,
4814 * so that we can free its AUX pages and corresponding PMU
4815 * data. Note that after rb::aux_mmap_count dropped to zero,
4816 * they won't start any more (see perf_aux_output_begin()).
4817 */
4818 perf_pmu_output_stop(event);
4819
4820 /* now it's safe to free the pages */
4689 atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm);4821 atomic_long_sub(rb->aux_nr_pages, &mmap_user->locked_vm);
4690 vma->vm_mm->pinned_vm -= rb->aux_mmap_locked;4822 vma->vm_mm->pinned_vm -= rb->aux_mmap_locked;
4691 4823
4824 /* this has to be the last one */
4692 rb_free_aux(rb);4825 rb_free_aux(rb);
4826 WARN_ON_ONCE(atomic_read(&rb->aux_refcount));
4827
4693 mutex_unlock(&event->mmap_mutex);4828 mutex_unlock(&event->mmap_mutex);
4694 }4829 }
4695 4830
@@ -5630,9 +5765,13 @@ void perf_prepare_sample(struct perf_event_header *header, · 934 unmodified lines
5630 }5765 }
5631}5766}
5632 5767
5633void perf_event_output(struct perf_event *event,5768static void __always_inline
5634 struct perf_sample_data *data,5769__perf_event_output(struct perf_event *event,
5635 struct pt_regs *regs)5770 struct perf_sample_data *data,
5771 struct pt_regs *regs,
5772 int (*output_begin)(struct perf_output_handle *,
5773 struct perf_event *,
5774 unsigned int))
5636{5775{
5637 struct perf_output_handle handle;5776 struct perf_output_handle handle;
5638 struct perf_event_header header;5777 struct perf_event_header header;
@@ -5642,7 +5781,7 @@ void perf_event_output(struct perf_event *event, · 3 unmodified lines
5642 5781
5643 perf_prepare_sample(&header, data, event, regs);5782 perf_prepare_sample(&header, data, event, regs);
5644 5783
5645 if (perf_output_begin(&handle, event, header.size))5784 if (output_begin(&handle, event, header.size))
5646 goto exit;5785 goto exit;
5647 5786
5648 perf_output_sample(&handle, &header, data, event);5787 perf_output_sample(&handle, &header, data, event);
@@ -5653,6 +5792,30 @@ exit: · 4 unmodified lines
5653 rcu_read_unlock();5792 rcu_read_unlock();
5654}5793}
5655 5794
5795void
5796perf_event_output_forward(struct perf_event *event,
5797 struct perf_sample_data *data,
5798 struct pt_regs *regs)
5799{
5800 __perf_event_output(event, data, regs, perf_output_begin_forward);
5801}
5802
5803void
5804perf_event_output_backward(struct perf_event *event,
5805 struct perf_sample_data *data,
5806 struct pt_regs *regs)
5807{
5808 __perf_event_output(event, data, regs, perf_output_begin_backward);
5809}
5810
5811void
5812perf_event_output(struct perf_event *event,
5813 struct perf_sample_data *data,
5814 struct pt_regs *regs)
5815{
5816 __perf_event_output(event, data, regs, perf_output_begin);
5817}
5818
5656/*5819/*
5657 * read event_id5820 * read event_id
5658 */5821 */
@@ -5698,15 +5861,18 @@ typedef void (perf_event_aux_output_cb)(struct perf_event *event, void *data); · 39 unmodified lines
5698static void5861static void
5699perf_event_aux_ctx(struct perf_event_context *ctx,5862perf_event_aux_ctx(struct perf_event_context *ctx,
5700 perf_event_aux_output_cb output,5863 perf_event_aux_output_cb output,
5701 void *data)5864 void *data, bool all)
5702{5865{
5703 struct perf_event *event;5866 struct perf_event *event;
5704 5867
5705 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {5868 list_for_each_entry_rcu(event, &ctx->event_list, event_entry) {
5706 if (event->state < PERF_EVENT_STATE_INACTIVE)5869 if (!all) {
5707 continue;5870 if (event->state < PERF_EVENT_STATE_INACTIVE)
5708 if (!event_filter_match(event))5871 continue;
5709 continue;5872 if (!event_filter_match(event))
5873 continue;
5874 }
5875
5710 output(event, data);5876 output(event, data);
5711 }5877 }
5712}5878}
@@ -5717,7 +5883,7 @@ perf_event_aux_task_ctx(perf_event_aux_output_cb output, void *data, · 4 unmodified lines
5717{5883{
5718 rcu_read_lock();5884 rcu_read_lock();
5719 preempt_disable();5885 preempt_disable();
5720 perf_event_aux_ctx(task_ctx, output, data);5886 perf_event_aux_ctx(task_ctx, output, data, false);
5721 preempt_enable();5887 preempt_enable();
5722 rcu_read_unlock();5888 rcu_read_unlock();
5723}5889}
@@ -5747,19 +5913,147 @@ perf_event_aux(perf_event_aux_output_cb output, void *data, · 23 unmodified lines
5747 cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);5913 cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
5748 if (cpuctx->unique_pmu != pmu)5914 if (cpuctx->unique_pmu != pmu)
5749 goto next;5915 goto next;
5750 perf_event_aux_ctx(&cpuctx->ctx, output, data);5916 perf_event_aux_ctx(&cpuctx->ctx, output, data, false);
5751 ctxn = pmu->task_ctx_nr;5917 ctxn = pmu->task_ctx_nr;
5752 if (ctxn < 0)5918 if (ctxn < 0)
5753 goto next;5919 goto next;
5754 ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);5920 ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
5755 if (ctx)5921 if (ctx)
5756 perf_event_aux_ctx(ctx, output, data);5922 perf_event_aux_ctx(ctx, output, data, false);
5757next:5923next:
5758 put_cpu_ptr(pmu->pmu_cpu_context);5924 put_cpu_ptr(pmu->pmu_cpu_context);
5759 }5925 }
5760 rcu_read_unlock();5926 rcu_read_unlock();
5761}5927}
5762 5928
5929/*
5930 * Clear all file-based filters at exec, they'll have to be
5931 * re-instated when/if these objects are mmapped again.
5932 */
5933static void perf_event_addr_filters_exec(struct perf_event *event, void *data)
5934{
5935 struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);
5936 struct perf_addr_filter *filter;
5937 unsigned int restart = 0, count = 0;
5938 unsigned long flags;
5939
5940 if (!has_addr_filter(event))
5941 return;
5942
5943 raw_spin_lock_irqsave(&ifh->lock, flags);
5944 list_for_each_entry(filter, &ifh->list, entry) {
5945 if (filter->inode) {
5946 event->addr_filters_offs[count] = 0;
5947 restart++;
5948 }
5949
5950 count++;
5951 }
5952
5953 if (restart)
5954 event->addr_filters_gen++;
5955 raw_spin_unlock_irqrestore(&ifh->lock, flags);
5956
5957 if (restart)
5958 perf_event_restart(event);
5959}
5960
5961void perf_event_exec(void)
5962{
5963 struct perf_event_context *ctx;
5964 int ctxn;
5965
5966 rcu_read_lock();
5967 for_each_task_context_nr(ctxn) {
5968 ctx = current->perf_event_ctxp[ctxn];
5969 if (!ctx)
5970 continue;
5971
5972 perf_event_enable_on_exec(ctxn);
5973
5974 perf_event_aux_ctx(ctx, perf_event_addr_filters_exec, NULL,
5975 true);
5976 }
5977 rcu_read_unlock();
5978}
5979
5980struct remote_output {
5981 struct ring_buffer *rb;
5982 int err;
5983};
5984
5985static void __perf_event_output_stop(struct perf_event *event, void *data)
5986{
5987 struct perf_event *parent = event->parent;
5988 struct remote_output *ro = data;
5989 struct ring_buffer *rb = ro->rb;
5990 struct stop_event_data sd = {
5991 .event = event,
5992 };
5993
5994 if (!has_aux(event))
5995 return;
5996
5997 if (!parent)
5998 parent = event;
5999
6000 /*
6001 * In case of inheritance, it will be the parent that links to the
6002 * ring-buffer, but it will be the child that's actually using it:
6003 */
6004 if (rcu_dereference(parent->rb) == rb)
6005 ro->err = __perf_event_stop(&sd);
6006}
6007
6008static int __perf_pmu_output_stop(void *info)
6009{
6010 struct perf_event *event = info;
6011 struct pmu *pmu = event->pmu;
6012 struct perf_cpu_context *cpuctx = get_cpu_ptr(pmu->pmu_cpu_context);
6013 struct remote_output ro = {
6014 .rb = event->rb,
6015 };
6016
6017 rcu_read_lock();
6018 perf_event_aux_ctx(&cpuctx->ctx, __perf_event_output_stop, &ro, false);
6019 if (cpuctx->task_ctx)
6020 perf_event_aux_ctx(cpuctx->task_ctx, __perf_event_output_stop,
6021 &ro, false);
6022 rcu_read_unlock();
6023
6024 return ro.err;
6025}
6026
6027static void perf_pmu_output_stop(struct perf_event *event)
6028{
6029 struct perf_event *iter;
6030 int err, cpu;
6031
6032restart:
6033 rcu_read_lock();
6034 list_for_each_entry_rcu(iter, &event->rb->event_list, rb_entry) {
6035 /*
6036 * For per-CPU events, we need to make sure that neither they
6037 * nor their children are running; for cpu==-1 events it's
6038 * sufficient to stop the event itself if it's active, since
6039 * it can't have children.
6040 */
6041 cpu = iter->cpu;
6042 if (cpu == -1)
6043 cpu = READ_ONCE(iter->oncpu);
6044
6045 if (cpu == -1)
6046 continue;
6047
6048 err = cpu_function_call(cpu, __perf_pmu_output_stop, event);
6049 if (err == -EAGAIN) {
6050 rcu_read_unlock();
6051 goto restart;
6052 }
6053 }
6054 rcu_read_unlock();
6055}
6056
5763/*6057/*
5764 * task tracking -- fork/exit6058 * task tracking -- fork/exit
5765 *6059 *
@@ -6169,6 +6463,87 @@ got_name: · 403 unmodified lines
6169 kfree(buf);6463 kfree(buf);
6170}6464}
6171 6465
6466/*
6467 * Whether this @filter depends on a dynamic object which is not loaded
6468 * yet or its load addresses are not known.
6469 */
6470static bool perf_addr_filter_needs_mmap(struct perf_addr_filter *filter)
6471{
6472 return filter->filter && filter->inode;
6473}
6474
6475/*
6476 * Check whether inode and address range match filter criteria.
6477 */
6478static bool perf_addr_filter_match(struct perf_addr_filter *filter,
6479 struct file *file, unsigned long offset,
6480 unsigned long size)
6481{
6482 if (filter->inode != file->f_inode)
6483 return false;
6484
6485 if (filter->offset > offset + size)
6486 return false;
6487
6488 if (filter->offset + filter->size < offset)
6489 return false;
6490
6491 return true;
6492}
6493
6494static void __perf_addr_filters_adjust(struct perf_event *event, void *data)
6495{
6496 struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);
6497 struct vm_area_struct *vma = data;
6498 unsigned long off = vma->vm_pgoff << PAGE_SHIFT, flags;
6499 struct file *file = vma->vm_file;
6500 struct perf_addr_filter *filter;
6501 unsigned int restart = 0, count = 0;
6502
6503 if (!has_addr_filter(event))
6504 return;
6505
6506 if (!file)
6507 return;
6508
6509 raw_spin_lock_irqsave(&ifh->lock, flags);
6510 list_for_each_entry(filter, &ifh->list, entry) {
6511 if (perf_addr_filter_match(filter, file, off,
6512 vma->vm_end - vma->vm_start)) {
6513 event->addr_filters_offs[count] = vma->vm_start;
6514 restart++;
6515 }
6516
6517 count++;
6518 }
6519
6520 if (restart)
6521 event->addr_filters_gen++;
6522 raw_spin_unlock_irqrestore(&ifh->lock, flags);
6523
6524 if (restart)
6525 perf_event_restart(event);
6526}
6527
6528/*
6529 * Adjust all task's events' filters to the new vma
6530 */
6531static void perf_addr_filters_adjust(struct vm_area_struct *vma)
6532{
6533 struct perf_event_context *ctx;
6534 int ctxn;
6535
6536 rcu_read_lock();
6537 for_each_task_context_nr(ctxn) {
6538 ctx = rcu_dereference(current->perf_event_ctxp[ctxn]);
6539 if (!ctx)
6540 continue;
6541
6542 perf_event_aux_ctx(ctx, __perf_addr_filters_adjust, vma, true);
6543 }
6544 rcu_read_unlock();
6545}
6546
6172void perf_event_mmap(struct vm_area_struct *vma)6547void perf_event_mmap(struct vm_area_struct *vma)
6173{6548{
6174 struct perf_mmap_event mmap_event;6549 struct perf_mmap_event mmap_event;
@@ -6200,6 +6575,7 @@ void perf_event_mmap(struct vm_area_struct *vma) · 25 unmodified lines
6200 /* .flags (attr_mmap2 only) */6575 /* .flags (attr_mmap2 only) */
6201 };6576 };
6202 6577
6578 perf_addr_filters_adjust(vma);
6203 perf_event_mmap_event(&mmap_event);6579 perf_event_mmap_event(&mmap_event);
6204}6580}
6205 6581
@@ -6491,10 +6867,7 @@ static int __perf_event_overflow(struct perf_event *event, · 285 unmodified lines
6491 irq_work_queue(&event->pending);6867 irq_work_queue(&event->pending);
6492 }6868 }
6493 6869
6494 if (event->overflow_handler)6870 event->overflow_handler(event, data, regs);
6495 event->overflow_handler(event, data, regs);
6496 else
6497 perf_event_output(event, data, regs);
6498 6871
6499 if (*perf_event_fasync(event) && event->pending_kill) {6872 if (*perf_event_fasync(event) && event->pending_kill) {
6500 event->pending_wakeup = 1;6873 event->pending_wakeup = 1;
@@ -7081,24 +7454,6 @@ static inline void perf_tp_register(void) · 580 unmodified lines
7081 perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);7454 perf_pmu_register(&perf_tracepoint, "tracepoint", PERF_TYPE_TRACEPOINT);
7082}7455}
7083 7456
7084static int perf_event_set_filter(struct perf_event *event, void __user *arg)
7085{
7086 char *filter_str;
7087 int ret;
7088
7089 if (event->attr.type != PERF_TYPE_TRACEPOINT)
7090 return -EINVAL;
7091
7092 filter_str = strndup_user(arg, PAGE_SIZE);
7093 if (IS_ERR(filter_str))
7094 return PTR_ERR(filter_str);
7095
7096 ret = ftrace_profile_set_filter(event, event->attr.config, filter_str);
7097
7098 kfree(filter_str);
7099 return ret;
7100}
7101
7102static void perf_event_free_filter(struct perf_event *event)7457static void perf_event_free_filter(struct perf_event *event)
7103{7458{
7104 ftrace_profile_free_filter(event);7459 ftrace_profile_free_filter(event);
@@ -7153,11 +7508,6 @@ static inline void perf_tp_register(void) · 48 unmodified lines
7153{7508{
7154}7509}
7155 7510
7156static int perf_event_set_filter(struct perf_event *event, void __user *arg)
7157{
7158 return -ENOENT;
7159}
7160
7161static void perf_event_free_filter(struct perf_event *event)7511static void perf_event_free_filter(struct perf_event *event)
7162{7512{
7163}7513}
@@ -7185,6 +7535,387 @@ void perf_bp_event(struct perf_event *bp, void *data) · 21 unmodified lines
7185}7535}
7186#endif7536#endif
7187 7537
7538/*
7539 * Allocate a new address filter
7540 */
7541static struct perf_addr_filter *
7542perf_addr_filter_new(struct perf_event *event, struct list_head *filters)
7543{
7544 int node = cpu_to_node(event->cpu == -1 ? 0 : event->cpu);
7545 struct perf_addr_filter *filter;
7546
7547 filter = kzalloc_node(sizeof(*filter), GFP_KERNEL, node);
7548 if (!filter)
7549 return NULL;
7550
7551 INIT_LIST_HEAD(&filter->entry);
7552 list_add_tail(&filter->entry, filters);
7553
7554 return filter;
7555}
7556
7557static void free_filters_list(struct list_head *filters)
7558{
7559 struct perf_addr_filter *filter, *iter;
7560
7561 list_for_each_entry_safe(filter, iter, filters, entry) {
7562 if (filter->inode)
7563 iput(filter->inode);
7564 list_del(&filter->entry);
7565 kfree(filter);
7566 }
7567}
7568
7569/*
7570 * Free existing address filters and optionally install new ones
7571 */
7572static void perf_addr_filters_splice(struct perf_event *event,
7573 struct list_head *head)
7574{
7575 unsigned long flags;
7576 LIST_HEAD(list);
7577
7578 if (!has_addr_filter(event))
7579 return;
7580
7581 /* don't bother with children, they don't have their own filters */
7582 if (event->parent)
7583 return;
7584
7585 raw_spin_lock_irqsave(&event->addr_filters.lock, flags);
7586
7587 list_splice_init(&event->addr_filters.list, &list);
7588 if (head)
7589 list_splice(head, &event->addr_filters.list);
7590
7591 raw_spin_unlock_irqrestore(&event->addr_filters.lock, flags);
7592
7593 free_filters_list(&list);
7594}
7595
7596/*
7597 * Scan through mm's vmas and see if one of them matches the
7598 * @filter; if so, adjust filter's address range.
7599 * Called with mm::mmap_sem down for reading.
7600 */
7601static unsigned long perf_addr_filter_apply(struct perf_addr_filter *filter,
7602 struct mm_struct *mm)
7603{
7604 struct vm_area_struct *vma;
7605
7606 for (vma = mm->mmap; vma; vma = vma->vm_next) {
7607 struct file *file = vma->vm_file;
7608 unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
7609 unsigned long vma_size = vma->vm_end - vma->vm_start;
7610
7611 if (!file)
7612 continue;
7613
7614 if (!perf_addr_filter_match(filter, file, off, vma_size))
7615 continue;
7616
7617 return vma->vm_start;
7618 }
7619
7620 return 0;
7621}
7622
7623/*
7624 * Update event's address range filters based on the
7625 * task's existing mappings, if any.
7626 */
7627static void perf_event_addr_filters_apply(struct perf_event *event)
7628{
7629 struct perf_addr_filters_head *ifh = perf_event_addr_filters(event);
7630 struct task_struct *task = READ_ONCE(event->ctx->task);
7631 struct perf_addr_filter *filter;
7632 struct mm_struct *mm = NULL;
7633 unsigned int count = 0;
7634 unsigned long flags;
7635
7636 /*
7637 * We may observe TASK_TOMBSTONE, which means that the event tear-down
7638 * will stop on the parent's child_mutex that our caller is also holding
7639 */
7640 if (task == TASK_TOMBSTONE)
7641 return;
7642
7643 mm = get_task_mm(event->ctx->task);
7644 if (!mm)
7645 goto restart;
7646
7647 down_read(&mm->mmap_sem);
7648
7649 raw_spin_lock_irqsave(&ifh->lock, flags);
7650 list_for_each_entry(filter, &ifh->list, entry) {
7651 event->addr_filters_offs[count] = 0;
7652
7653 if (perf_addr_filter_needs_mmap(filter))
7654 event->addr_filters_offs[count] =
7655 perf_addr_filter_apply(filter, mm);
7656
7657 count++;
7658 }
7659
7660 event->addr_filters_gen++;
7661 raw_spin_unlock_irqrestore(&ifh->lock, flags);
7662
7663 up_read(&mm->mmap_sem);
7664
7665 mmput(mm);
7666
7667restart:
7668 perf_event_restart(event);
7669}
7670
7671/*
7672 * Address range filtering: limiting the data to certain
7673 * instruction address ranges. Filters are ioctl()ed to us from
7674 * userspace as ascii strings.
7675 *
7676 * Filter string format:
7677 *
7678 * ACTION RANGE_SPEC
7679 * where ACTION is one of the
7680 * * "filter": limit the trace to this region
7681 * * "start": start tracing from this address
7682 * * "stop": stop tracing at this address/region;
7683 * RANGE_SPEC is
7684 * * for kernel addresses: <start address>[/<size>]
7685 * * for object files: <start address>[/<size>]@</path/to/object/file>
7686 *
7687 * if <size> is not specified, the range is treated as a single address.
7688 */
7689enum {
7690 IF_ACT_FILTER,
7691 IF_ACT_START,
7692 IF_ACT_STOP,
7693 IF_SRC_FILE,
7694 IF_SRC_KERNEL,
7695 IF_SRC_FILEADDR,
7696 IF_SRC_KERNELADDR,
7697};
7698
7699enum {
7700 IF_STATE_ACTION = 0,
7701 IF_STATE_SOURCE,
7702 IF_STATE_END,
7703};
7704
7705static const match_table_t if_tokens = {
7706 { IF_ACT_FILTER, "filter" },
7707 { IF_ACT_START, "start" },
7708 { IF_ACT_STOP, "stop" },
7709 { IF_SRC_FILE, "%u/%u@%s" },
7710 { IF_SRC_KERNEL, "%u/%u" },
7711 { IF_SRC_FILEADDR, "%u@%s" },
7712 { IF_SRC_KERNELADDR, "%u" },
7713};
7714
7715/*
7716 * Address filter string parser
7717 */
7718static int
7719perf_event_parse_addr_filter(struct perf_event *event, char *fstr,
7720 struct list_head *filters)
7721{
7722 struct perf_addr_filter *filter = NULL;
7723 char *start, *orig, *filename = NULL;
7724 struct path path;
7725 substring_t args[MAX_OPT_ARGS];
7726 int state = IF_STATE_ACTION, token;
7727 unsigned int kernel = 0;
7728 int ret = -EINVAL;
7729
7730 orig = fstr = kstrdup(fstr, GFP_KERNEL);
7731 if (!fstr)
7732 return -ENOMEM;
7733
7734 while ((start = strsep(&fstr, " ,\n")) != NULL) {
7735 ret = -EINVAL;
7736
7737 if (!*start)
7738 continue;
7739
7740 /* filter definition begins */
7741 if (state == IF_STATE_ACTION) {
7742 filter = perf_addr_filter_new(event, filters);
7743 if (!filter)
7744 goto fail;
7745 }
7746
7747 token = match_token(start, if_tokens, args);
7748 switch (token) {
7749 case IF_ACT_FILTER:
7750 case IF_ACT_START:
7751 filter->filter = 1;
7752
7753 case IF_ACT_STOP:
7754 if (state != IF_STATE_ACTION)
7755 goto fail;
7756
7757 state = IF_STATE_SOURCE;
7758 break;
7759
7760 case IF_SRC_KERNELADDR:
7761 case IF_SRC_KERNEL:
7762 kernel = 1;
7763
7764 case IF_SRC_FILEADDR:
7765 case IF_SRC_FILE:
7766 if (state != IF_STATE_SOURCE)
7767 goto fail;
7768
7769 if (token == IF_SRC_FILE || token == IF_SRC_KERNEL)
7770 filter->range = 1;
7771
7772 *args[0].to = 0;
7773 ret = kstrtoul(args[0].from, 0, &filter->offset);
7774 if (ret)
7775 goto fail;
7776
7777 if (filter->range) {
7778 *args[1].to = 0;
7779 ret = kstrtoul(args[1].from, 0, &filter->size);
7780 if (ret)
7781 goto fail;
7782 }
7783
7784 if (token == IF_SRC_FILE) {
7785 filename = match_strdup(&args[2]);
7786 if (!filename) {
7787 ret = -ENOMEM;
7788 goto fail;
7789 }
7790 }
7791
7792 state = IF_STATE_END;
7793 break;
7794
7795 default:
7796 goto fail;
7797 }
7798
7799 /*
7800 * Filter definition is fully parsed, validate and install it.
7801 * Make sure that it doesn't contradict itself or the event's
7802 * attribute.
7803 */
7804 if (state == IF_STATE_END) {
7805 if (kernel && event->attr.exclude_kernel)
7806 goto fail;
7807
7808 if (!kernel) {
7809 if (!filename)
7810 goto fail;
7811
7812 /* look up the path and grab its inode */
7813 ret = kern_path(filename, LOOKUP_FOLLOW, &path);
7814 if (ret)
7815 goto fail_free_name;
7816
7817 filter->inode = igrab(d_inode(path.dentry));
7818 path_put(&path);
7819 kfree(filename);
7820 filename = NULL;
7821
7822 ret = -EINVAL;
7823 if (!filter->inode ||
7824 !S_ISREG(filter->inode->i_mode))
7825 /* free_filters_list() will iput() */
7826 goto fail;
7827 }
7828
7829 /* ready to consume more filters */
7830 state = IF_STATE_ACTION;
7831 filter = NULL;
7832 }
7833 }
7834
7835 if (state != IF_STATE_ACTION)
7836 goto fail;
7837
7838 kfree(orig);
7839
7840 return 0;
7841
7842fail_free_name:
7843 kfree(filename);
7844fail:
7845 free_filters_list(filters);
7846 kfree(orig);
7847
7848 return ret;
7849}
7850
7851static int
7852perf_event_set_addr_filter(struct perf_event *event, char *filter_str)
7853{
7854 LIST_HEAD(filters);
7855 int ret;
7856
7857 /*
7858 * Since this is called in perf_ioctl() path, we're already holding
7859 * ctx::mutex.
7860 */
7861 lockdep_assert_held(&event->ctx->mutex);
7862
7863 if (WARN_ON_ONCE(event->parent))
7864 return -EINVAL;
7865
7866 /*
7867 * For now, we only support filtering in per-task events; doing so
7868 * for CPU-wide events requires additional context switching trickery,
7869 * since same object code will be mapped at different virtual
7870 * addresses in different processes.
7871 */
7872 if (!event->ctx->task)
7873 return -EOPNOTSUPP;
7874
7875 ret = perf_event_parse_addr_filter(event, filter_str, &filters);
7876 if (ret)
7877 return ret;
7878
7879 ret = event->pmu->addr_filters_validate(&filters);
7880 if (ret) {
7881 free_filters_list(&filters);
7882 return ret;
7883 }
7884
7885 /* remove existing filters, if any */
7886 perf_addr_filters_splice(event, &filters);
7887
7888 /* install new filters */
7889 perf_event_for_each_child(event, perf_event_addr_filters_apply);
7890
7891 return ret;
7892}
7893
7894static int perf_event_set_filter(struct perf_event *event, void __user *arg)
7895{
7896 char *filter_str;
7897 int ret = -EINVAL;
7898
7899 if ((event->attr.type != PERF_TYPE_TRACEPOINT ||
7900 !IS_ENABLED(CONFIG_EVENT_TRACING)) &&
7901 !has_addr_filter(event))
7902 return -EINVAL;
7903
7904 filter_str = strndup_user(arg, PAGE_SIZE);
7905 if (IS_ERR(filter_str))
7906 return PTR_ERR(filter_str);
7907
7908 if (IS_ENABLED(CONFIG_EVENT_TRACING) &&
7909 event->attr.type == PERF_TYPE_TRACEPOINT)
7910 ret = ftrace_profile_set_filter(event, event->attr.config,
7911 filter_str);
7912 else if (has_addr_filter(event))
7913 ret = perf_event_set_addr_filter(event, filter_str);
7914
7915 kfree(filter_str);
7916 return ret;
7917}
7918
7188/*7919/*
7189 * hrtimer based swevent callback7920 * hrtimer based swevent callback
7190 */7921 */
@@ -7542,6 +8273,20 @@ static void free_pmu_context(struct pmu *pmu) · 351 unmodified lines
7542out:8273out:
7543 mutex_unlock(&pmus_lock);8274 mutex_unlock(&pmus_lock);
7544}8275}
8276
8277/*
8278 * Let userspace know that this PMU supports address range filtering:
8279 */
8280static ssize_t nr_addr_filters_show(struct device *dev,
8281 struct device_attribute *attr,
8282 char *page)
8283{
8284 struct pmu *pmu = dev_get_drvdata(dev);
8285
8286 return snprintf(page, PAGE_SIZE - 1, "%d\n", pmu->nr_addr_filters);
8287}
8288DEVICE_ATTR_RO(nr_addr_filters);
8289
7545static struct idr pmu_idr;8290static struct idr pmu_idr;
7546 8291
7547static ssize_t8292static ssize_t
@@ -7643,9 +8388,19 @@ static int pmu_dev_alloc(struct pmu *pmu) · 95 unmodified lines
7643 if (ret)8388 if (ret)
7644 goto free_dev;8389 goto free_dev;
7645 8390
8391 /* For PMUs with address filters, throw in an extra attribute: */
8392 if (pmu->nr_addr_filters)
8393 ret = device_create_file(pmu->dev, &dev_attr_nr_addr_filters);
8394
8395 if (ret)
8396 goto del_dev;
8397
7646out:8398out:
7647 return ret;8399 return ret;
7648 8400
8401del_dev:
8402 device_del(pmu->dev);
8403
7649free_dev:8404free_dev:
7650 put_device(pmu->dev);8405 put_device(pmu->dev);
7651 goto out;8406 goto out;
@@ -7685,6 +8440,21 @@ int perf_pmu_register(struct pmu *pmu, const char *name, int type) · 33 unmodified lines
7685 }8440 }
7686 8441
7687skip_type:8442skip_type:
8443 if (pmu->task_ctx_nr == perf_hw_context) {
8444 static int hw_context_taken = 0;
8445
8446 /*
8447 * Other than systems with heterogeneous CPUs, it never makes
8448 * sense for two PMUs to share perf_hw_context. PMUs which are
8449 * uncore must use perf_invalid_context.
8450 */
8451 if (WARN_ON_ONCE(hw_context_taken &&
8452 !(pmu->capabilities & PERF_PMU_CAP_HETEROGENEOUS_CPUS)))
8453 pmu->task_ctx_nr = perf_invalid_context;
8454
8455 hw_context_taken = 1;
8456 }
8457
7688 pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);8458 pmu->pmu_cpu_context = find_pmu_context(pmu->task_ctx_nr);
7689 if (pmu->pmu_cpu_context)8459 if (pmu->pmu_cpu_context)
7690 goto got_cpu_context;8460 goto got_cpu_context;
@@ -7772,6 +8542,8 @@ void perf_pmu_unregister(struct pmu *pmu) · 81 unmodified lines
7772 free_percpu(pmu->pmu_disable_count);8542 free_percpu(pmu->pmu_disable_count);
7773 if (pmu->type >= PERF_TYPE_MAX)8543 if (pmu->type >= PERF_TYPE_MAX)
7774 idr_remove(&pmu_idr, pmu->type);8544 idr_remove(&pmu_idr, pmu->type);
8545 if (pmu->nr_addr_filters)
8546 device_remove_file(pmu->dev, &dev_attr_nr_addr_filters);
7775 device_del(pmu->dev);8547 device_del(pmu->dev);
7776 put_device(pmu->dev);8548 put_device(pmu->dev);
7777 free_pmu_context(pmu);8549 free_pmu_context(pmu);
@@ -7965,6 +8737,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, · 187 unmodified lines
7965 INIT_LIST_HEAD(&event->sibling_list);8737 INIT_LIST_HEAD(&event->sibling_list);
7966 INIT_LIST_HEAD(&event->rb_entry);8738 INIT_LIST_HEAD(&event->rb_entry);
7967 INIT_LIST_HEAD(&event->active_entry);8739 INIT_LIST_HEAD(&event->active_entry);
8740 INIT_LIST_HEAD(&event->addr_filters.list);
7968 INIT_HLIST_NODE(&event->hlist_entry);8741 INIT_HLIST_NODE(&event->hlist_entry);
7969 8742
7970 8743
@@ -7972,6 +8745,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, · 1 unmodified line
7972 init_irq_work(&event->pending, perf_pending_event);8745 init_irq_work(&event->pending, perf_pending_event);
7973 8746
7974 mutex_init(&event->mmap_mutex);8747 mutex_init(&event->mmap_mutex);
8748 raw_spin_lock_init(&event->addr_filters.lock);
7975 8749
7976 atomic_long_set(&event->refcount, 1);8750 atomic_long_set(&event->refcount, 1);
7977 event->cpu = cpu;8751 event->cpu = cpu;
@@ -8006,8 +8780,16 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, · 28 unmodified lines
8006 context = parent_event->overflow_handler_context;8780 context = parent_event->overflow_handler_context;
8007 }8781 }
8008 8782
8009 event->overflow_handler = overflow_handler;8783 if (overflow_handler) {
8010 event->overflow_handler_context = context;8784 event->overflow_handler = overflow_handler;
8785 event->overflow_handler_context = context;
8786 } else if (is_write_backward(event)){
8787 event->overflow_handler = perf_event_output_backward;
8788 event->overflow_handler_context = NULL;
8789 } else {
8790 event->overflow_handler = perf_event_output_forward;
8791 event->overflow_handler_context = NULL;
8792 }
8011 8793
8012 perf_event__state_init(event);8794 perf_event__state_init(event);
8013 8795
@@ -8048,11 +8830,22 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, · 34 unmodified lines
8048 if (err)8830 if (err)
8049 goto err_pmu;8831 goto err_pmu;
8050 8832
8833 if (has_addr_filter(event)) {
8834 event->addr_filters_offs = kcalloc(pmu->nr_addr_filters,
8835 sizeof(unsigned long),
8836 GFP_KERNEL);
8837 if (!event->addr_filters_offs)
8838 goto err_per_task;
8839
8840 /* force hw sync on the address filters */
8841 event->addr_filters_gen = 1;
8842 }
8843
8051 if (!event->parent) {8844 if (!event->parent) {
8052 if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {8845 if (event->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
8053 err = get_callchain_buffers();8846 err = get_callchain_buffers();
8054 if (err)8847 if (err)
8055 goto err_per_task;8848 goto err_addr_filters;
8056 }8849 }
8057 }8850 }
8058 8851
@@ -8061,6 +8854,9 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu, · 2 unmodified lines
8061 8854
8062 return event;8855 return event;
8063 8856
8857err_addr_filters:
8858 kfree(event->addr_filters_offs);
8859
8064err_per_task:8860err_per_task:
8065 exclusive_event_destroy(event);8861 exclusive_event_destroy(event);
8066 8862
@@ -8239,6 +9035,13 @@ perf_event_set_output(struct perf_event *event, struct perf_event *output_event) · 172 unmodified lines
8239 if (output_event->clock != event->clock)9035 if (output_event->clock != event->clock)
8240 goto out;9036 goto out;
8241 9037
9038 /*
9039 * Either writing ring buffer from beginning or from end.
9040 * Mixing is not allowed.
9041 */
9042 if (is_write_backward(output_event) != is_write_backward(event))
9043 goto out;
9044
8242 /*9045 /*
8243 * If both events generate aux data, they must be on the same PMU9046 * If both events generate aux data, they must be on the same PMU
8244 */9047 */
kernel/events/internal.h+9−1
@@ -11,13 +11,13 @@ · 10 unmodified lines
11struct ring_buffer {11struct ring_buffer {
12 atomic_t refcount;12 atomic_t refcount;
13 struct rcu_head rcu_head;13 struct rcu_head rcu_head;
14 struct irq_work irq_work;
15#ifdef CONFIG_PERF_USE_VMALLOC14#ifdef CONFIG_PERF_USE_VMALLOC
16 struct work_struct work;15 struct work_struct work;
17 int page_order; /* allocation order */16 int page_order; /* allocation order */
18#endif17#endif
19 int nr_pages; /* nr of data pages */18 int nr_pages; /* nr of data pages */
20 int overwrite; /* can overwrite itself */19 int overwrite; /* can overwrite itself */
20 int paused; /* can write into ring buffer */
21 21
22 atomic_t poll; /* POLL_ for wakeups */22 atomic_t poll; /* POLL_ for wakeups */
23 23
@@ -65,6 +65,14 @@ static inline void rb_free_rcu(struct rcu_head *rcu_head) · 41 unmodified lines
65 rb_free(rb);65 rb_free(rb);
66}66}
67 67
68static inline void rb_toggle_paused(struct ring_buffer *rb, bool pause)
69{
70 if (!pause && rb->nr_pages)
71 rb->paused = 0;
72 else
73 rb->paused = 1;
74}
75
68extern struct ring_buffer *76extern struct ring_buffer *
69rb_alloc(int nr_pages, long watermark, int cpu, int flags);77rb_alloc(int nr_pages, long watermark, int cpu, int flags);
70extern void perf_event_wakeup(struct perf_event *event);78extern void perf_event_wakeup(struct perf_event *event);
kernel/events/ring_buffer.c+87−31
@@ -102,8 +102,21 @@ out: · 101 unmodified lines
102 preempt_enable();102 preempt_enable();
103}103}
104 104
105int perf_output_begin(struct perf_output_handle *handle,105static bool __always_inline
106 struct perf_event *event, unsigned int size)106ring_buffer_has_space(unsigned long head, unsigned long tail,
107 unsigned long data_size, unsigned int size,
108 bool backward)
109{
110 if (!backward)
111 return CIRC_SPACE(head, tail, data_size) >= size;
112 else
113 return CIRC_SPACE(tail, head, data_size) >= size;
114}
115
116static int __always_inline
117__perf_output_begin(struct perf_output_handle *handle,
118 struct perf_event *event, unsigned int size,
119 bool backward)
107{120{
108 struct ring_buffer *rb;121 struct ring_buffer *rb;
109 unsigned long tail, offset, head;122 unsigned long tail, offset, head;
@@ -125,8 +138,11 @@ int perf_output_begin(struct perf_output_handle *handle, · 15 unmodified lines
125 if (unlikely(!rb))138 if (unlikely(!rb))
126 goto out;139 goto out;
127 140
128 if (unlikely(!rb->nr_pages))141 if (unlikely(rb->paused)) {
142 if (rb->nr_pages)
143 local_inc(&rb->lost);
129 goto out;144 goto out;
145 }
130 146
131 handle->rb = rb;147 handle->rb = rb;
132 handle->event = event;148 handle->event = event;
@@ -143,9 +159,12 @@ int perf_output_begin(struct perf_output_handle *handle, · 10 unmodified lines
143 do {159 do {
144 tail = READ_ONCE(rb->user_page->data_tail);160 tail = READ_ONCE(rb->user_page->data_tail);
145 offset = head = local_read(&rb->head);161 offset = head = local_read(&rb->head);
146 if (!rb->overwrite &&162 if (!rb->overwrite) {
147 unlikely(CIRC_SPACE(head, tail, perf_data_size(rb)) < size))163 if (unlikely(!ring_buffer_has_space(head, tail,
148 goto fail;164 perf_data_size(rb),
165 size, backward)))
166 goto fail;
167 }
149 168
150 /*169 /*
151 * The above forms a control dependency barrier separating the170 * The above forms a control dependency barrier separating the
@@ -159,9 +178,17 @@ int perf_output_begin(struct perf_output_handle *handle, · 7 unmodified lines
159 * See perf_output_put_handle().178 * See perf_output_put_handle().
160 */179 */
161 180
162 head += size;181 if (!backward)
182 head += size;
183 else
184 head -= size;
163 } while (local_cmpxchg(&rb->head, offset, head) != offset);185 } while (local_cmpxchg(&rb->head, offset, head) != offset);
164 186
187 if (backward) {
188 offset = head;
189 head = (u64)(-head);
190 }
191
165 /*192 /*
166 * We rely on the implied barrier() by local_cmpxchg() to ensure193 * We rely on the implied barrier() by local_cmpxchg() to ensure
167 * none of the data stores below can be lifted up by the compiler.194 * none of the data stores below can be lifted up by the compiler.
@@ -203,6 +230,26 @@ out: · 35 unmodified lines
203 return -ENOSPC;230 return -ENOSPC;
204}231}
205 232
233int perf_output_begin_forward(struct perf_output_handle *handle,
234 struct perf_event *event, unsigned int size)
235{
236 return __perf_output_begin(handle, event, size, false);
237}
238
239int perf_output_begin_backward(struct perf_output_handle *handle,
240 struct perf_event *event, unsigned int size)
241{
242 return __perf_output_begin(handle, event, size, true);
243}
244
245int perf_output_begin(struct perf_output_handle *handle,
246 struct perf_event *event, unsigned int size)
247{
248
249 return __perf_output_begin(handle, event, size,
250 unlikely(is_write_backward(event)));
251}
252
206unsigned int perf_output_copy(struct perf_output_handle *handle,253unsigned int perf_output_copy(struct perf_output_handle *handle,
207 const void *buf, unsigned int len)254 const void *buf, unsigned int len)
208{255{
@@ -221,8 +268,6 @@ void perf_output_end(struct perf_output_handle *handle) · 12 unmodified lines
221 rcu_read_unlock();268 rcu_read_unlock();
222}269}
223 270
224static void rb_irq_work(struct irq_work *work);
225
226static void271static void
227ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)272ring_buffer_init(struct ring_buffer *rb, long watermark, int flags)
228{273{
@@ -243,16 +288,13 @@ ring_buffer_init(struct ring_buffer *rb, long watermark, int flags) · 14 unmodified lines
243 288
244 INIT_LIST_HEAD(&rb->event_list);289 INIT_LIST_HEAD(&rb->event_list);
245 spin_lock_init(&rb->event_lock);290 spin_lock_init(&rb->event_lock);
246 init_irq_work(&rb->irq_work, rb_irq_work);
247}
248 291
249static void ring_buffer_put_async(struct ring_buffer *rb)292 /*
250{293 * perf_output_begin() only checks rb->paused, therefore
251 if (!atomic_dec_and_test(&rb->refcount))294 * rb->paused must be true if we have no pages for output.
252 return;295 */
253 296 if (!rb->nr_pages)
254 rb->rcu_head.next = (void *)rb;297 rb->paused = 1;
255 irq_work_queue(&rb->irq_work);
256}298}
257 299
258/*300/*
@@ -264,6 +306,10 @@ static void ring_buffer_put_async(struct ring_buffer *rb) · 5 unmodified lines
264 * The ordering is similar to that of perf_output_{begin,end}, with306 * The ordering is similar to that of perf_output_{begin,end}, with
265 * the exception of (B), which should be taken care of by the pmu307 * the exception of (B), which should be taken care of by the pmu
266 * driver, since ordering rules will differ depending on hardware.308 * driver, since ordering rules will differ depending on hardware.
309 *
310 * Call this from pmu::start(); see the comment in perf_aux_output_end()
311 * about its use in pmu callbacks. Both can also be called from the PMI
312 * handler if needed.
267 */313 */
268void *perf_aux_output_begin(struct perf_output_handle *handle,314void *perf_aux_output_begin(struct perf_output_handle *handle,
269 struct perf_event *event)315 struct perf_event *event)
@@ -287,6 +333,13 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, · 17 unmodified lines
287 if (!rb_has_aux(rb) || !atomic_inc_not_zero(&rb->aux_refcount))333 if (!rb_has_aux(rb) || !atomic_inc_not_zero(&rb->aux_refcount))
288 goto err;334 goto err;
289 335
336 /*
337 * If rb::aux_mmap_count is zero (and rb_has_aux() above went through),
338 * the aux buffer is in perf_mmap_close(), about to get freed.
339 */
340 if (!atomic_read(&rb->aux_mmap_count))
341 goto err_put;
342
290 /*343 /*
291 * Nesting is not supported for AUX area, make sure nested344 * Nesting is not supported for AUX area, make sure nested
292 * writers are caught early345 * writers are caught early
@@ -328,10 +381,11 @@ void *perf_aux_output_begin(struct perf_output_handle *handle, · 35 unmodified lines
328 return handle->rb->aux_priv;381 return handle->rb->aux_priv;
329 382
330err_put:383err_put:
384 /* can't be last */
331 rb_free_aux(rb);385 rb_free_aux(rb);
332 386
333err:387err:
334 ring_buffer_put_async(rb);388 ring_buffer_put(rb);
335 handle->event = NULL;389 handle->event = NULL;
336 390
337 return NULL;391 return NULL;
@@ -342,6 +396,10 @@ err: · 4 unmodified lines
342 * aux_head and posting a PERF_RECORD_AUX into the perf buffer. It is the396 * aux_head and posting a PERF_RECORD_AUX into the perf buffer. It is the
343 * pmu driver's responsibility to observe ordering rules of the hardware,397 * pmu driver's responsibility to observe ordering rules of the hardware,
344 * so that all the data is externally visible before this is called.398 * so that all the data is externally visible before this is called.
399 *
400 * Note: this has to be called from pmu::stop() callback, as the assumption
401 * of the AUX buffer management code is that after pmu::stop(), the AUX
402 * transaction must be stopped and therefore drop the AUX reference count.
345 */403 */
346void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,404void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size,
347 bool truncated)405 bool truncated)
@@ -389,8 +447,9 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size, · 41 unmodified lines
389 handle->event = NULL;447 handle->event = NULL;
390 448
391 local_set(&rb->aux_nest, 0);449 local_set(&rb->aux_nest, 0);
450 /* can't be last */
392 rb_free_aux(rb);451 rb_free_aux(rb);
393 ring_buffer_put_async(rb);452 ring_buffer_put(rb);
394}453}
395 454
396/*455/*
@@ -471,6 +530,14 @@ static void __rb_free_aux(struct ring_buffer *rb) · 74 unmodified lines
471{530{
472 int pg;531 int pg;
473 532
533 /*
534 * Should never happen, the last reference should be dropped from
535 * perf_mmap_close() path, which first stops aux transactions (which
536 * in turn are the atomic holders of aux_refcount) and then does the
537 * last rb_free_aux().
538 */
539 WARN_ON_ONCE(in_atomic());
540
474 if (rb->aux_priv) {541 if (rb->aux_priv) {
475 rb->free_aux(rb->aux_priv);542 rb->free_aux(rb->aux_priv);
476 rb->free_aux = NULL;543 rb->free_aux = NULL;
@@ -582,18 +649,7 @@ out: · 105 unmodified lines
582void rb_free_aux(struct ring_buffer *rb)649void rb_free_aux(struct ring_buffer *rb)
583{650{
584 if (atomic_dec_and_test(&rb->aux_refcount))651 if (atomic_dec_and_test(&rb->aux_refcount))
585 irq_work_queue(&rb->irq_work);
586}
587
588static void rb_irq_work(struct irq_work *work)
589{
590 struct ring_buffer *rb = container_of(work, struct ring_buffer, irq_work);
591
592 if (!atomic_read(&rb->aux_refcount))
593 __rb_free_aux(rb);652 __rb_free_aux(rb);
594
595 if (rb->rcu_head.next == (void *)rb)
596 call_rcu(&rb->rcu_head, rb_free_rcu);
597}653}
598 654
599#ifndef CONFIG_PERF_USE_VMALLOC655#ifndef CONFIG_PERF_USE_VMALLOC
kernel/sysctl.c+12−0
@@ -130,6 +130,9 @@ static int one_thousand = 1000; · 129 unmodified lines
130#ifdef CONFIG_PRINTK130#ifdef CONFIG_PRINTK
131static int ten_thousand = 10000;131static int ten_thousand = 10000;
132#endif132#endif
133#ifdef CONFIG_PERF_EVENTS
134static int six_hundred_forty_kb = 640 * 1024;
135#endif
133 136
134/* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */137/* this is needed for the proc_doulongvec_minmax of vm_dirty_bytes */
135static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;138static unsigned long dirty_bytes_min = 2 * PAGE_SIZE;
@@ -1144,6 +1147,15 @@ static struct ctl_table kern_table[] = { · 1008 unmodified lines
1144 .extra1 = &zero,1147 .extra1 = &zero,
1145 .extra2 = &one_hundred,1148 .extra2 = &one_hundred,
1146 },1149 },
1150 {
1151 .procname = "perf_event_max_stack",
1152 .data = NULL, /* filled in by handler */
1153 .maxlen = sizeof(sysctl_perf_event_max_stack),
1154 .mode = 0644,
1155 .proc_handler = perf_event_max_stack_handler,
1156 .extra1 = &zero,
1157 .extra2 = &six_hundred_forty_kb,
1158 },
1147#endif1159#endif
1148#ifdef CONFIG_KMEMCHECK1160#ifdef CONFIG_KMEMCHECK
1149 {1161 {
kernel/trace/trace_event_perf.c+3−0
@@ -47,6 +47,9 @@ static int perf_trace_event_perm(struct trace_event_call *tp_event, · 46 unmodified lines
47 if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))47 if (perf_paranoid_tracepoint_raw() && !capable(CAP_SYS_ADMIN))
48 return -EPERM;48 return -EPERM;
49 49
50 if (!is_sampling_event(p_event))
51 return 0;
52
50 /*53 /*
51 * We don't allow user space callchains for function trace54 * We don't allow user space callchains for function trace
52 * event, due to issues with page faults while tracing page55 * event, due to issues with page faults while tracing page
tools/Makefile+2−1
@@ -137,7 +137,8 @@ libsubcmd_clean: · 136 unmodified lines
137 $(call descend,lib/subcmd,clean)137 $(call descend,lib/subcmd,clean)
138 138
139perf_clean:139perf_clean:
140 $(call descend,$(@:_clean=),clean)140 $(Q)mkdir -p $(PERF_O) .
141 $(Q)$(MAKE) --no-print-directory -C perf O=$(PERF_O) subdir= clean
141 142
142selftests_clean:143selftests_clean:
143 $(call descend,testing/$(@:_clean=),clean)144 $(call descend,testing/$(@:_clean=),clean)
tools/build/Makefile.feature+7−1
@@ -49,6 +49,10 @@ FEATURE_TESTS_BASIC := \ · 48 unmodified lines
49 libslang \49 libslang \
50 libcrypto \50 libcrypto \
51 libunwind \51 libunwind \
52 libunwind-x86 \
53 libunwind-x86_64 \
54 libunwind-arm \
55 libunwind-aarch64 \
52 pthread-attr-setaffinity-np \56 pthread-attr-setaffinity-np \
53 stackprotector-all \57 stackprotector-all \
54 timerfd \58 timerfd \
@@ -69,7 +73,9 @@ FEATURE_TESTS_EXTRA := \ · 14 unmodified lines
69 libbabeltrace \73 libbabeltrace \
70 liberty \74 liberty \
71 liberty-z \75 liberty-z \
72 libunwind-debug-frame76 libunwind-debug-frame \
77 libunwind-debug-frame-arm \
78 libunwind-debug-frame-aarch64
73 79
74FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)80FEATURE_TESTS ?= $(FEATURE_TESTS_BASIC)
75 81
tools/build/feature/Makefile+23−0
@@ -27,6 +27,12 @@ FILES= \ · 26 unmodified lines
27 test-libcrypto.bin \27 test-libcrypto.bin \
28 test-libunwind.bin \28 test-libunwind.bin \
29 test-libunwind-debug-frame.bin \29 test-libunwind-debug-frame.bin \
30 test-libunwind-x86.bin \
31 test-libunwind-x86_64.bin \
32 test-libunwind-arm.bin \
33 test-libunwind-aarch64.bin \
34 test-libunwind-debug-frame-arm.bin \
35 test-libunwind-debug-frame-aarch64.bin \
30 test-pthread-attr-setaffinity-np.bin \36 test-pthread-attr-setaffinity-np.bin \
31 test-stackprotector-all.bin \37 test-stackprotector-all.bin \
32 test-timerfd.bin \38 test-timerfd.bin \
@@ -103,6 +109,23 @@ $(OUTPUT)test-libunwind.bin: · 70 unmodified lines
103 109
104$(OUTPUT)test-libunwind-debug-frame.bin:110$(OUTPUT)test-libunwind-debug-frame.bin:
105 $(BUILD) -lelf111 $(BUILD) -lelf
112$(OUTPUT)test-libunwind-x86.bin:
113 $(BUILD) -lelf -lunwind-x86
114
115$(OUTPUT)test-libunwind-x86_64.bin:
116 $(BUILD) -lelf -lunwind-x86_64
117
118$(OUTPUT)test-libunwind-arm.bin:
119 $(BUILD) -lelf -lunwind-arm
120
121$(OUTPUT)test-libunwind-aarch64.bin:
122 $(BUILD) -lelf -lunwind-aarch64
123
124$(OUTPUT)test-libunwind-debug-frame-arm.bin:
125 $(BUILD) -lelf -lunwind-arm
126
127$(OUTPUT)test-libunwind-debug-frame-aarch64.bin:
128 $(BUILD) -lelf -lunwind-aarch64
106 129
107$(OUTPUT)test-libaudit.bin:130$(OUTPUT)test-libaudit.bin:
108 $(BUILD) -laudit131 $(BUILD) -laudit
tools/build/feature/test-bpf.c+1−2
@@ -27,10 +27,9 @@ int main(void) · 26 unmodified lines
27 attr.log_level = 0;27 attr.log_level = 0;
28 attr.kern_version = 0;28 attr.kern_version = 0;
29 29
30 attr = attr;
31 /*30 /*
32 * Test existence of __NR_bpf and BPF_PROG_LOAD.31 * Test existence of __NR_bpf and BPF_PROG_LOAD.
33 * This call should fail if we run the testcase.32 * This call should fail if we run the testcase.
34 */33 */
35 return syscall(__NR_bpf, BPF_PROG_LOAD, attr, sizeof(attr));34 return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
36}35}
tools/build/feature/test-libunwind-aarch64.c+26−0
@@ -0,0 +1,26 @@
1#include <libunwind-aarch64.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
11
12static unw_accessors_t accessors;
13
14int main(void)
15{
16 unw_addr_space_t addr_space;
17
18 addr_space = unw_create_addr_space(&accessors, 0);
19 if (addr_space)
20 return 0;
21
22 unw_init_remote(NULL, addr_space, NULL);
23 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
24
25 return 0;
26}
tools/build/feature/test-libunwind-arm.c+27−0
@@ -0,0 +1,27 @@
1#include <libunwind-arm.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
tools/build/feature/test-libunwind-debug-frame-aarch64.c+16−0
@@ -0,0 +1,16 @@
1#include <libunwind-aarch64.h>
2#include <stdlib.h>
3
4extern int
5UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
6 unw_word_t ip, unw_word_t segbase,
7 const char *obj_name, unw_word_t start,
8 unw_word_t end);
9
10#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
11
12int main(void)
13{
14 dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
15 return 0;
16}
tools/build/feature/test-libunwind-debug-frame-arm.c+16−0
@@ -0,0 +1,16 @@
1#include <libunwind-arm.h>
2#include <stdlib.h>
3
4extern int
5UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
6 unw_word_t ip, unw_word_t segbase,
7 const char *obj_name, unw_word_t start,
8 unw_word_t end);
9
10#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
11
12int main(void)
13{
14 dwarf_find_debug_frame(0, NULL, 0, 0, NULL, 0, 0);
15 return 0;
16}
tools/build/feature/test-libunwind-x86.c+27−0
@@ -0,0 +1,27 @@
1#include <libunwind-x86.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
tools/build/feature/test-libunwind-x86_64.c+27−0
@@ -0,0 +1,27 @@
1#include <libunwind-x86_64.h>
2#include <stdlib.h>
3
4extern int UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
5 unw_word_t ip,
6 unw_dyn_info_t *di,
7 unw_proc_info_t *pi,
8 int need_unwind_info, void *arg);
9
10
11#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
12
13static unw_accessors_t accessors;
14
15int main(void)
16{
17 unw_addr_space_t addr_space;
18
19 addr_space = unw_create_addr_space(&accessors, 0);
20 if (addr_space)
21 return 0;
22
23 unw_init_remote(NULL, addr_space, NULL);
24 dwarf_search_unwind_table(addr_space, 0, NULL, NULL, 0, NULL);
25
26 return 0;
27}
tools/lib/api/fs/fs.c+13−0
@@ -351,6 +351,19 @@ int filename__read_str(const char *filename, char **buf, size_t *sizep) · 350 unmodified lines
351 return err;351 return err;
352}352}
353 353
354int procfs__read_str(const char *entry, char **buf, size_t *sizep)
355{
356 char path[PATH_MAX];
357 const char *procfs = procfs__mountpoint();
358
359 if (!procfs)
360 return -1;
361
362 snprintf(path, sizeof(path), "%s/%s", procfs, entry);
363
364 return filename__read_str(path, buf, sizep);
365}
366
354int sysfs__read_ull(const char *entry, unsigned long long *value)367int sysfs__read_ull(const char *entry, unsigned long long *value)
355{368{
356 char path[PATH_MAX];369 char path[PATH_MAX];
tools/lib/api/fs/fs.h+2−0
@@ -29,6 +29,8 @@ int filename__read_int(const char *filename, int *value); · 28 unmodified lines
29int filename__read_ull(const char *filename, unsigned long long *value);29int filename__read_ull(const char *filename, unsigned long long *value);
30int filename__read_str(const char *filename, char **buf, size_t *sizep);30int filename__read_str(const char *filename, char **buf, size_t *sizep);
31 31
32int procfs__read_str(const char *entry, char **buf, size_t *sizep);
33
32int sysctl__read_int(const char *sysctl, int *value);34int sysctl__read_int(const char *sysctl, int *value);
33int sysfs__read_int(const char *entry, int *value);35int sysfs__read_int(const char *entry, int *value);
34int sysfs__read_ull(const char *entry, unsigned long long *value);36int sysfs__read_ull(const char *entry, unsigned long long *value);
tools/perf/Documentation/intel-pt.txt+7−0
@@ -672,6 +672,7 @@ The letters are: · 671 unmodified lines
672 d create a debug log672 d create a debug log
673 g synthesize a call chain (use with i or x)673 g synthesize a call chain (use with i or x)
674 l synthesize last branch entries (use with i or x)674 l synthesize last branch entries (use with i or x)
675 s skip initial number of events
675 676
676"Instructions" events look like they were recorded by "perf record -e677"Instructions" events look like they were recorded by "perf record -e
677instructions".678instructions".
@@ -730,6 +731,12 @@ from one sample to the next. · 52 unmodified lines
730 731
731To disable trace decoding entirely, use the option --no-itrace.732To disable trace decoding entirely, use the option --no-itrace.
732 733
734It is also possible to skip events generated (instructions, branches, transactions)
735at the beginning. This is useful to ignore initialization code.
736
737 --itrace=i0nss1000000
738
739skips the first million instructions.
733 740
734dump option741dump option
735-----------742-----------
tools/perf/Documentation/itrace.txt+8−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
7 d create a debug log7 d create a debug log
8 g synthesize a call chain (use with i or x)8 g synthesize a call chain (use with i or x)
9 l synthesize last branch entries (use with i or x)9 l synthesize last branch entries (use with i or x)
10 s skip initial number of events
10 11
11 The default is all events i.e. the same as --itrace=ibxe12 The default is all events i.e. the same as --itrace=ibxe
12 13
@@ -24,3 +25,10 @@ · 11 unmodified lines
24 25
25 Also the number of last branch entries (default 64, max. 1024) for26 Also the number of last branch entries (default 64, max. 1024) for
26 instructions or transactions events can be specified.27 instructions or transactions events can be specified.
28
29 It is also possible to skip events generated (instructions, branches, transactions)
30 at the beginning. This is useful to ignore initialization code.
31
32 --itrace=i0nss1000000
33
34 skips the first million instructions.
tools/perf/Documentation/perf-annotate.txt+1−1
@@ -33,7 +33,7 @@ OPTIONS · 32 unmodified lines
33 33
34-f::34-f::
35--force::35--force::
36 Don't complain, do it.36 Don't do ownership validation.
37 37
38-v::38-v::
39--verbose::39--verbose::
tools/perf/Documentation/perf-diff.txt+1−1
@@ -75,7 +75,7 @@ OPTIONS · 74 unmodified lines
75 75
76-f::76-f::
77--force::77--force::
78 Don't complain, do it.78 Don't do ownership validation.
79 79
80--symfs=<directory>::80--symfs=<directory>::
81 Look for files with symbols relative to this directory.81 Look for files with symbols relative to this directory.
tools/perf/Documentation/perf-list.txt+106−1
@@ -93,6 +93,67 @@ raw encoding of 0x1A8 can be used: · 92 unmodified lines
93You should refer to the processor specific documentation for getting these93You should refer to the processor specific documentation for getting these
94details. Some of them are referenced in the SEE ALSO section below.94details. Some of them are referenced in the SEE ALSO section below.
95 95
96ARBITRARY PMUS
97--------------
98
99perf also supports an extended syntax for specifying raw parameters
100to PMUs. Using this typically requires looking up the specific event
101in the CPU vendor specific documentation.
102
103The available PMUs and their raw parameters can be listed with
104
105 ls /sys/devices/*/format
106
107For example the raw event "LSD.UOPS" core pmu event above could
108be specified as
109
110 perf stat -e cpu/event=0xa8,umask=0x1,name=LSD.UOPS_CYCLES,cmask=1/ ...
111
112PER SOCKET PMUS
113---------------
114
115Some PMUs are not associated with a core, but with a whole CPU socket.
116Events on these PMUs generally cannot be sampled, but only counted globally
117with perf stat -a. They can be bound to one logical CPU, but will measure
118all the CPUs in the same socket.
119
120This example measures memory bandwidth every second
121on the first memory controller on socket 0 of a Intel Xeon system
122
123 perf stat -C 0 -a uncore_imc_0/cas_count_read/,uncore_imc_0/cas_count_write/ -I 1000 ...
124
125Each memory controller has its own PMU. Measuring the complete system
126bandwidth would require specifying all imc PMUs (see perf list output),
127and adding the values together.
128
129This example measures the combined core power every second
130
131 perf stat -I 1000 -e power/energy-cores/ -a
132
133ACCESS RESTRICTIONS
134-------------------
135
136For non root users generally only context switched PMU events are available.
137This is normally only the events in the cpu PMU, the predefined events
138like cycles and instructions and some software events.
139
140Other PMUs and global measurements are normally root only.
141Some event qualifiers, such as "any", are also root only.
142
143This can be overriden by setting the kernel.perf_event_paranoid
144sysctl to -1, which allows non root to use these events.
145
146For accessing trace point events perf needs to have read access to
147/sys/kernel/debug/tracing, even when perf_event_paranoid is in a relaxed
148setting.
149
150TRACING
151-------
152
153Some PMUs control advanced hardware tracing capabilities, such as Intel PT,
154that allows low overhead execution tracing. These are described in a separate
155intel-pt.txt document.
156
96PARAMETERIZED EVENTS157PARAMETERIZED EVENTS
97--------------------158--------------------
98 159
@@ -106,6 +167,50 @@ also be supplied. For example: · 7 unmodified lines
106 167
107 perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...168 perf stat -C 0 -e 'hv_gpci/dtbp_ptitc,phys_processor_idx=0x2/' ...
108 169
170EVENT GROUPS
171------------
172
173Perf supports time based multiplexing of events, when the number of events
174active exceeds the number of hardware performance counters. Multiplexing
175can cause measurement errors when the workload changes its execution
176profile.
177
178When metrics are computed using formulas from event counts, it is useful to
179ensure some events are always measured together as a group to minimize multiplexing
180errors. Event groups can be specified using { }.
181
182 perf stat -e '{instructions,cycles}' ...
183
184The number of available performance counters depend on the CPU. A group
185cannot contain more events than available counters.
186For example Intel Core CPUs typically have four generic performance counters
187for the core, plus three fixed counters for instructions, cycles and
188ref-cycles. Some special events have restrictions on which counter they
189can schedule, and may not support multiple instances in a single group.
190When too many events are specified in the group none of them will not
191be measured.
192
193Globally pinned events can limit the number of counters available for
194other groups. On x86 systems, the NMI watchdog pins a counter by default.
195The nmi watchdog can be disabled as root with
196
197 echo 0 > /proc/sys/kernel/nmi_watchdog
198
199Events from multiple different PMUs cannot be mixed in a group, with
200some exceptions for software events.
201
202LEADER SAMPLING
203---------------
204
205perf also supports group leader sampling using the :S specifier.
206
207 perf record -e '{cycles,instructions}:S' ...
208 perf report --group
209
210Normally all events in a event group sample, but with :S only
211the first event (the leader) samples, and it only reads the values of the
212other events in the group.
213
109OPTIONS214OPTIONS
110-------215-------
111 216
@@ -143,5 +248,5 @@ SEE ALSO · 31 unmodified lines
143--------248--------
144linkperf:perf-stat[1], linkperf:perf-top[1],249linkperf:perf-stat[1], linkperf:perf-top[1],
145linkperf:perf-record[1],250linkperf:perf-record[1],
146http://www.intel.com/Assets/PDF/manual/253669.pdf[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],251http://www.intel.com/sdm/[Intel® 64 and IA-32 Architectures Software Developer's Manual Volume 3B: System Programming Guide],
147http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming]252http://support.amd.com/us/Processor_TechDocs/24593_APM_v2.pdf[AMD64 Architecture Programmer’s Manual Volume 2: System Programming]
tools/perf/Documentation/perf-mem.txt+8−0
@@ -48,6 +48,14 @@ OPTIONS · 47 unmodified lines
48 option can be passed in record mode. It will be interpreted the same way as perf48 option can be passed in record mode. It will be interpreted the same way as perf
49 record.49 record.
50 50
51-K::
52--all-kernel::
53 Configure all used events to run in kernel space.
54
55-U::
56--all-user::
57 Configure all used events to run in user space.
58
51SEE ALSO59SEE ALSO
52--------60--------
53linkperf:perf-record[1], linkperf:perf-report[1]61linkperf:perf-record[1], linkperf:perf-report[1]
tools/perf/Documentation/perf-record.txt+13−0
@@ -347,6 +347,19 @@ Configure all used events to run in kernel space. · 346 unmodified lines
347--all-user::347--all-user::
348Configure all used events to run in user space.348Configure all used events to run in user space.
349 349
350--timestamp-filename
351Append timestamp to output file name.
352
353--switch-output::
354Generate multiple perf.data files, timestamp prefixed, switching to a new one
355when receiving a SIGUSR2.
356
357A possible use case is to, given an external event, slice the perf.data file
358that gets then processed, possibly via a perf script, to decide if that
359particular perf.data snapshot should be kept or not.
360
361Implies --timestamp-filename, --no-buildid and --no-buildid-cache.
362
350SEE ALSO363SEE ALSO
351--------364--------
352linkperf:perf-stat[1], linkperf:perf-list[1]365linkperf:perf-stat[1], linkperf:perf-list[1]
tools/perf/Documentation/perf-report.txt+2−2
@@ -248,7 +248,7 @@ OPTIONS · 247 unmodified lines
248 Note that when using the --itrace option the synthesized callchain size248 Note that when using the --itrace option the synthesized callchain size
249 will override this value if the synthesized callchain size is bigger.249 will override this value if the synthesized callchain size is bigger.
250 250
251 Default: 127251 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
252 252
253-G::253-G::
254--inverted::254--inverted::
@@ -285,7 +285,7 @@ OPTIONS · 30 unmodified lines
285 285
286-f::286-f::
287--force::287--force::
288 Don't complain, do it.288 Don't do ownership validation.
289 289
290--symfs=<directory>::290--symfs=<directory>::
291 Look for files with symbols relative to this directory.291 Look for files with symbols relative to this directory.
tools/perf/Documentation/perf-sched.txt+16−0
@@ -50,6 +50,22 @@ OPTIONS · 49 unmodified lines
50--dump-raw-trace=::50--dump-raw-trace=::
51 Display verbose dump of the sched data.51 Display verbose dump of the sched data.
52 52
53OPTIONS for 'perf sched map'
54----------------------------
55
56--compact::
57 Show only CPUs with activity. Helps visualizing on high core
58 count systems.
59
60--cpus::
61 Show just entries with activities for the given CPUs.
62
63--color-cpus::
64 Highlight the given cpus.
65
66--color-pids::
67 Highlight the given pids.
68
53SEE ALSO69SEE ALSO
54--------70--------
55linkperf:perf-record[1]71linkperf:perf-record[1]
tools/perf/Documentation/perf-script.txt+14−0
@@ -259,9 +259,23 @@ include::itrace.txt[] · 258 unmodified lines
259--full-source-path::259--full-source-path::
260 Show the full path for source files for srcline output.260 Show the full path for source files for srcline output.
261 261
262--max-stack::
263 Set the stack depth limit when parsing the callchain, anything
264 beyond the specified depth will be ignored. This is a trade-off
265 between information loss and faster processing especially for
266 workloads that can have a very long callchain stack.
267 Note that when using the --itrace option the synthesized callchain size
268 will override this value if the synthesized callchain size is bigger.
269
270 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
271
262--ns::272--ns::
263 Use 9 decimal places when displaying time (i.e. show the nanoseconds)273 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
264 274
275-f::
276--force::
277 Don't do ownership validation.
278
265SEE ALSO279SEE ALSO
266--------280--------
267linkperf:perf-record[1], linkperf:perf-script-perl[1],281linkperf:perf-record[1], linkperf:perf-script-perl[1],
tools/perf/Documentation/perf-top.txt+1−1
@@ -177,7 +177,7 @@ Default is to monitor all CPUS. · 176 unmodified lines
177 between information loss and faster processing especially for177 between information loss and faster processing especially for
178 workloads that can have a very long callchain stack.178 workloads that can have a very long callchain stack.
179 179
180 Default: 127180 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
181 181
182--ignore-callees=<regex>::182--ignore-callees=<regex>::
183 Ignore callees of the function(s) matching the given regex.183 Ignore callees of the function(s) matching the given regex.
tools/perf/Documentation/perf-trace.txt+32−0
@@ -117,9 +117,41 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs. · 116 unmodified lines
117--syscalls::117--syscalls::
118 Trace system calls. This options is enabled by default.118 Trace system calls. This options is enabled by default.
119 119
120--call-graph [mode,type,min[,limit],order[,key][,branch]]::
121 Setup and enable call-graph (stack chain/backtrace) recording.
122 See `--call-graph` section in perf-record and perf-report
123 man pages for details. The ones that are most useful in 'perf trace'
124 are 'dwarf' and 'lbr', where available, try: 'perf trace --call-graph dwarf'.
125
126 Using this will, for the root user, bump the value of --mmap-pages to 4
127 times the maximum for non-root users, based on the kernel.perf_event_mlock_kb
128 sysctl. This is done only if the user doesn't specify a --mmap-pages value.
129
130--kernel-syscall-graph::
131 Show the kernel callchains on the syscall exit path.
132
120--event::133--event::
121 Trace other events, see 'perf list' for a complete list.134 Trace other events, see 'perf list' for a complete list.
122 135
136--max-stack::
137 Set the stack depth limit when parsing the callchain, anything
138 beyond the specified depth will be ignored. Note that at this point
139 this is just about the presentation part, i.e. the kernel is still
140 not limiting, the overhead of callchains needs to be set via the
141 knobs in --call-graph dwarf.
142
143 Implies '--call-graph dwarf' when --call-graph not present on the
144 command line, on systems where DWARF unwinding was built in.
145
146 Default: /proc/sys/kernel/perf_event_max_stack when present, 127 otherwise.
147
148--min-stack::
149 Set the stack depth limit when parsing the callchain, anything
150 below the specified depth will be ignored. Disabled by default.
151
152 Implies '--call-graph dwarf' when --call-graph not present on the
153 command line, on systems where DWARF unwinding was built in.
154
123--proc-map-timeout::155--proc-map-timeout::
124 When processing pre-existing threads /proc/XXX/mmap, it may take a long time,156 When processing pre-existing threads /proc/XXX/mmap, it may take a long time,
125 because the file may be huge. A time out is needed in such cases.157 because the file may be huge. A time out is needed in such cases.
tools/perf/Makefile.perf+9−6
@@ -183,6 +183,11 @@ endif · 182 unmodified lines
183include config/Makefile183include config/Makefile
184endif184endif
185 185
186ifeq ($(config),0)
187include $(srctree)/tools/scripts/Makefile.arch
188-include arch/$(ARCH)/Makefile
189endif
190
186# The FEATURE_DUMP_EXPORT holds location of the actual191# The FEATURE_DUMP_EXPORT holds location of the actual
187# FEATURE_DUMP file to be used to bypass feature detection192# FEATURE_DUMP file to be used to bypass feature detection
188# (for bpf or any other subproject)193# (for bpf or any other subproject)
@@ -297,8 +302,6 @@ endif · 108 unmodified lines
297# because maintaining the nesting to match is a pain. If302# because maintaining the nesting to match is a pain. If
298# we had "elif" things would have been much nicer...303# we had "elif" things would have been much nicer...
299 304
300-include arch/$(ARCH)/Makefile
301
302ifneq ($(OUTPUT),)305ifneq ($(OUTPUT),)
303 CFLAGS += -I$(OUTPUT)306 CFLAGS += -I$(OUTPUT)
304endif307endif
@@ -390,7 +393,7 @@ endif · 85 unmodified lines
390__build-dir = $(subst $(OUTPUT),,$(dir $@))393__build-dir = $(subst $(OUTPUT),,$(dir $@))
391build-dir = $(if $(__build-dir),$(__build-dir),.)394build-dir = $(if $(__build-dir),$(__build-dir),.)
392 395
393prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep396prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep archheaders
394 397
395$(OUTPUT)%.o: %.c prepare FORCE398$(OUTPUT)%.o: %.c prepare FORCE
396 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@399 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -430,7 +433,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h) · 33 unmodified lines
430 433
431LIBPERF_IN := $(OUTPUT)libperf-in.o434LIBPERF_IN := $(OUTPUT)libperf-in.o
432 435
433$(LIBPERF_IN): fixdep FORCE436$(LIBPERF_IN): prepare fixdep FORCE
434 $(Q)$(MAKE) $(build)=libperf437 $(Q)$(MAKE) $(build)=libperf
435 438
436$(LIB_FILE): $(LIBPERF_IN)439$(LIB_FILE): $(LIBPERF_IN)
@@ -625,7 +628,7 @@ config-clean: · 188 unmodified lines
625 $(call QUIET_CLEAN, config)628 $(call QUIET_CLEAN, config)
626 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null629 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
627 630
628clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean631clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean
629 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)632 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
630 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete633 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
631 $(Q)$(RM) $(OUTPUT).config-detected634 $(Q)$(RM) $(OUTPUT).config-detected
@@ -662,5 +665,5 @@ FORCE: · 30 unmodified lines
662.PHONY: all install clean config-clean strip install-gtk665.PHONY: all install clean config-clean strip install-gtk
663.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell666.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
664.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare667.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
665.PHONY: libtraceevent_plugins668.PHONY: libtraceevent_plugins archheaders
666 669
tools/perf/arch/powerpc/Makefile+1−0
@@ -3,4 +3,5 @@ PERF_HAVE_DWARF_REGS := 1 · 2 unmodified lines
3endif3endif
4 4
5HAVE_KVM_STAT_SUPPORT := 15HAVE_KVM_STAT_SUPPORT := 1
6PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
6PERF_HAVE_JITDUMP := 17PERF_HAVE_JITDUMP := 1
tools/perf/arch/powerpc/util/dwarf-regs.c+28−12
@@ -10,19 +10,26 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <stddef.h>12#include <stddef.h>
13#include <errno.h>
14#include <string.h>
13#include <dwarf-regs.h>15#include <dwarf-regs.h>
14 16#include <linux/ptrace.h>
17#include <linux/kernel.h>
18#include "util.h"
15 19
16struct pt_regs_dwarfnum {20struct pt_regs_dwarfnum {
17 const char *name;21 const char *name;
18 unsigned int dwarfnum;22 unsigned int dwarfnum;
23 unsigned int ptregs_offset;
19};24};
20 25
21#define STR(s) #s26#define REG_DWARFNUM_NAME(r, num) \
22#define REG_DWARFNUM_NAME(r, num) {.name = r, .dwarfnum = num}27 {.name = STR(%)STR(r), .dwarfnum = num, \
23#define GPR_DWARFNUM_NAME(num) \28 .ptregs_offset = offsetof(struct pt_regs, r)}
24 {.name = STR(%gpr##num), .dwarfnum = num}29#define GPR_DWARFNUM_NAME(num) \
25#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0}30 {.name = STR(%gpr##num), .dwarfnum = num, \
31 .ptregs_offset = offsetof(struct pt_regs, gpr[num])}
32#define REG_DWARFNUM_END {.name = NULL, .dwarfnum = 0, .ptregs_offset = 0}
26 33
27/*34/*
28 * Reference:35 * Reference:
@@ -61,12 +68,12 @@ static const struct pt_regs_dwarfnum regdwarfnum_table[] = { · 32 unmodified lines
61 GPR_DWARFNUM_NAME(29),68 GPR_DWARFNUM_NAME(29),
62 GPR_DWARFNUM_NAME(30),69 GPR_DWARFNUM_NAME(30),
63 GPR_DWARFNUM_NAME(31),70 GPR_DWARFNUM_NAME(31),
64 REG_DWARFNUM_NAME("%msr", 66),71 REG_DWARFNUM_NAME(msr, 66),
65 REG_DWARFNUM_NAME("%ctr", 109),72 REG_DWARFNUM_NAME(ctr, 109),
66 REG_DWARFNUM_NAME("%link", 108),73 REG_DWARFNUM_NAME(link, 108),
67 REG_DWARFNUM_NAME("%xer", 101),74 REG_DWARFNUM_NAME(xer, 101),
68 REG_DWARFNUM_NAME("%dar", 119),75 REG_DWARFNUM_NAME(dar, 119),
69 REG_DWARFNUM_NAME("%dsisr", 118),76 REG_DWARFNUM_NAME(dsisr, 118),
70 REG_DWARFNUM_END,77 REG_DWARFNUM_END,
71};78};
72 79
@@ -86,3 +93,12 @@ const char *get_arch_regstr(unsigned int n) · 13 unmodified lines
86 return roff->name;93 return roff->name;
87 return NULL;94 return NULL;
88}95}
96
97int regs_query_register_offset(const char *name)
98{
99 const struct pt_regs_dwarfnum *roff;
100 for (roff = regdwarfnum_table; roff->name != NULL; roff++)
101 if (!strcmp(roff->name, name))
102 return roff->ptregs_offset;
103 return -EINVAL;
104}
tools/perf/arch/powerpc/util/sym-handling.c+32−11
@@ -19,12 +19,6 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr) · 18 unmodified lines
19 ehdr.e_type == ET_DYN;19 ehdr.e_type == ET_DYN;
20}20}
21 21
22#if defined(_CALL_ELF) && _CALL_ELF == 2
23void arch__elf_sym_adjust(GElf_Sym *sym)
24{
25 sym->st_value += PPC64_LOCAL_ENTRY_OFFSET(sym->st_other);
26}
27#endif
28#endif22#endif
29 23
30#if !defined(_CALL_ELF) || _CALL_ELF != 224#if !defined(_CALL_ELF) || _CALL_ELF != 2
@@ -65,18 +59,45 @@ bool arch__prefers_symtab(void) · 34 unmodified lines
65 return true;59 return true;
66}60}
67 61
62#ifdef HAVE_LIBELF_SUPPORT
63void arch__sym_update(struct symbol *s, GElf_Sym *sym)
64{
65 s->arch_sym = sym->st_other;
66}
67#endif
68
68#define PPC64LE_LEP_OFFSET 869#define PPC64LE_LEP_OFFSET 8
69 70
70void arch__fix_tev_from_maps(struct perf_probe_event *pev,71void arch__fix_tev_from_maps(struct perf_probe_event *pev,
71 struct probe_trace_event *tev, struct map *map)72 struct probe_trace_event *tev, struct map *map,
73 struct symbol *sym)
72{74{
75 int lep_offset;
76
73 /*77 /*
74 * ppc64 ABIv2 local entry point is currently always 2 instructions78 * When probing at a function entry point, we normally always want the
75 * (8 bytes) after the global entry point.79 * LEP since that catches calls to the function through both the GEP and
80 * the LEP. Hence, we would like to probe at an offset of 8 bytes if
81 * the user only specified the function entry.
82 *
83 * However, if the user specifies an offset, we fall back to using the
84 * GEP since all userspace applications (objdump/readelf) show function
85 * disassembly with offsets from the GEP.
86 *
87 * In addition, we shouldn't specify an offset for kretprobes.
76 */88 */
77 if (!pev->uprobes && map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {89 if (pev->point.offset || pev->point.retprobe || !map || !sym)
78 tev->point.address += PPC64LE_LEP_OFFSET;90 return;
91
92 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym);
93
94 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS)
79 tev->point.offset += PPC64LE_LEP_OFFSET;95 tev->point.offset += PPC64LE_LEP_OFFSET;
96 else if (lep_offset) {
97 if (pev->uprobes)
98 tev->point.address += lep_offset;
99 else
100 tev->point.offset += lep_offset;
80 }101 }
81}102}
82#endif103#endif
tools/perf/arch/x86/Makefile+23−0
@@ -4,3 +4,26 @@ endif · 3 unmodified lines
4HAVE_KVM_STAT_SUPPORT := 14HAVE_KVM_STAT_SUPPORT := 1
5PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 15PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
6PERF_HAVE_JITDUMP := 16PERF_HAVE_JITDUMP := 1
7
8###
9# Syscall table generation
10#
11
12out := $(OUTPUT)arch/x86/include/generated/asm
13header := $(out)/syscalls_64.c
14sys := $(srctree)/tools/perf/arch/x86/entry/syscalls
15systbl := $(sys)/syscalltbl.sh
16
17# Create output directory if not already present
18_dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
19
20$(header): $(sys)/syscall_64.tbl $(systbl)
21 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
22 (diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
23 || echo "Warning: x86_64's syscall_64.tbl differs from kernel" >&2 )) || true
24 $(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
25
26clean::
27 $(call QUIET_CLEAN, x86) $(RM) $(header)
28
29archheaders: $(header)
tools/perf/arch/x86/entry/syscalls/syscall_64.tbl+376−0
@@ -0,0 +1,376 @@
1#
2# 64-bit system call numbers and entry vectors
3#
4# The format is:
5# <number> <abi> <name> <entry point>
6#
7# The abi is "common", "64" or "x32" for this file.
8#
90 common read sys_read
101 common write sys_write
112 common open sys_open
123 common close sys_close
134 common stat sys_newstat
145 common fstat sys_newfstat
156 common lstat sys_newlstat
167 common poll sys_poll
178 common lseek sys_lseek
189 common mmap sys_mmap
1910 common mprotect sys_mprotect
2011 common munmap sys_munmap
2112 common brk sys_brk
2213 64 rt_sigaction sys_rt_sigaction
2314 common rt_sigprocmask sys_rt_sigprocmask
2415 64 rt_sigreturn sys_rt_sigreturn/ptregs
2516 64 ioctl sys_ioctl
2617 common pread64 sys_pread64
2718 common pwrite64 sys_pwrite64
2819 64 readv sys_readv
2920 64 writev sys_writev
3021 common access sys_access
3122 common pipe sys_pipe
3223 common select sys_select
3324 common sched_yield sys_sched_yield
3425 common mremap sys_mremap
3526 common msync sys_msync
3627 common mincore sys_mincore
3728 common madvise sys_madvise
3829 common shmget sys_shmget
3930 common shmat sys_shmat
4031 common shmctl sys_shmctl
4132 common dup sys_dup
4233 common dup2 sys_dup2
4334 common pause sys_pause
4435 common nanosleep sys_nanosleep
4536 common getitimer sys_getitimer
4637 common alarm sys_alarm
4738 common setitimer sys_setitimer
4839 common getpid sys_getpid
4940 common sendfile sys_sendfile64
5041 common socket sys_socket
5142 common connect sys_connect
5243 common accept sys_accept
5344 common sendto sys_sendto
5445 64 recvfrom sys_recvfrom
5546 64 sendmsg sys_sendmsg
5647 64 recvmsg sys_recvmsg
5748 common shutdown sys_shutdown
5849 common bind sys_bind
5950 common listen sys_listen
6051 common getsockname sys_getsockname
6152 common getpeername sys_getpeername
6253 common socketpair sys_socketpair
6354 64 setsockopt sys_setsockopt
6455 64 getsockopt sys_getsockopt
6556 common clone sys_clone/ptregs
6657 common fork sys_fork/ptregs
6758 common vfork sys_vfork/ptregs
6859 64 execve sys_execve/ptregs
6960 common exit sys_exit
7061 common wait4 sys_wait4
7162 common kill sys_kill
7263 common uname sys_newuname
7364 common semget sys_semget
7465 common semop sys_semop
7566 common semctl sys_semctl
7667 common shmdt sys_shmdt
7768 common msgget sys_msgget
7869 common msgsnd sys_msgsnd
7970 common msgrcv sys_msgrcv
8071 common msgctl sys_msgctl
8172 common fcntl sys_fcntl
8273 common flock sys_flock
8374 common fsync sys_fsync
8475 common fdatasync sys_fdatasync
8576 common truncate sys_truncate
8677 common ftruncate sys_ftruncate
8778 common getdents sys_getdents
8879 common getcwd sys_getcwd
8980 common chdir sys_chdir
9081 common fchdir sys_fchdir
9182 common rename sys_rename
9283 common mkdir sys_mkdir
9384 common rmdir sys_rmdir
9485 common creat sys_creat
9586 common link sys_link
9687 common unlink sys_unlink
9788 common symlink sys_symlink
9889 common readlink sys_readlink
9990 common chmod sys_chmod
10091 common fchmod sys_fchmod
10192 common chown sys_chown
10293 common fchown sys_fchown
10394 common lchown sys_lchown
10495 common umask sys_umask
10596 common gettimeofday sys_gettimeofday
10697 common getrlimit sys_getrlimit
10798 common getrusage sys_getrusage
10899 common sysinfo sys_sysinfo
109100 common times sys_times
110101 64 ptrace sys_ptrace
111102 common getuid sys_getuid
112103 common syslog sys_syslog
113104 common getgid sys_getgid
114105 common setuid sys_setuid
115106 common setgid sys_setgid
116107 common geteuid sys_geteuid
117108 common getegid sys_getegid
118109 common setpgid sys_setpgid
119110 common getppid sys_getppid
120111 common getpgrp sys_getpgrp
121112 common setsid sys_setsid
122113 common setreuid sys_setreuid
123114 common setregid sys_setregid
124115 common getgroups sys_getgroups
125116 common setgroups sys_setgroups
126117 common setresuid sys_setresuid
127118 common getresuid sys_getresuid
128119 common setresgid sys_setresgid
129120 common getresgid sys_getresgid
130121 common getpgid sys_getpgid
131122 common setfsuid sys_setfsuid
132123 common setfsgid sys_setfsgid
133124 common getsid sys_getsid
134125 common capget sys_capget
135126 common capset sys_capset
136127 64 rt_sigpending sys_rt_sigpending
137128 64 rt_sigtimedwait sys_rt_sigtimedwait
138129 64 rt_sigqueueinfo sys_rt_sigqueueinfo
139130 common rt_sigsuspend sys_rt_sigsuspend
140131 64 sigaltstack sys_sigaltstack
141132 common utime sys_utime
142133 common mknod sys_mknod
143134 64 uselib
144135 common personality sys_personality
145136 common ustat sys_ustat
146137 common statfs sys_statfs
147138 common fstatfs sys_fstatfs
148139 common sysfs sys_sysfs
149140 common getpriority sys_getpriority
150141 common setpriority sys_setpriority
151142 common sched_setparam sys_sched_setparam
152143 common sched_getparam sys_sched_getparam
153144 common sched_setscheduler sys_sched_setscheduler
154145 common sched_getscheduler sys_sched_getscheduler
155146 common sched_get_priority_max sys_sched_get_priority_max
156147 common sched_get_priority_min sys_sched_get_priority_min
157148 common sched_rr_get_interval sys_sched_rr_get_interval
158149 common mlock sys_mlock
159150 common munlock sys_munlock
160151 common mlockall sys_mlockall
161152 common munlockall sys_munlockall
162153 common vhangup sys_vhangup
163154 common modify_ldt sys_modify_ldt
164155 common pivot_root sys_pivot_root
165156 64 _sysctl sys_sysctl
166157 common prctl sys_prctl
167158 common arch_prctl sys_arch_prctl
168159 common adjtimex sys_adjtimex
169160 common setrlimit sys_setrlimit
170161 common chroot sys_chroot
171162 common sync sys_sync
172163 common acct sys_acct
173164 common settimeofday sys_settimeofday
174165 common mount sys_mount
175166 common umount2 sys_umount
176167 common swapon sys_swapon
177168 common swapoff sys_swapoff
178169 common reboot sys_reboot
179170 common sethostname sys_sethostname
180171 common setdomainname sys_setdomainname
181172 common iopl sys_iopl/ptregs
182173 common ioperm sys_ioperm
183174 64 create_module
184175 common init_module sys_init_module
185176 common delete_module sys_delete_module
186177 64 get_kernel_syms
187178 64 query_module
188179 common quotactl sys_quotactl
189180 64 nfsservctl
190181 common getpmsg
191182 common putpmsg
192183 common afs_syscall
193184 common tuxcall
194185 common security
195186 common gettid sys_gettid
196187 common readahead sys_readahead
197188 common setxattr sys_setxattr
198189 common lsetxattr sys_lsetxattr
199190 common fsetxattr sys_fsetxattr
200191 common getxattr sys_getxattr
201192 common lgetxattr sys_lgetxattr
202193 common fgetxattr sys_fgetxattr
203194 common listxattr sys_listxattr
204195 common llistxattr sys_llistxattr
205196 common flistxattr sys_flistxattr
206197 common removexattr sys_removexattr
207198 common lremovexattr sys_lremovexattr
208199 common fremovexattr sys_fremovexattr
209200 common tkill sys_tkill
210201 common time sys_time
211202 common futex sys_futex
212203 common sched_setaffinity sys_sched_setaffinity
213204 common sched_getaffinity sys_sched_getaffinity
214205 64 set_thread_area
215206 64 io_setup sys_io_setup
216207 common io_destroy sys_io_destroy
217208 common io_getevents sys_io_getevents
218209 64 io_submit sys_io_submit
219210 common io_cancel sys_io_cancel
220211 64 get_thread_area
221212 common lookup_dcookie sys_lookup_dcookie
222213 common epoll_create sys_epoll_create
223214 64 epoll_ctl_old
224215 64 epoll_wait_old
225216 common remap_file_pages sys_remap_file_pages
226217 common getdents64 sys_getdents64
227218 common set_tid_address sys_set_tid_address
228219 common restart_syscall sys_restart_syscall
229220 common semtimedop sys_semtimedop
230221 common fadvise64 sys_fadvise64
231222 64 timer_create sys_timer_create
232223 common timer_settime sys_timer_settime
233224 common timer_gettime sys_timer_gettime
234225 common timer_getoverrun sys_timer_getoverrun
235226 common timer_delete sys_timer_delete
236227 common clock_settime sys_clock_settime
237228 common clock_gettime sys_clock_gettime
238229 common clock_getres sys_clock_getres
239230 common clock_nanosleep sys_clock_nanosleep
240231 common exit_group sys_exit_group
241232 common epoll_wait sys_epoll_wait
242233 common epoll_ctl sys_epoll_ctl
243234 common tgkill sys_tgkill
244235 common utimes sys_utimes
245236 64 vserver
246237 common mbind sys_mbind
247238 common set_mempolicy sys_set_mempolicy
248239 common get_mempolicy sys_get_mempolicy
249240 common mq_open sys_mq_open
250241 common mq_unlink sys_mq_unlink
251242 common mq_timedsend sys_mq_timedsend
252243 common mq_timedreceive sys_mq_timedreceive
253244 64 mq_notify sys_mq_notify
254245 common mq_getsetattr sys_mq_getsetattr
255246 64 kexec_load sys_kexec_load
256247 64 waitid sys_waitid
257248 common add_key sys_add_key
258249 common request_key sys_request_key
259250 common keyctl sys_keyctl
260251 common ioprio_set sys_ioprio_set
261252 common ioprio_get sys_ioprio_get
262253 common inotify_init sys_inotify_init
263254 common inotify_add_watch sys_inotify_add_watch
264255 common inotify_rm_watch sys_inotify_rm_watch
265256 common migrate_pages sys_migrate_pages
266257 common openat sys_openat
267258 common mkdirat sys_mkdirat
268259 common mknodat sys_mknodat
269260 common fchownat sys_fchownat
270261 common futimesat sys_futimesat
271262 common newfstatat sys_newfstatat
272263 common unlinkat sys_unlinkat
273264 common renameat sys_renameat
274265 common linkat sys_linkat
275266 common symlinkat sys_symlinkat
276267 common readlinkat sys_readlinkat
277268 common fchmodat sys_fchmodat
278269 common faccessat sys_faccessat
279270 common pselect6 sys_pselect6
280271 common ppoll sys_ppoll
281272 common unshare sys_unshare
282273 64 set_robust_list sys_set_robust_list
283274 64 get_robust_list sys_get_robust_list
284275 common splice sys_splice
285276 common tee sys_tee
286277 common sync_file_range sys_sync_file_range
287278 64 vmsplice sys_vmsplice
288279 64 move_pages sys_move_pages
289280 common utimensat sys_utimensat
290281 common epoll_pwait sys_epoll_pwait
291282 common signalfd sys_signalfd
292283 common timerfd_create sys_timerfd_create
293284 common eventfd sys_eventfd
294285 common fallocate sys_fallocate
295286 common timerfd_settime sys_timerfd_settime
296287 common timerfd_gettime sys_timerfd_gettime
297288 common accept4 sys_accept4
298289 common signalfd4 sys_signalfd4
299290 common eventfd2 sys_eventfd2
300291 common epoll_create1 sys_epoll_create1
301292 common dup3 sys_dup3
302293 common pipe2 sys_pipe2
303294 common inotify_init1 sys_inotify_init1
304295 64 preadv sys_preadv
305296 64 pwritev sys_pwritev
306297 64 rt_tgsigqueueinfo sys_rt_tgsigqueueinfo
307298 common perf_event_open sys_perf_event_open
308299 64 recvmmsg sys_recvmmsg
309300 common fanotify_init sys_fanotify_init
310301 common fanotify_mark sys_fanotify_mark
311302 common prlimit64 sys_prlimit64
312303 common name_to_handle_at sys_name_to_handle_at
313304 common open_by_handle_at sys_open_by_handle_at
314305 common clock_adjtime sys_clock_adjtime
315306 common syncfs sys_syncfs
316307 64 sendmmsg sys_sendmmsg
317308 common setns sys_setns
318309 common getcpu sys_getcpu
319310 64 process_vm_readv sys_process_vm_readv
320311 64 process_vm_writev sys_process_vm_writev
321312 common kcmp sys_kcmp
322313 common finit_module sys_finit_module
323314 common sched_setattr sys_sched_setattr
324315 common sched_getattr sys_sched_getattr
325316 common renameat2 sys_renameat2
326317 common seccomp sys_seccomp
327318 common getrandom sys_getrandom
328319 common memfd_create sys_memfd_create
329320 common kexec_file_load sys_kexec_file_load
330321 common bpf sys_bpf
331322 64 execveat sys_execveat/ptregs
332323 common userfaultfd sys_userfaultfd
333324 common membarrier sys_membarrier
334325 common mlock2 sys_mlock2
335326 common copy_file_range sys_copy_file_range
336327 64 preadv2 sys_preadv2
337328 64 pwritev2 sys_pwritev2
338
339#
340# x32-specific system call numbers start at 512 to avoid cache impact
341# for native 64-bit operation.
342#
343512 x32 rt_sigaction compat_sys_rt_sigaction
344513 x32 rt_sigreturn sys32_x32_rt_sigreturn
345514 x32 ioctl compat_sys_ioctl
346515 x32 readv compat_sys_readv
347516 x32 writev compat_sys_writev
348517 x32 recvfrom compat_sys_recvfrom
349518 x32 sendmsg compat_sys_sendmsg
350519 x32 recvmsg compat_sys_recvmsg
351520 x32 execve compat_sys_execve/ptregs
352521 x32 ptrace compat_sys_ptrace
353522 x32 rt_sigpending compat_sys_rt_sigpending
354523 x32 rt_sigtimedwait compat_sys_rt_sigtimedwait
355524 x32 rt_sigqueueinfo compat_sys_rt_sigqueueinfo
356525 x32 sigaltstack compat_sys_sigaltstack
357526 x32 timer_create compat_sys_timer_create
358527 x32 mq_notify compat_sys_mq_notify
359528 x32 kexec_load compat_sys_kexec_load
360529 x32 waitid compat_sys_waitid
361530 x32 set_robust_list compat_sys_set_robust_list
362531 x32 get_robust_list compat_sys_get_robust_list
363532 x32 vmsplice compat_sys_vmsplice
364533 x32 move_pages compat_sys_move_pages
365534 x32 preadv compat_sys_preadv64
366535 x32 pwritev compat_sys_pwritev64
367536 x32 rt_tgsigqueueinfo compat_sys_rt_tgsigqueueinfo
368537 x32 recvmmsg compat_sys_recvmmsg
369538 x32 sendmmsg compat_sys_sendmmsg
370539 x32 process_vm_readv compat_sys_process_vm_readv
371540 x32 process_vm_writev compat_sys_process_vm_writev
372541 x32 setsockopt compat_sys_setsockopt
373542 x32 getsockopt compat_sys_getsockopt
374543 x32 io_setup compat_sys_io_setup
375544 x32 io_submit compat_sys_io_submit
376545 x32 execveat compat_sys_execveat/ptregs
tools/perf/arch/x86/entry/syscalls/syscalltbl.sh+39−0
@@ -0,0 +1,39 @@
1#!/bin/sh
2
3in="$1"
4arch="$2"
5
6syscall_macro() {
7 nr="$1"
8 name="$2"
9
10 echo " [$nr] = \"$name\","
11}
12
13emit() {
14 nr="$1"
15 entry="$2"
16
17 syscall_macro "$nr" "$entry"
18}
19
20echo "static const char *syscalltbl_${arch}[] = {"
21
22sorted_table=$(mktemp /tmp/syscalltbl.XXXXXX)
23grep '^[0-9]' "$in" | sort -n > $sorted_table
24
25max_nr=0
26while read nr abi name entry compat; do
27 if [ $nr -ge 512 ] ; then # discard compat sycalls
28 break
29 fi
30
31 emit "$nr" "$name"
32 max_nr=$nr
33done < $sorted_table
34
35rm -f $sorted_table
36
37echo "};"
38
39echo "#define SYSCALLTBL_${arch}_MAX_ID ${max_nr}"
tools/perf/arch/x86/tests/perf-time-to-tsc.c+1−1
@@ -71,7 +71,7 @@ int test__perf_time_to_tsc(int subtest __maybe_unused) · 70 unmodified lines
71 71
72 CHECK__(parse_events(evlist, "cycles:u", NULL));72 CHECK__(parse_events(evlist, "cycles:u", NULL));
73 73
74 perf_evlist__config(evlist, &opts);74 perf_evlist__config(evlist, &opts, NULL);
75 75
76 evsel = perf_evlist__first(evlist);76 evsel = perf_evlist__first(evlist);
77 77
tools/perf/arch/x86/util/intel-bts.c+5−0
@@ -438,6 +438,11 @@ struct auxtrace_record *intel_bts_recording_init(int *err) · 437 unmodified lines
438 if (!intel_bts_pmu)438 if (!intel_bts_pmu)
439 return NULL;439 return NULL;
440 440
441 if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) {
442 *err = -errno;
443 return NULL;
444 }
445
441 btsr = zalloc(sizeof(struct intel_bts_recording));446 btsr = zalloc(sizeof(struct intel_bts_recording));
442 if (!btsr) {447 if (!btsr) {
443 *err = -ENOMEM;448 *err = -ENOMEM;
tools/perf/arch/x86/util/intel-pt.c+5−0
@@ -1027,6 +1027,11 @@ struct auxtrace_record *intel_pt_recording_init(int *err) · 1026 unmodified lines
1027 if (!intel_pt_pmu)1027 if (!intel_pt_pmu)
1028 return NULL;1028 return NULL;
1029 1029
1030 if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) {
1031 *err = -errno;
1032 return NULL;
1033 }
1034
1030 ptr = zalloc(sizeof(struct intel_pt_recording));1035 ptr = zalloc(sizeof(struct intel_pt_recording));
1031 if (!ptr) {1036 if (!ptr) {
1032 *err = -ENOMEM;1037 *err = -ENOMEM;
tools/perf/arch/x86/util/tsc.c+31−1
@@ -7,7 +7,6 @@ · 6 unmodified lines
7#include <linux/types.h>7#include <linux/types.h>
8#include "../../util/debug.h"8#include "../../util/debug.h"
9#include "../../util/tsc.h"9#include "../../util/tsc.h"
10#include "tsc.h"
11 10
12int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,11int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
13 struct perf_tsc_conversion *tc)12 struct perf_tsc_conversion *tc)
@@ -46,3 +45,34 @@ u64 rdtsc(void) · 32 unmodified lines
46 45
47 return low | ((u64)high) << 32;46 return low | ((u64)high) << 32;
48}47}
48
49int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc,
50 struct perf_tool *tool,
51 perf_event__handler_t process,
52 struct machine *machine)
53{
54 union perf_event event = {
55 .time_conv = {
56 .header = {
57 .type = PERF_RECORD_TIME_CONV,
58 .size = sizeof(struct time_conv_event),
59 },
60 },
61 };
62 struct perf_tsc_conversion tc;
63 int err;
64
65 err = perf_read_tsc_conversion(pc, &tc);
66 if (err == -EOPNOTSUPP)
67 return 0;
68 if (err)
69 return err;
70
71 pr_debug2("Synthesizing TSC conversion information\n");
72
73 event.time_conv.time_mult = tc.time_mult;
74 event.time_conv.time_shift = tc.time_shift;
75 event.time_conv.time_zero = tc.time_zero;
76
77 return process(tool, &event, NULL, machine);
78}
tools/perf/arch/x86/util/tsc.h+0−17
@@ -1,17 +0,0 @@
1#ifndef TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
2#define TOOLS_PERF_ARCH_X86_UTIL_TSC_H__
3
4#include <linux/types.h>
5
6struct perf_tsc_conversion {
7 u16 time_shift;
8 u32 time_mult;
9 u64 time_zero;
10};
11
12struct perf_event_mmap_page;
13
14int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
15 struct perf_tsc_conversion *tc);
16
17#endif /* TOOLS_PERF_ARCH_X86_UTIL_TSC_H__ */
tools/perf/bench/futex-lock-pi.c+1−1
@@ -83,7 +83,7 @@ static void *workerfn(void *arg) · 82 unmodified lines
83 do {83 do {
84 int ret;84 int ret;
85 again:85 again:
86 ret = futex_lock_pi(w->futex, NULL, 0, futex_flag);86 ret = futex_lock_pi(w->futex, NULL, futex_flag);
87 87
88 if (ret) { /* handle lock acquisition */88 if (ret) { /* handle lock acquisition */
89 if (!silent)89 if (!silent)
tools/perf/bench/futex.h+2−4
@@ -57,13 +57,11 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags) · 56 unmodified lines
57 57
58/**58/**
59 * futex_lock_pi() - block on uaddr as a PI mutex59 * futex_lock_pi() - block on uaddr as a PI mutex
60 * @detect: whether (1) or not (0) to perform deadlock detection
61 */60 */
62static inline int61static inline int
63futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int detect,62futex_lock_pi(u_int32_t *uaddr, struct timespec *timeout, int opflags)
64 int opflags)
65{63{
66 return futex(uaddr, FUTEX_LOCK_PI, detect, timeout, NULL, 0, opflags);64 return futex(uaddr, FUTEX_LOCK_PI, 0, timeout, NULL, 0, opflags);
67}65}
68 66
69/**67/**
tools/perf/bench/mem-functions.c+15−7
@@ -6,6 +6,7 @@ · 5 unmodified lines
6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>6 * Written by Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
7 */7 */
8 8
9#include "debug.h"
9#include "../perf.h"10#include "../perf.h"
10#include "../util/util.h"11#include "../util/util.h"
11#include <subcmd/parse-options.h>12#include <subcmd/parse-options.h>
@@ -63,14 +64,16 @@ static struct perf_event_attr cycle_attr = { · 51 unmodified lines
63 .config = PERF_COUNT_HW_CPU_CYCLES64 .config = PERF_COUNT_HW_CPU_CYCLES
64};65};
65 66
66static void init_cycles(void)67static int init_cycles(void)
67{68{
68 cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag());69 cycles_fd = sys_perf_event_open(&cycle_attr, getpid(), -1, -1, perf_event_open_cloexec_flag());
69 70
70 if (cycles_fd < 0 && errno == ENOSYS)71 if (cycles_fd < 0 && errno == ENOSYS) {
71 die("No CONFIG_PERF_EVENTS=y kernel support configured?\n");72 pr_debug("No CONFIG_PERF_EVENTS=y kernel support configured?\n");
72 else73 return -1;
73 BUG_ON(cycles_fd < 0);74 }
75
76 return cycles_fd;
74}77}
75 78
76static u64 get_cycles(void)79static u64 get_cycles(void)
@@ -155,8 +158,13 @@ static int bench_mem_common(int argc, const char **argv, struct bench_mem_info * · 78 unmodified lines
155 158
156 argc = parse_options(argc, argv, options, info->usage, 0);159 argc = parse_options(argc, argv, options, info->usage, 0);
157 160
158 if (use_cycles)161 if (use_cycles) {
159 init_cycles();162 i = init_cycles();
163 if (i < 0) {
164 fprintf(stderr, "Failed to open cycles counter\n");
165 return i;
166 }
167 }
160 168
161 size = (size_t)perf_atoll((char *)size_str);169 size = (size_t)perf_atoll((char *)size_str);
162 size_total = (double)size * nr_loops;170 size_total = (double)size * nr_loops;
tools/perf/builtin-config.c+32−7
@@ -12,6 +12,7 @@ · 11 unmodified lines
12#include <subcmd/parse-options.h>12#include <subcmd/parse-options.h>
13#include "util/util.h"13#include "util/util.h"
14#include "util/debug.h"14#include "util/debug.h"
15#include "util/config.h"
15 16
16static bool use_system_config, use_user_config;17static bool use_system_config, use_user_config;
17 18
@@ -32,13 +33,28 @@ static struct option config_options[] = { · 14 unmodified lines
32 OPT_END()33 OPT_END()
33};34};
34 35
35static int show_config(const char *key, const char *value,36static int show_config(struct perf_config_set *set)
36 void *cb __maybe_unused)
37{37{
38 if (value)38 struct perf_config_section *section;
39 printf("%s=%s\n", key, value);39 struct perf_config_item *item;
40 else40 struct list_head *sections;
41 printf("%s\n", key);41
42 if (set == NULL)
43 return -1;
44
45 sections = &set->sections;
46 if (list_empty(sections))
47 return -1;
48
49 list_for_each_entry(section, sections, node) {
50 list_for_each_entry(item, &section->items, node) {
51 char *value = item->value;
52
53 if (value)
54 printf("%s.%s=%s\n", section->name,
55 item->name, value);
56 }
57 }
42 58
43 return 0;59 return 0;
44}60}
@@ -46,6 +62,7 @@ static int show_config(const char *key, const char *value, · 1 unmodified line
46int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)62int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
47{63{
48 int ret = 0;64 int ret = 0;
65 struct perf_config_set *set;
49 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));66 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
50 67
51 argc = parse_options(argc, argv, config_options, config_usage,68 argc = parse_options(argc, argv, config_options, config_usage,
@@ -63,13 +80,19 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) · 11 unmodified lines
63 else if (use_user_config)80 else if (use_user_config)
64 config_exclusive_filename = user_config;81 config_exclusive_filename = user_config;
65 82
83 set = perf_config_set__new();
84 if (!set) {
85 ret = -1;
86 goto out_err;
87 }
88
66 switch (actions) {89 switch (actions) {
67 case ACTION_LIST:90 case ACTION_LIST:
68 if (argc) {91 if (argc) {
69 pr_err("Error: takes no arguments\n");92 pr_err("Error: takes no arguments\n");
70 parse_options_usage(config_usage, config_options, "l", 1);93 parse_options_usage(config_usage, config_options, "l", 1);
71 } else {94 } else {
72 ret = perf_config(show_config, NULL);95 ret = show_config(set);
73 if (ret < 0) {96 if (ret < 0) {
74 const char * config_filename = config_exclusive_filename;97 const char * config_filename = config_exclusive_filename;
75 if (!config_exclusive_filename)98 if (!config_exclusive_filename)
@@ -83,5 +106,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) · 7 unmodified lines
83 usage_with_options(config_usage, config_options);106 usage_with_options(config_usage, config_options);
84 }107 }
85 108
109 perf_config_set__delete(set);
110out_err:
86 return ret;111 return ret;
87}112}
tools/perf/builtin-diff.c+2−2
@@ -428,7 +428,7 @@ static void hists__baseline_only(struct hists *hists) · 427 unmodified lines
428 struct rb_root *root;428 struct rb_root *root;
429 struct rb_node *next;429 struct rb_node *next;
430 430
431 if (sort__need_collapse)431 if (hists__has(hists, need_collapse))
432 root = &hists->entries_collapsed;432 root = &hists->entries_collapsed;
433 else433 else
434 root = hists->entries_in;434 root = hists->entries_in;
@@ -450,7 +450,7 @@ static void hists__precompute(struct hists *hists) · 15 unmodified lines
450 struct rb_root *root;450 struct rb_root *root;
451 struct rb_node *next;451 struct rb_node *next;
452 452
453 if (sort__need_collapse)453 if (hists__has(hists, need_collapse))
454 root = &hists->entries_collapsed;454 root = &hists->entries_collapsed;
455 else455 else
456 root = hists->entries_in;456 root = hists->entries_in;
tools/perf/builtin-help.c+10−8
@@ -61,6 +61,7 @@ static int check_emacsclient_version(void) · 60 unmodified lines
61 struct child_process ec_process;61 struct child_process ec_process;
62 const char *argv_ec[] = { "emacsclient", "--version", NULL };62 const char *argv_ec[] = { "emacsclient", "--version", NULL };
63 int version;63 int version;
64 int ret = -1;
64 65
65 /* emacsclient prints its version number on stderr */66 /* emacsclient prints its version number on stderr */
66 memset(&ec_process, 0, sizeof(ec_process));67 memset(&ec_process, 0, sizeof(ec_process));
@@ -71,7 +72,10 @@ static int check_emacsclient_version(void) · 4 unmodified lines
71 fprintf(stderr, "Failed to start emacsclient.\n");72 fprintf(stderr, "Failed to start emacsclient.\n");
72 return -1;73 return -1;
73 }74 }
74 strbuf_read(&buffer, ec_process.err, 20);75 if (strbuf_read(&buffer, ec_process.err, 20) < 0) {
76 fprintf(stderr, "Failed to read emacsclient version\n");
77 goto out;
78 }
75 close(ec_process.err);79 close(ec_process.err);
76 80
77 /*81 /*
@@ -82,8 +86,7 @@ static int check_emacsclient_version(void) · 4 unmodified lines
82 86
83 if (prefixcmp(buffer.buf, "emacsclient")) {87 if (prefixcmp(buffer.buf, "emacsclient")) {
84 fprintf(stderr, "Failed to parse emacsclient version.\n");88 fprintf(stderr, "Failed to parse emacsclient version.\n");
85 strbuf_release(&buffer);89 goto out;
86 return -1;
87 }90 }
88 91
89 version = atoi(buffer.buf + strlen("emacsclient"));92 version = atoi(buffer.buf + strlen("emacsclient"));
@@ -92,12 +95,11 @@ static int check_emacsclient_version(void) · 2 unmodified lines
92 fprintf(stderr,95 fprintf(stderr,
93 "emacsclient version '%d' too old (< 22).\n",96 "emacsclient version '%d' too old (< 22).\n",
94 version);97 version);
95 strbuf_release(&buffer);98 } else
96 return -1;99 ret = 0;
97 }100out:
98
99 strbuf_release(&buffer);101 strbuf_release(&buffer);
100 return 0;102 return ret;
101}103}
102 104
103static void exec_woman_emacs(const char *path, const char *page)105static void exec_woman_emacs(const char *path, const char *page)
tools/perf/builtin-inject.c+1−0
@@ -748,6 +748,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused) · 747 unmodified lines
748 .auxtrace_info = perf_event__repipe_op2_synth,748 .auxtrace_info = perf_event__repipe_op2_synth,
749 .auxtrace = perf_event__repipe_auxtrace,749 .auxtrace = perf_event__repipe_auxtrace,
750 .auxtrace_error = perf_event__repipe_op2_synth,750 .auxtrace_error = perf_event__repipe_op2_synth,
751 .time_conv = perf_event__repipe_op2_synth,
751 .finished_round = perf_event__repipe_oe_synth,752 .finished_round = perf_event__repipe_oe_synth,
752 .build_id = perf_event__repipe_op2_synth,753 .build_id = perf_event__repipe_op2_synth,
753 .id_index = perf_event__repipe_op2_synth,754 .id_index = perf_event__repipe_op2_synth,
tools/perf/builtin-kmem.c+1−1
@@ -375,7 +375,7 @@ static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample) · 374 unmodified lines
375 }375 }
376 376
377 al.thread = machine__findnew_thread(machine, sample->pid, sample->tid);377 al.thread = machine__findnew_thread(machine, sample->pid, sample->tid);
378 sample__resolve_callchain(sample, NULL, evsel, &al, 16);378 sample__resolve_callchain(sample, &callchain_cursor, NULL, evsel, &al, 16);
379 379
380 callchain_cursor_commit(&callchain_cursor);380 callchain_cursor_commit(&callchain_cursor);
381 while (true) {381 while (true) {
tools/perf/builtin-kvm.c+1−1
@@ -982,7 +982,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm) · 981 unmodified lines
982 struct perf_evlist *evlist = kvm->evlist;982 struct perf_evlist *evlist = kvm->evlist;
983 char sbuf[STRERR_BUFSIZE];983 char sbuf[STRERR_BUFSIZE];
984 984
985 perf_evlist__config(evlist, &kvm->opts);985 perf_evlist__config(evlist, &kvm->opts, NULL);
986 986
987 /*987 /*
988 * Note: exclude_{guest,host} do not apply here.988 * Note: exclude_{guest,host} do not apply here.
tools/perf/builtin-mem.c+10−1
@@ -62,19 +62,22 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) · 61 unmodified lines
62 int rec_argc, i = 0, j;62 int rec_argc, i = 0, j;
63 const char **rec_argv;63 const char **rec_argv;
64 int ret;64 int ret;
65 bool all_user = false, all_kernel = false;
65 struct option options[] = {66 struct option options[] = {
66 OPT_CALLBACK('e', "event", &mem, "event",67 OPT_CALLBACK('e', "event", &mem, "event",
67 "event selector. use 'perf mem record -e list' to list available events",68 "event selector. use 'perf mem record -e list' to list available events",
68 parse_record_events),69 parse_record_events),
69 OPT_INCR('v', "verbose", &verbose,70 OPT_INCR('v', "verbose", &verbose,
70 "be more verbose (show counter open errors, etc)"),71 "be more verbose (show counter open errors, etc)"),
72 OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"),
73 OPT_BOOLEAN('K', "--all-kernel", &all_kernel, "collect only kernel level data"),
71 OPT_END()74 OPT_END()
72 };75 };
73 76
74 argc = parse_options(argc, argv, options, record_mem_usage,77 argc = parse_options(argc, argv, options, record_mem_usage,
75 PARSE_OPT_STOP_AT_NON_OPTION);78 PARSE_OPT_STOP_AT_NON_OPTION);
76 79
77 rec_argc = argc + 7; /* max number of arguments */80 rec_argc = argc + 9; /* max number of arguments */
78 rec_argv = calloc(rec_argc + 1, sizeof(char *));81 rec_argv = calloc(rec_argc + 1, sizeof(char *));
79 if (!rec_argv)82 if (!rec_argv)
80 return -1;83 return -1;
@@ -103,6 +106,12 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem) · 22 unmodified lines
103 rec_argv[i++] = perf_mem_events__name(j);106 rec_argv[i++] = perf_mem_events__name(j);
104 };107 };
105 108
109 if (all_user)
110 rec_argv[i++] = "--all-user";
111
112 if (all_kernel)
113 rec_argv[i++] = "--all-kernel";
114
106 for (j = 0; j < argc; j++, i++)115 for (j = 0; j < argc; j++, i++)
107 rec_argv[i] = argv[j];116 rec_argv[i] = argv[j];
108 117
tools/perf/builtin-record.c+220−47
@@ -29,10 +29,12 @@ · 28 unmodified lines
29#include "util/data.h"29#include "util/data.h"
30#include "util/perf_regs.h"30#include "util/perf_regs.h"
31#include "util/auxtrace.h"31#include "util/auxtrace.h"
32#include "util/tsc.h"
32#include "util/parse-branch-options.h"33#include "util/parse-branch-options.h"
33#include "util/parse-regs-options.h"34#include "util/parse-regs-options.h"
34#include "util/llvm-utils.h"35#include "util/llvm-utils.h"
35#include "util/bpf-loader.h"36#include "util/bpf-loader.h"
37#include "util/trigger.h"
36#include "asm/bug.h"38#include "asm/bug.h"
37 39
38#include <unistd.h>40#include <unistd.h>
@@ -55,6 +57,8 @@ struct record { · 16 unmodified lines
55 bool no_buildid_cache;57 bool no_buildid_cache;
56 bool no_buildid_cache_set;58 bool no_buildid_cache_set;
57 bool buildid_all;59 bool buildid_all;
60 bool timestamp_filename;
61 bool switch_output;
58 unsigned long long samples;62 unsigned long long samples;
59};63};
60 64
@@ -124,9 +128,10 @@ out: · 63 unmodified lines
124static volatile int done;128static volatile int done;
125static volatile int signr = -1;129static volatile int signr = -1;
126static volatile int child_finished;130static volatile int child_finished;
127static volatile int auxtrace_snapshot_enabled;131
128static volatile int auxtrace_snapshot_err;
129static volatile int auxtrace_record__snapshot_started;132static volatile int auxtrace_record__snapshot_started;
133static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
134static DEFINE_TRIGGER(switch_output_trigger);
130 135
131static void sig_handler(int sig)136static void sig_handler(int sig)
132{137{
@@ -244,11 +249,12 @@ static void record__read_auxtrace_snapshot(struct record *rec) · 111 unmodified lines
244{249{
245 pr_debug("Recording AUX area tracing snapshot\n");250 pr_debug("Recording AUX area tracing snapshot\n");
246 if (record__auxtrace_read_snapshot_all(rec) < 0) {251 if (record__auxtrace_read_snapshot_all(rec) < 0) {
247 auxtrace_snapshot_err = -1;252 trigger_error(&auxtrace_snapshot_trigger);
248 } else {253 } else {
249 auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr);254 if (auxtrace_record__snapshot_finish(rec->itr))
250 if (!auxtrace_snapshot_err)255 trigger_error(&auxtrace_snapshot_trigger);
251 auxtrace_snapshot_enabled = 1;256 else
257 trigger_ready(&auxtrace_snapshot_trigger);
252 }258 }
253}259}
254 260
@@ -283,7 +289,7 @@ static int record__open(struct record *rec) · 28 unmodified lines
283 struct record_opts *opts = &rec->opts;289 struct record_opts *opts = &rec->opts;
284 int rc = 0;290 int rc = 0;
285 291
286 perf_evlist__config(evlist, opts);292 perf_evlist__config(evlist, opts, &callchain_param);
287 293
288 evlist__for_each(evlist, pos) {294 evlist__for_each(evlist, pos) {
289try_again:295try_again:
@@ -494,6 +500,73 @@ record__finish_output(struct record *rec) · 204 unmodified lines
494 return;500 return;
495}501}
496 502
503static int record__synthesize_workload(struct record *rec)
504{
505 struct {
506 struct thread_map map;
507 struct thread_map_data map_data;
508 } thread_map;
509
510 thread_map.map.nr = 1;
511 thread_map.map.map[0].pid = rec->evlist->workload.pid;
512 thread_map.map.map[0].comm = NULL;
513 return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
514 process_synthesized_event,
515 &rec->session->machines.host,
516 rec->opts.sample_address,
517 rec->opts.proc_map_timeout);
518}
519
520static int record__synthesize(struct record *rec);
521
522static int
523record__switch_output(struct record *rec, bool at_exit)
524{
525 struct perf_data_file *file = &rec->file;
526 int fd, err;
527
528 /* Same Size: "2015122520103046"*/
529 char timestamp[] = "InvalidTimestamp";
530
531 rec->samples = 0;
532 record__finish_output(rec);
533 err = fetch_current_timestamp(timestamp, sizeof(timestamp));
534 if (err) {
535 pr_err("Failed to get current timestamp\n");
536 return -EINVAL;
537 }
538
539 fd = perf_data_file__switch(file, timestamp,
540 rec->session->header.data_offset,
541 at_exit);
542 if (fd >= 0 && !at_exit) {
543 rec->bytes_written = 0;
544 rec->session->header.data_size = 0;
545 }
546
547 if (!quiet)
548 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
549 file->path, timestamp);
550
551 /* Output tracking events */
552 if (!at_exit) {
553 record__synthesize(rec);
554
555 /*
556 * In 'perf record --switch-output' without -a,
557 * record__synthesize() in record__switch_output() won't
558 * generate tracking events because there's no thread_map
559 * in evlist. Which causes newly created perf.data doesn't
560 * contain map and comm information.
561 * Create a fake thread_map and directly call
562 * perf_event__synthesize_thread_map() for those events.
563 */
564 if (target__none(&rec->opts.target))
565 record__synthesize_workload(rec);
566 }
567 return fd;
568}
569
497static volatile int workload_exec_errno;570static volatile int workload_exec_errno;
498 571
499/*572/*
@@ -512,6 +585,15 @@ static void workload_exec_failed_signal(int signo __maybe_unused, · 12 unmodified lines
512 585
513static void snapshot_sig_handler(int sig);586static void snapshot_sig_handler(int sig);
514 587
588int __weak
589perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
590 struct perf_tool *tool __maybe_unused,
591 perf_event__handler_t process __maybe_unused,
592 struct machine *machine __maybe_unused)
593{
594 return 0;
595}
596
515static int record__synthesize(struct record *rec)597static int record__synthesize(struct record *rec)
516{598{
517 struct perf_session *session = rec->session;599 struct perf_session *session = rec->session;
@@ -549,6 +631,11 @@ static int record__synthesize(struct record *rec) · 31 unmodified lines
549 }631 }
550 }632 }
551 633
634 err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool,
635 process_synthesized_event, machine);
636 if (err)
637 goto out;
638
552 if (rec->opts.full_auxtrace) {639 if (rec->opts.full_auxtrace) {
553 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,640 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
554 session, process_synthesized_event);641 session, process_synthesized_event);
@@ -600,10 +687,16 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) · 45 unmodified lines
600 signal(SIGCHLD, sig_handler);687 signal(SIGCHLD, sig_handler);
601 signal(SIGINT, sig_handler);688 signal(SIGINT, sig_handler);
602 signal(SIGTERM, sig_handler);689 signal(SIGTERM, sig_handler);
603 if (rec->opts.auxtrace_snapshot_mode)690
691 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
604 signal(SIGUSR2, snapshot_sig_handler);692 signal(SIGUSR2, snapshot_sig_handler);
605 else693 if (rec->opts.auxtrace_snapshot_mode)
694 trigger_on(&auxtrace_snapshot_trigger);
695 if (rec->switch_output)
696 trigger_on(&switch_output_trigger);
697 } else {
606 signal(SIGUSR2, SIG_IGN);698 signal(SIGUSR2, SIG_IGN);
699 }
607 700
608 session = perf_session__new(file, false, tool);701 session = perf_session__new(file, false, tool);
609 if (session == NULL) {702 if (session == NULL) {
@@ -729,27 +822,45 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) · 119 unmodified lines
729 perf_evlist__enable(rec->evlist);822 perf_evlist__enable(rec->evlist);
730 }823 }
731 824
732 auxtrace_snapshot_enabled = 1;825 trigger_ready(&auxtrace_snapshot_trigger);
826 trigger_ready(&switch_output_trigger);
733 for (;;) {827 for (;;) {
734 unsigned long long hits = rec->samples;828 unsigned long long hits = rec->samples;
735 829
736 if (record__mmap_read_all(rec) < 0) {830 if (record__mmap_read_all(rec) < 0) {
737 auxtrace_snapshot_enabled = 0;831 trigger_error(&auxtrace_snapshot_trigger);
832 trigger_error(&switch_output_trigger);
738 err = -1;833 err = -1;
739 goto out_child;834 goto out_child;
740 }835 }
741 836
742 if (auxtrace_record__snapshot_started) {837 if (auxtrace_record__snapshot_started) {
743 auxtrace_record__snapshot_started = 0;838 auxtrace_record__snapshot_started = 0;
744 if (!auxtrace_snapshot_err)839 if (!trigger_is_error(&auxtrace_snapshot_trigger))
745 record__read_auxtrace_snapshot(rec);840 record__read_auxtrace_snapshot(rec);
746 if (auxtrace_snapshot_err) {841 if (trigger_is_error(&auxtrace_snapshot_trigger)) {
747 pr_err("AUX area tracing snapshot failed\n");842 pr_err("AUX area tracing snapshot failed\n");
748 err = -1;843 err = -1;
749 goto out_child;844 goto out_child;
750 }845 }
751 }846 }
752 847
848 if (trigger_is_hit(&switch_output_trigger)) {
849 trigger_ready(&switch_output_trigger);
850
851 if (!quiet)
852 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
853 waking);
854 waking = 0;
855 fd = record__switch_output(rec, false);
856 if (fd < 0) {
857 pr_err("Failed to switch to new file\n");
858 trigger_error(&switch_output_trigger);
859 err = fd;
860 goto out_child;
861 }
862 }
863
753 if (hits == rec->samples) {864 if (hits == rec->samples) {
754 if (done || draining)865 if (done || draining)
755 break;866 break;
@@ -772,12 +883,13 @@ static int __cmd_record(struct record *rec, int argc, const char **argv) · 16 unmodified lines
772 * disable events in this case.883 * disable events in this case.
773 */884 */
774 if (done && !disabled && !target__none(&opts->target)) {885 if (done && !disabled && !target__none(&opts->target)) {
775 auxtrace_snapshot_enabled = 0;886 trigger_off(&auxtrace_snapshot_trigger);
776 perf_evlist__disable(rec->evlist);887 perf_evlist__disable(rec->evlist);
777 disabled = true;888 disabled = true;
778 }889 }
779 }890 }
780 auxtrace_snapshot_enabled = 0;891 trigger_off(&auxtrace_snapshot_trigger);
892 trigger_off(&switch_output_trigger);
781 893
782 if (forks && workload_exec_errno) {894 if (forks && workload_exec_errno) {
783 char msg[STRERR_BUFSIZE];895 char msg[STRERR_BUFSIZE];
@@ -811,11 +923,22 @@ out_child: · 27 unmodified lines
811 /* this will be recalculated during process_buildids() */923 /* this will be recalculated during process_buildids() */
812 rec->samples = 0;924 rec->samples = 0;
813 925
814 if (!err)926 if (!err) {
815 record__finish_output(rec);927 if (!rec->timestamp_filename) {
928 record__finish_output(rec);
929 } else {
930 fd = record__switch_output(rec, true);
931 if (fd < 0) {
932 status = fd;
933 goto out_delete_session;
934 }
935 }
936 }
816 937
817 if (!err && !quiet) {938 if (!err && !quiet) {
818 char samples[128];939 char samples[128];
940 const char *postfix = rec->timestamp_filename ?
941 ".<timestamp>" : "";
819 942
820 if (rec->samples && !rec->opts.full_auxtrace)943 if (rec->samples && !rec->opts.full_auxtrace)
821 scnprintf(samples, sizeof(samples),944 scnprintf(samples, sizeof(samples),
@@ -823,9 +946,9 @@ out_child: · 1 unmodified line
823 else946 else
824 samples[0] = '\0';947 samples[0] = '\0';
825 948
826 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n",949 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
827 perf_data_file__size(file) / 1024.0 / 1024.0,950 perf_data_file__size(file) / 1024.0 / 1024.0,
828 file->path, samples);951 file->path, postfix, samples);
829 }952 }
830 953
831out_delete_session:954out_delete_session:
@@ -833,58 +956,61 @@ out_delete_session: · 1 unmodified line
833 return status;956 return status;
834}957}
835 958
836static void callchain_debug(void)959static void callchain_debug(struct callchain_param *callchain)
837{960{
838 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };961 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
839 962
840 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]);963 pr_debug("callchain: type %s\n", str[callchain->record_mode]);
841 964
842 if (callchain_param.record_mode == CALLCHAIN_DWARF)965 if (callchain->record_mode == CALLCHAIN_DWARF)
843 pr_debug("callchain: stack dump size %d\n",966 pr_debug("callchain: stack dump size %d\n",
844 callchain_param.dump_size);967 callchain->dump_size);
845}968}
846 969
847int record_parse_callchain_opt(const struct option *opt,970int record_opts__parse_callchain(struct record_opts *record,
848 const char *arg,971 struct callchain_param *callchain,
849 int unset)972 const char *arg, bool unset)
850{973{
851 int ret;974 int ret;
852 struct record_opts *record = (struct record_opts *)opt->value;975 callchain->enabled = !unset;
853
854 record->callgraph_set = true;
855 callchain_param.enabled = !unset;
856 976
857 /* --no-call-graph */977 /* --no-call-graph */
858 if (unset) {978 if (unset) {
859 callchain_param.record_mode = CALLCHAIN_NONE;979 callchain->record_mode = CALLCHAIN_NONE;
860 pr_debug("callchain: disabled\n");980 pr_debug("callchain: disabled\n");
861 return 0;981 return 0;
862 }982 }
863 983
864 ret = parse_callchain_record_opt(arg, &callchain_param);984 ret = parse_callchain_record_opt(arg, callchain);
865 if (!ret) {985 if (!ret) {
866 /* Enable data address sampling for DWARF unwind. */986 /* Enable data address sampling for DWARF unwind. */
867 if (callchain_param.record_mode == CALLCHAIN_DWARF)987 if (callchain->record_mode == CALLCHAIN_DWARF)
868 record->sample_address = true;988 record->sample_address = true;
869 callchain_debug();989 callchain_debug(callchain);
870 }990 }
871 991
872 return ret;992 return ret;
873}993}
874 994
995int record_parse_callchain_opt(const struct option *opt,
996 const char *arg,
997 int unset)
998{
999 return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
1000}
1001
875int record_callchain_opt(const struct option *opt,1002int record_callchain_opt(const struct option *opt,
876 const char *arg __maybe_unused,1003 const char *arg __maybe_unused,
877 int unset __maybe_unused)1004 int unset __maybe_unused)
878{1005{
879 struct record_opts *record = (struct record_opts *)opt->value;1006 struct callchain_param *callchain = opt->value;
880 1007
881 record->callgraph_set = true;1008 callchain->enabled = true;
882 callchain_param.enabled = true;
883 1009
884 if (callchain_param.record_mode == CALLCHAIN_NONE)1010 if (callchain->record_mode == CALLCHAIN_NONE)
885 callchain_param.record_mode = CALLCHAIN_FP;1011 callchain->record_mode = CALLCHAIN_FP;
886 1012
887 callchain_debug();1013 callchain_debug(callchain);
888 return 0;1014 return 0;
889}1015}
890 1016
@@ -1122,7 +1248,7 @@ struct option __record_options[] = { · 231 unmodified lines
1122 record__parse_mmap_pages),1248 record__parse_mmap_pages),
1123 OPT_BOOLEAN(0, "group", &record.opts.group,1249 OPT_BOOLEAN(0, "group", &record.opts.group,
1124 "put the counters into a counter group"),1250 "put the counters into a counter group"),
1125 OPT_CALLBACK_NOOPT('g', NULL, &record.opts,1251 OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
1126 NULL, "enables call-graph recording" ,1252 NULL, "enables call-graph recording" ,
1127 &record_callchain_opt),1253 &record_callchain_opt),
1128 OPT_CALLBACK(0, "call-graph", &record.opts,1254 OPT_CALLBACK(0, "call-graph", &record.opts,
@@ -1195,6 +1321,10 @@ struct option __record_options[] = { · 66 unmodified lines
1195 "file", "vmlinux pathname"),1321 "file", "vmlinux pathname"),
1196 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,1322 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
1197 "Record build-id of all DSOs regardless of hits"),1323 "Record build-id of all DSOs regardless of hits"),
1324 OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1325 "append timestamp to output filename"),
1326 OPT_BOOLEAN(0, "switch-output", &record.switch_output,
1327 "Switch output when receive SIGUSR2"),
1198 OPT_END()1328 OPT_END()
1199};1329};
1200 1330
@@ -1250,6 +1380,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) · 49 unmodified lines
1250 return -EINVAL;1380 return -EINVAL;
1251 }1381 }
1252 1382
1383 if (rec->switch_output)
1384 rec->timestamp_filename = true;
1385
1253 if (!rec->itr) {1386 if (!rec->itr) {
1254 rec->itr = auxtrace_record__init(rec->evlist, &err);1387 rec->itr = auxtrace_record__init(rec->evlist, &err);
1255 if (err)1388 if (err)
@@ -1261,6 +1394,14 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) · 5 unmodified lines
1261 if (err)1394 if (err)
1262 return err;1395 return err;
1263 1396
1397 err = bpf__setup_stdout(rec->evlist);
1398 if (err) {
1399 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1400 pr_err("ERROR: Setup BPF stdout failed: %s\n",
1401 errbuf);
1402 return err;
1403 }
1404
1264 err = -ENOMEM;1405 err = -ENOMEM;
1265 1406
1266 symbol__init(NULL);1407 symbol__init(NULL);
@@ -1275,8 +1416,36 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused) · 8 unmodified lines
1275"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"1416"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1276"even with a suitable vmlinux or kallsyms file.\n\n");1417"even with a suitable vmlinux or kallsyms file.\n\n");
1277 1418
1278 if (rec->no_buildid_cache || rec->no_buildid)1419 if (rec->no_buildid_cache || rec->no_buildid) {
1279 disable_buildid_cache();1420 disable_buildid_cache();
1421 } else if (rec->switch_output) {
1422 /*
1423 * In 'perf record --switch-output', disable buildid
1424 * generation by default to reduce data file switching
1425 * overhead. Still generate buildid if they are required
1426 * explicitly using
1427 *
1428 * perf record --signal-trigger --no-no-buildid \
1429 * --no-no-buildid-cache
1430 *
1431 * Following code equals to:
1432 *
1433 * if ((rec->no_buildid || !rec->no_buildid_set) &&
1434 * (rec->no_buildid_cache || !rec->no_buildid_cache_set))
1435 * disable_buildid_cache();
1436 */
1437 bool disable = true;
1438
1439 if (rec->no_buildid_set && !rec->no_buildid)
1440 disable = false;
1441 if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
1442 disable = false;
1443 if (disable) {
1444 rec->no_buildid = true;
1445 rec->no_buildid_cache = true;
1446 disable_buildid_cache();
1447 }
1448 }
1280 1449
1281 if (rec->evlist->nr_entries == 0 &&1450 if (rec->evlist->nr_entries == 0 &&
1282 perf_evlist__add_default(rec->evlist) < 0) {1451 perf_evlist__add_default(rec->evlist) < 0) {
@@ -1335,9 +1504,13 @@ out_symbol_exit: · 52 unmodified lines
1335 1504
1336static void snapshot_sig_handler(int sig __maybe_unused)1505static void snapshot_sig_handler(int sig __maybe_unused)
1337{1506{
1338 if (!auxtrace_snapshot_enabled)1507 if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
1339 return;1508 trigger_hit(&auxtrace_snapshot_trigger);
1340 auxtrace_snapshot_enabled = 0;1509 auxtrace_record__snapshot_started = 1;
1341 auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr);1510 if (auxtrace_record__snapshot_start(record.itr))
1342 auxtrace_record__snapshot_started = 1;1511 trigger_error(&auxtrace_snapshot_trigger);
1512 }
1513
1514 if (trigger_is_ready(&switch_output_trigger))
1515 trigger_hit(&switch_output_trigger);
1343}1516}
tools/perf/builtin-report.c+10−9
@@ -47,7 +47,6 @@ struct report { · 46 unmodified lines
47 struct perf_tool tool;47 struct perf_tool tool;
48 struct perf_session *session;48 struct perf_session *session;
49 bool use_tui, use_gtk, use_stdio;49 bool use_tui, use_gtk, use_stdio;
50 bool dont_use_callchains;
51 bool show_full_info;50 bool show_full_info;
52 bool show_threads;51 bool show_threads;
53 bool inverted_callchain;52 bool inverted_callchain;
@@ -235,7 +234,7 @@ static int report__setup_sample_type(struct report *rep) · 181 unmodified lines
235 sample_type |= PERF_SAMPLE_BRANCH_STACK;234 sample_type |= PERF_SAMPLE_BRANCH_STACK;
236 235
237 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {236 if (!is_pipe && !(sample_type & PERF_SAMPLE_CALLCHAIN)) {
238 if (sort__has_parent) {237 if (perf_hpp_list.parent) {
239 ui__error("Selected --sort parent, but no "238 ui__error("Selected --sort parent, but no "
240 "callchain data. Did you call "239 "callchain data. Did you call "
241 "'perf record' without -g?\n");240 "'perf record' without -g?\n");
@@ -247,7 +246,7 @@ static int report__setup_sample_type(struct report *rep) · 5 unmodified lines
247 "you call 'perf record' without -g?\n");246 "you call 'perf record' without -g?\n");
248 return -1;247 return -1;
249 }248 }
250 } else if (!rep->dont_use_callchains &&249 } else if (!callchain_param.enabled &&
251 callchain_param.mode != CHAIN_NONE &&250 callchain_param.mode != CHAIN_NONE &&
252 !symbol_conf.use_callchain) {251 !symbol_conf.use_callchain) {
253 symbol_conf.use_callchain = true;252 symbol_conf.use_callchain = true;
@@ -599,13 +598,15 @@ static int __cmd_report(struct report *rep) · 345 unmodified lines
599static int598static int
600report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)599report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
601{600{
602 struct report *rep = (struct report *)opt->value;601 struct callchain_param *callchain = opt->value;
603 602
603 callchain->enabled = !unset;
604 /*604 /*
605 * --no-call-graph605 * --no-call-graph
606 */606 */
607 if (unset) {607 if (unset) {
608 rep->dont_use_callchains = true;608 symbol_conf.use_callchain = false;
609 callchain->mode = CHAIN_NONE;
609 return 0;610 return 0;
610 }611 }
611 612
@@ -690,7 +691,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) · 78 unmodified lines
690 .ordered_events = true,691 .ordered_events = true,
691 .ordering_requires_timestamps = true,692 .ordering_requires_timestamps = true,
692 },693 },
693 .max_stack = PERF_MAX_STACK_DEPTH,694 .max_stack = sysctl_perf_event_max_stack,
694 .pretty_printing_style = "normal",695 .pretty_printing_style = "normal",
695 .socket_filter = -1,696 .socket_filter = -1,
696 };697 };
@@ -734,7 +735,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) · 37 unmodified lines
734 "regex filter to identify parent, see: '--sort parent'"),735 "regex filter to identify parent, see: '--sort parent'"),
735 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,736 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
736 "Only display entries with parent-match"),737 "Only display entries with parent-match"),
737 OPT_CALLBACK_DEFAULT('g', "call-graph", &report,738 OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
738 "print_type,threshold[,print_limit],order,sort_key[,branch],value",739 "print_type,threshold[,print_limit],order,sort_key[,branch],value",
739 report_callchain_help, &report_parse_callchain_opt,740 report_callchain_help, &report_parse_callchain_opt,
740 callchain_default_opt),741 callchain_default_opt),
@@ -743,7 +744,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) · 2 unmodified lines
743 OPT_INTEGER(0, "max-stack", &report.max_stack,744 OPT_INTEGER(0, "max-stack", &report.max_stack,
744 "Set the maximum stack depth when parsing the callchain, "745 "Set the maximum stack depth when parsing the callchain, "
745 "anything beyond the specified depth will be ignored. "746 "anything beyond the specified depth will be ignored. "
746 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),747 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
747 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,748 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
748 "alias for inverted call graph"),749 "alias for inverted call graph"),
749 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",750 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
@@ -935,7 +936,7 @@ repeat: · 185 unmodified lines
935 goto error;936 goto error;
936 }937 }
937 938
938 sort__need_collapse = true;939 perf_hpp_list.need_collapse = true;
939 }940 }
940 941
941 /* Force tty output for header output and per-thread stat. */942 /* Force tty output for header output and per-thread stat. */
tools/perf/builtin-sched.c+186−12
@@ -11,6 +11,8 @@ · 10 unmodified lines
11#include "util/session.h"11#include "util/session.h"
12#include "util/tool.h"12#include "util/tool.h"
13#include "util/cloexec.h"13#include "util/cloexec.h"
14#include "util/thread_map.h"
15#include "util/color.h"
14 16
15#include <subcmd/parse-options.h>17#include <subcmd/parse-options.h>
16#include "util/trace-event.h"18#include "util/trace-event.h"
@@ -122,6 +124,21 @@ struct trace_sched_handler { · 105 unmodified lines
122 struct machine *machine);124 struct machine *machine);
123};125};
124 126
127#define COLOR_PIDS PERF_COLOR_BLUE
128#define COLOR_CPUS PERF_COLOR_BG_RED
129
130struct perf_sched_map {
131 DECLARE_BITMAP(comp_cpus_mask, MAX_CPUS);
132 int *comp_cpus;
133 bool comp;
134 struct thread_map *color_pids;
135 const char *color_pids_str;
136 struct cpu_map *color_cpus;
137 const char *color_cpus_str;
138 struct cpu_map *cpus;
139 const char *cpus_str;
140};
141
125struct perf_sched {142struct perf_sched {
126 struct perf_tool tool;143 struct perf_tool tool;
127 const char *sort_order;144 const char *sort_order;
@@ -173,6 +190,7 @@ struct perf_sched { · 45 unmodified lines
173 struct list_head sort_list, cmp_pid;190 struct list_head sort_list, cmp_pid;
174 bool force;191 bool force;
175 bool skip_merge;192 bool skip_merge;
193 struct perf_sched_map map;
176};194};
177 195
178static u64 get_nsecs(void)196static u64 get_nsecs(void)
@@ -1339,6 +1357,38 @@ static int process_sched_wakeup_event(struct perf_tool *tool, · 1160 unmodified lines
1339 return 0;1357 return 0;
1340}1358}
1341 1359
1360union map_priv {
1361 void *ptr;
1362 bool color;
1363};
1364
1365static bool thread__has_color(struct thread *thread)
1366{
1367 union map_priv priv = {
1368 .ptr = thread__priv(thread),
1369 };
1370
1371 return priv.color;
1372}
1373
1374static struct thread*
1375map__findnew_thread(struct perf_sched *sched, struct machine *machine, pid_t pid, pid_t tid)
1376{
1377 struct thread *thread = machine__findnew_thread(machine, pid, tid);
1378 union map_priv priv = {
1379 .color = false,
1380 };
1381
1382 if (!sched->map.color_pids || !thread || thread__priv(thread))
1383 return thread;
1384
1385 if (thread_map__has(sched->map.color_pids, tid))
1386 priv.color = true;
1387
1388 thread__set_priv(thread, priv.ptr);
1389 return thread;
1390}
1391
1342static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,1392static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1343 struct perf_sample *sample, struct machine *machine)1393 struct perf_sample *sample, struct machine *machine)
1344{1394{
@@ -1347,13 +1397,25 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, · 2 unmodified lines
1347 int new_shortname;1397 int new_shortname;
1348 u64 timestamp0, timestamp = sample->time;1398 u64 timestamp0, timestamp = sample->time;
1349 s64 delta;1399 s64 delta;
1350 int cpu, this_cpu = sample->cpu;1400 int i, this_cpu = sample->cpu;
1401 int cpus_nr;
1402 bool new_cpu = false;
1403 const char *color = PERF_COLOR_NORMAL;
1351 1404
1352 BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0);1405 BUG_ON(this_cpu >= MAX_CPUS || this_cpu < 0);
1353 1406
1354 if (this_cpu > sched->max_cpu)1407 if (this_cpu > sched->max_cpu)
1355 sched->max_cpu = this_cpu;1408 sched->max_cpu = this_cpu;
1356 1409
1410 if (sched->map.comp) {
1411 cpus_nr = bitmap_weight(sched->map.comp_cpus_mask, MAX_CPUS);
1412 if (!test_and_set_bit(this_cpu, sched->map.comp_cpus_mask)) {
1413 sched->map.comp_cpus[cpus_nr++] = this_cpu;
1414 new_cpu = true;
1415 }
1416 } else
1417 cpus_nr = sched->max_cpu;
1418
1357 timestamp0 = sched->cpu_last_switched[this_cpu];1419 timestamp0 = sched->cpu_last_switched[this_cpu];
1358 sched->cpu_last_switched[this_cpu] = timestamp;1420 sched->cpu_last_switched[this_cpu] = timestamp;
1359 if (timestamp0)1421 if (timestamp0)
@@ -1366,7 +1428,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, · 6 unmodified lines
1366 return -1;1428 return -1;
1367 }1429 }
1368 1430
1369 sched_in = machine__findnew_thread(machine, -1, next_pid);1431 sched_in = map__findnew_thread(sched, machine, -1, next_pid);
1370 if (sched_in == NULL)1432 if (sched_in == NULL)
1371 return -1;1433 return -1;
1372 1434
@@ -1400,26 +1462,52 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel, · 27 unmodified lines
1400 new_shortname = 1;1462 new_shortname = 1;
1401 }1463 }
1402 1464
1403 for (cpu = 0; cpu <= sched->max_cpu; cpu++) {1465 for (i = 0; i < cpus_nr; i++) {
1466 int cpu = sched->map.comp ? sched->map.comp_cpus[i] : i;
1467 struct thread *curr_thread = sched->curr_thread[cpu];
1468 const char *pid_color = color;
1469 const char *cpu_color = color;
1470
1471 if (curr_thread && thread__has_color(curr_thread))
1472 pid_color = COLOR_PIDS;
1473
1474 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, cpu))
1475 continue;
1476
1477 if (sched->map.color_cpus && cpu_map__has(sched->map.color_cpus, cpu))
1478 cpu_color = COLOR_CPUS;
1479
1404 if (cpu != this_cpu)1480 if (cpu != this_cpu)
1405 printf(" ");1481 color_fprintf(stdout, cpu_color, " ");
1406 else1482 else
1407 printf("*");1483 color_fprintf(stdout, cpu_color, "*");
1408 1484
1409 if (sched->curr_thread[cpu])1485 if (sched->curr_thread[cpu])
1410 printf("%2s ", sched->curr_thread[cpu]->shortname);1486 color_fprintf(stdout, pid_color, "%2s ", sched->curr_thread[cpu]->shortname);
1411 else1487 else
1412 printf(" ");1488 color_fprintf(stdout, color, " ");
1413 }1489 }
1414 1490
1415 printf(" %12.6f secs ", (double)timestamp/1e9);1491 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu))
1492 goto out;
1493
1494 color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9);
1416 if (new_shortname) {1495 if (new_shortname) {
1417 printf("%s => %s:%d\n",1496 const char *pid_color = color;
1497
1498 if (thread__has_color(sched_in))
1499 pid_color = COLOR_PIDS;
1500
1501 color_fprintf(stdout, pid_color, "%s => %s:%d",
1418 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid);1502 sched_in->shortname, thread__comm_str(sched_in), sched_in->tid);
1419 } else {
1420 printf("\n");
1421 }1503 }
1422 1504
1505 if (sched->map.comp && new_cpu)
1506 color_fprintf(stdout, color, " (CPU %d)", this_cpu);
1507
1508out:
1509 color_fprintf(stdout, color, "\n");
1510
1423 thread__put(sched_in);1511 thread__put(sched_in);
1424 1512
1425 return 0;1513 return 0;
@@ -1675,9 +1763,75 @@ static int perf_sched__lat(struct perf_sched *sched) · 249 unmodified lines
1675 return 0;1763 return 0;
1676}1764}
1677 1765
1766static int setup_map_cpus(struct perf_sched *sched)
1767{
1768 struct cpu_map *map;
1769
1770 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);
1771
1772 if (sched->map.comp) {
1773 sched->map.comp_cpus = zalloc(sched->max_cpu * sizeof(int));
1774 if (!sched->map.comp_cpus)
1775 return -1;
1776 }
1777
1778 if (!sched->map.cpus_str)
1779 return 0;
1780
1781 map = cpu_map__new(sched->map.cpus_str);
1782 if (!map) {
1783 pr_err("failed to get cpus map from %s\n", sched->map.cpus_str);
1784 return -1;
1785 }
1786
1787 sched->map.cpus = map;
1788 return 0;
1789}
1790
1791static int setup_color_pids(struct perf_sched *sched)
1792{
1793 struct thread_map *map;
1794
1795 if (!sched->map.color_pids_str)
1796 return 0;
1797
1798 map = thread_map__new_by_tid_str(sched->map.color_pids_str);
1799 if (!map) {
1800 pr_err("failed to get thread map from %s\n", sched->map.color_pids_str);
1801 return -1;
1802 }
1803
1804 sched->map.color_pids = map;
1805 return 0;
1806}
1807
1808static int setup_color_cpus(struct perf_sched *sched)
1809{
1810 struct cpu_map *map;
1811
1812 if (!sched->map.color_cpus_str)
1813 return 0;
1814
1815 map = cpu_map__new(sched->map.color_cpus_str);
1816 if (!map) {
1817 pr_err("failed to get thread map from %s\n", sched->map.color_cpus_str);
1818 return -1;
1819 }
1820
1821 sched->map.color_cpus = map;
1822 return 0;
1823}
1824
1678static int perf_sched__map(struct perf_sched *sched)1825static int perf_sched__map(struct perf_sched *sched)
1679{1826{
1680 sched->max_cpu = sysconf(_SC_NPROCESSORS_CONF);1827 if (setup_map_cpus(sched))
1828 return -1;
1829
1830 if (setup_color_pids(sched))
1831 return -1;
1832
1833 if (setup_color_cpus(sched))
1834 return -1;
1681 1835
1682 setup_pager();1836 setup_pager();
1683 if (perf_sched__read_events(sched))1837 if (perf_sched__read_events(sched))
@@ -1831,6 +1985,17 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) · 147 unmodified lines
1831 "dump raw trace in ASCII"),1985 "dump raw trace in ASCII"),
1832 OPT_END()1986 OPT_END()
1833 };1987 };
1988 const struct option map_options[] = {
1989 OPT_BOOLEAN(0, "compact", &sched.map.comp,
1990 "map output in compact mode"),
1991 OPT_STRING(0, "color-pids", &sched.map.color_pids_str, "pids",
1992 "highlight given pids in map"),
1993 OPT_STRING(0, "color-cpus", &sched.map.color_cpus_str, "cpus",
1994 "highlight given CPUs in map"),
1995 OPT_STRING(0, "cpus", &sched.map.cpus_str, "cpus",
1996 "display given CPUs in map"),
1997 OPT_END()
1998 };
1834 const char * const latency_usage[] = {1999 const char * const latency_usage[] = {
1835 "perf sched latency [<options>]",2000 "perf sched latency [<options>]",
1836 NULL2001 NULL
@@ -1839,6 +2004,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) · 2 unmodified lines
1839 "perf sched replay [<options>]",2004 "perf sched replay [<options>]",
1840 NULL2005 NULL
1841 };2006 };
2007 const char * const map_usage[] = {
2008 "perf sched map [<options>]",
2009 NULL
2010 };
1842 const char *const sched_subcommands[] = { "record", "latency", "map",2011 const char *const sched_subcommands[] = { "record", "latency", "map",
1843 "replay", "script", NULL };2012 "replay", "script", NULL };
1844 const char *sched_usage[] = {2013 const char *sched_usage[] = {
@@ -1887,6 +2056,11 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused) · 42 unmodified lines
1887 setup_sorting(&sched, latency_options, latency_usage);2056 setup_sorting(&sched, latency_options, latency_usage);
1888 return perf_sched__lat(&sched);2057 return perf_sched__lat(&sched);
1889 } else if (!strcmp(argv[0], "map")) {2058 } else if (!strcmp(argv[0], "map")) {
2059 if (argc) {
2060 argc = parse_options(argc, argv, map_options, map_usage, 0);
2061 if (argc)
2062 usage_with_options(map_usage, map_options);
2063 }
1890 sched.tp_handler = &map_ops;2064 sched.tp_handler = &map_ops;
1891 setup_sorting(&sched, latency_options, latency_usage);2065 setup_sorting(&sched, latency_options, latency_usage);
1892 return perf_sched__map(&sched);2066 return perf_sched__map(&sched);
tools/perf/builtin-script.c+35−21
@@ -22,6 +22,7 @@ · 21 unmodified lines
22#include "util/thread_map.h"22#include "util/thread_map.h"
23#include "util/stat.h"23#include "util/stat.h"
24#include <linux/bitmap.h>24#include <linux/bitmap.h>
25#include <linux/stringify.h>
25#include "asm/bug.h"26#include "asm/bug.h"
26#include "util/mem-events.h"27#include "util/mem-events.h"
27 28
@@ -317,19 +318,19 @@ static void set_print_ip_opts(struct perf_event_attr *attr) · 289 unmodified lines
317 318
318 output[type].print_ip_opts = 0;319 output[type].print_ip_opts = 0;
319 if (PRINT_FIELD(IP))320 if (PRINT_FIELD(IP))
320 output[type].print_ip_opts |= PRINT_IP_OPT_IP;321 output[type].print_ip_opts |= EVSEL__PRINT_IP;
321 322
322 if (PRINT_FIELD(SYM))323 if (PRINT_FIELD(SYM))
323 output[type].print_ip_opts |= PRINT_IP_OPT_SYM;324 output[type].print_ip_opts |= EVSEL__PRINT_SYM;
324 325
325 if (PRINT_FIELD(DSO))326 if (PRINT_FIELD(DSO))
326 output[type].print_ip_opts |= PRINT_IP_OPT_DSO;327 output[type].print_ip_opts |= EVSEL__PRINT_DSO;
327 328
328 if (PRINT_FIELD(SYMOFFSET))329 if (PRINT_FIELD(SYMOFFSET))
329 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET;330 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;
330 331
331 if (PRINT_FIELD(SRCLINE))332 if (PRINT_FIELD(SRCLINE))
332 output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE;333 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
333}334}
334 335
335/*336/*
@@ -569,18 +570,23 @@ static void print_sample_bts(struct perf_sample *sample, · 233 unmodified lines
569 /* print branch_from information */570 /* print branch_from information */
570 if (PRINT_FIELD(IP)) {571 if (PRINT_FIELD(IP)) {
571 unsigned int print_opts = output[attr->type].print_ip_opts;572 unsigned int print_opts = output[attr->type].print_ip_opts;
573 struct callchain_cursor *cursor = NULL;
572 574
573 if (symbol_conf.use_callchain && sample->callchain) {575 if (symbol_conf.use_callchain && sample->callchain &&
574 printf("\n");576 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
575 } else {577 sample, NULL, NULL, scripting_max_stack) == 0)
576 printf(" ");578 cursor = &callchain_cursor;
577 if (print_opts & PRINT_IP_OPT_SRCLINE) {579
580 if (cursor == NULL) {
581 putchar(' ');
582 if (print_opts & EVSEL__PRINT_SRCLINE) {
578 print_srcline_last = true;583 print_srcline_last = true;
579 print_opts &= ~PRINT_IP_OPT_SRCLINE;584 print_opts &= ~EVSEL__PRINT_SRCLINE;
580 }585 }
581 }586 } else
582 perf_evsel__print_ip(evsel, sample, al, print_opts,587 putchar('\n');
583 scripting_max_stack);588
589 sample__fprintf_sym(sample, al, 0, print_opts, cursor, stdout);
584 }590 }
585 591
586 /* print branch_to information */592 /* print branch_to information */
@@ -783,14 +789,15 @@ static void process_event(struct perf_script *script, · 196 unmodified lines
783 printf("%16" PRIu64, sample->weight);789 printf("%16" PRIu64, sample->weight);
784 790
785 if (PRINT_FIELD(IP)) {791 if (PRINT_FIELD(IP)) {
786 if (!symbol_conf.use_callchain)792 struct callchain_cursor *cursor = NULL;
787 printf(" ");793
788 else794 if (symbol_conf.use_callchain && sample->callchain &&
789 printf("\n");795 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
796 sample, NULL, NULL, scripting_max_stack) == 0)
797 cursor = &callchain_cursor;
790 798
791 perf_evsel__print_ip(evsel, sample, al,799 putchar(cursor ? '\n' : ' ');
792 output[attr->type].print_ip_opts,800 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
793 scripting_max_stack);
794 }801 }
795 802
796 if (PRINT_FIELD(IREGS))803 if (PRINT_FIELD(IREGS))
@@ -1959,6 +1966,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) · 1162 unmodified lines
1959 .exit = perf_event__process_exit,1966 .exit = perf_event__process_exit,
1960 .fork = perf_event__process_fork,1967 .fork = perf_event__process_fork,
1961 .attr = process_attr,1968 .attr = process_attr,
1969 .event_update = perf_event__process_event_update,
1962 .tracing_data = perf_event__process_tracing_data,1970 .tracing_data = perf_event__process_tracing_data,
1963 .build_id = perf_event__process_build_id,1971 .build_id = perf_event__process_build_id,
1964 .id_index = perf_event__process_id_index,1972 .id_index = perf_event__process_id_index,
@@ -2020,6 +2028,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) · 55 unmodified lines
2020 "only consider symbols in these pids"),2028 "only consider symbols in these pids"),
2021 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",2029 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
2022 "only consider symbols in these tids"),2030 "only consider symbols in these tids"),
2031 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
2032 "Set the maximum stack depth when parsing the callchain, "
2033 "anything beyond the specified depth will be ignored. "
2034 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
2023 OPT_BOOLEAN('I', "show-info", &show_full_info,2035 OPT_BOOLEAN('I', "show-info", &show_full_info,
2024 "display extended information from perf.data file"),2036 "display extended information from perf.data file"),
2025 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,2037 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -2055,6 +2067,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused) · 29 unmodified lines
2055 NULL2067 NULL
2056 };2068 };
2057 2069
2070 scripting_max_stack = sysctl_perf_event_max_stack;
2071
2058 setup_scripting();2072 setup_scripting();
2059 2073
2060 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,2074 argc = parse_options_subcommand(argc, argv, options, script_subcommands, script_usage,
tools/perf/builtin-stat.c+8−0
@@ -298,6 +298,14 @@ static int read_counter(struct perf_evsel *counter) · 297 unmodified lines
298 return -1;298 return -1;
299 }299 }
300 }300 }
301
302 if (verbose > 1) {
303 fprintf(stat_config.output,
304 "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
305 perf_evsel__name(counter),
306 cpu,
307 count->val, count->ena, count->run);
308 }
301 }309 }
302 }310 }
303 311
tools/perf/builtin-top.c+19−20
@@ -688,7 +688,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter, · 687 unmodified lines
688 struct hist_entry *he = iter->he;688 struct hist_entry *he = iter->he;
689 struct perf_evsel *evsel = iter->evsel;689 struct perf_evsel *evsel = iter->evsel;
690 690
691 if (sort__has_sym && single)691 if (perf_hpp_list.sym && single)
692 perf_top__record_precise_ip(top, he, evsel->idx, al->addr);692 perf_top__record_precise_ip(top, he, evsel->idx, al->addr);
693 693
694 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,694 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
@@ -886,7 +886,7 @@ static int perf_top__start_counters(struct perf_top *top) · 191 unmodified lines
886 struct perf_evlist *evlist = top->evlist;886 struct perf_evlist *evlist = top->evlist;
887 struct record_opts *opts = &top->record_opts;887 struct record_opts *opts = &top->record_opts;
888 888
889 perf_evlist__config(evlist, opts);889 perf_evlist__config(evlist, opts, &callchain_param);
890 890
891 evlist__for_each(evlist, counter) {891 evlist__for_each(evlist, counter) {
892try_again:892try_again:
@@ -917,15 +917,15 @@ out_err: · 24 unmodified lines
917 return -1;917 return -1;
918}918}
919 919
920static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused)920static int callchain_param__setup_sample_type(struct callchain_param *callchain)
921{921{
922 if (!sort__has_sym) {922 if (!perf_hpp_list.sym) {
923 if (symbol_conf.use_callchain) {923 if (callchain->enabled) {
924 ui__error("Selected -g but \"sym\" not present in --sort/-s.");924 ui__error("Selected -g but \"sym\" not present in --sort/-s.");
925 return -EINVAL;925 return -EINVAL;
926 }926 }
927 } else if (callchain_param.mode != CHAIN_NONE) {927 } else if (callchain->mode != CHAIN_NONE) {
928 if (callchain_register_param(&callchain_param) < 0) {928 if (callchain_register_param(callchain) < 0) {
929 ui__error("Can't register callchain params.\n");929 ui__error("Can't register callchain params.\n");
930 return -EINVAL;930 return -EINVAL;
931 }931 }
@@ -952,7 +952,7 @@ static int __cmd_top(struct perf_top *top) · 20 unmodified lines
952 goto out_delete;952 goto out_delete;
953 }953 }
954 954
955 ret = perf_top__setup_sample_type(top);955 ret = callchain_param__setup_sample_type(&callchain_param);
956 if (ret)956 if (ret)
957 goto out_delete;957 goto out_delete;
958 958
@@ -962,7 +962,7 @@ static int __cmd_top(struct perf_top *top) · 3 unmodified lines
962 machine__synthesize_threads(&top->session->machines.host, &opts->target,962 machine__synthesize_threads(&top->session->machines.host, &opts->target,
963 top->evlist->threads, false, opts->proc_map_timeout);963 top->evlist->threads, false, opts->proc_map_timeout);
964 964
965 if (sort__has_socket) {965 if (perf_hpp_list.socket) {
966 ret = perf_env__read_cpu_topology_map(&perf_env);966 ret = perf_env__read_cpu_topology_map(&perf_env);
967 if (ret < 0)967 if (ret < 0)
968 goto out_err_cpu_topo;968 goto out_err_cpu_topo;
@@ -1045,18 +1045,17 @@ callchain_opt(const struct option *opt, const char *arg, int unset) · 76 unmodified lines
1045static int1045static int
1046parse_callchain_opt(const struct option *opt, const char *arg, int unset)1046parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1047{1047{
1048 struct record_opts *record = (struct record_opts *)opt->value;1048 struct callchain_param *callchain = opt->value;
1049 1049
1050 record->callgraph_set = true;1050 callchain->enabled = !unset;
1051 callchain_param.enabled = !unset;1051 callchain->record_mode = CALLCHAIN_FP;
1052 callchain_param.record_mode = CALLCHAIN_FP;
1053 1052
1054 /*1053 /*
1055 * --no-call-graph1054 * --no-call-graph
1056 */1055 */
1057 if (unset) {1056 if (unset) {
1058 symbol_conf.use_callchain = false;1057 symbol_conf.use_callchain = false;
1059 callchain_param.record_mode = CALLCHAIN_NONE;1058 callchain->record_mode = CALLCHAIN_NONE;
1060 return 0;1059 return 0;
1061 }1060 }
1062 1061
@@ -1104,7 +1103,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) · 41 unmodified lines
1104 },1103 },
1105 .proc_map_timeout = 500,1104 .proc_map_timeout = 500,
1106 },1105 },
1107 .max_stack = PERF_MAX_STACK_DEPTH,1106 .max_stack = sysctl_perf_event_max_stack,
1108 .sym_pcnt_filter = 5,1107 .sym_pcnt_filter = 5,
1109 };1108 };
1110 struct record_opts *opts = &top.record_opts;1109 struct record_opts *opts = &top.record_opts;
@@ -1162,17 +1161,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) · 51 unmodified lines
1162 "output field(s): overhead, period, sample plus all of sort keys"),1161 "output field(s): overhead, period, sample plus all of sort keys"),
1163 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,1162 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1164 "Show a column with the number of samples"),1163 "Show a column with the number of samples"),
1165 OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts,1164 OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
1166 NULL, "enables call-graph recording and display",1165 NULL, "enables call-graph recording and display",
1167 &callchain_opt),1166 &callchain_opt),
1168 OPT_CALLBACK(0, "call-graph", &top.record_opts,1167 OPT_CALLBACK(0, "call-graph", &callchain_param,
1169 "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]",1168 "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]",
1170 top_callchain_help, &parse_callchain_opt),1169 top_callchain_help, &parse_callchain_opt),
1171 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,1170 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
1172 "Accumulate callchains of children and show total overhead as well"),1171 "Accumulate callchains of children and show total overhead as well"),
1173 OPT_INTEGER(0, "max-stack", &top.max_stack,1172 OPT_INTEGER(0, "max-stack", &top.max_stack,
1174 "Set the maximum stack depth when parsing the callchain. "1173 "Set the maximum stack depth when parsing the callchain. "
1175 "Default: " __stringify(PERF_MAX_STACK_DEPTH)),1174 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
1176 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",1175 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
1177 "ignore callees of these functions in call graphs",1176 "ignore callees of these functions in call graphs",
1178 report_parse_ignore_callees_opt),1177 report_parse_ignore_callees_opt),
@@ -1256,7 +1255,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) · 77 unmodified lines
1256 1255
1257 sort__mode = SORT_MODE__TOP;1256 sort__mode = SORT_MODE__TOP;
1258 /* display thread wants entries to be collapsed in a different tree */1257 /* display thread wants entries to be collapsed in a different tree */
1259 sort__need_collapse = 1;1258 perf_hpp_list.need_collapse = 1;
1260 1259
1261 if (top.use_stdio)1260 if (top.use_stdio)
1262 use_browser = 0;1261 use_browser = 0;
@@ -1312,7 +1311,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) · 49 unmodified lines
1312 1311
1313 top.sym_evsel = perf_evlist__first(top.evlist);1312 top.sym_evsel = perf_evlist__first(top.evlist);
1314 1313
1315 if (!symbol_conf.use_callchain) {1314 if (!callchain_param.enabled) {
1316 symbol_conf.cumulate_callchain = false;1315 symbol_conf.cumulate_callchain = false;
1317 perf_hpp__cancel_cumulate();1316 perf_hpp__cancel_cumulate();
1318 }1317 }
tools/perf/builtin-trace.c+416−669
@@ -34,79 +34,76 @@ · 33 unmodified lines
34#include "trace-event.h"34#include "trace-event.h"
35#include "util/parse-events.h"35#include "util/parse-events.h"
36#include "util/bpf-loader.h"36#include "util/bpf-loader.h"
37#include "callchain.h"
38#include "syscalltbl.h"
39#include "rb_resort.h"
37 40
38#include <libaudit.h>41#include <libaudit.h> /* FIXME: Still needed for audit_errno_to_name */
39#include <stdlib.h>42#include <stdlib.h>
40#include <sys/mman.h>
41#include <linux/futex.h>
42#include <linux/err.h>43#include <linux/err.h>
43 44#include <linux/filter.h>
44/* For older distros: */45#include <linux/audit.h>
45#ifndef MAP_STACK46#include <sys/ptrace.h>
46# define MAP_STACK 0x2000047#include <linux/random.h>
47#endif48#include <linux/stringify.h>
48
49#ifndef MADV_HWPOISON
50# define MADV_HWPOISON 100
51
52#endif
53
54#ifndef MADV_MERGEABLE
55# define MADV_MERGEABLE 12
56#endif
57
58#ifndef MADV_UNMERGEABLE
59# define MADV_UNMERGEABLE 13
60#endif
61
62#ifndef EFD_SEMAPHORE
63# define EFD_SEMAPHORE 1
64#endif
65
66#ifndef EFD_NONBLOCK
67# define EFD_NONBLOCK 00004000
68#endif
69
70#ifndef EFD_CLOEXEC
71# define EFD_CLOEXEC 02000000
72#endif
73 49
74#ifndef O_CLOEXEC50#ifndef O_CLOEXEC
75# define O_CLOEXEC 0200000051# define O_CLOEXEC 02000000
76#endif52#endif
77 53
78#ifndef SOCK_DCCP54struct trace {
79# define SOCK_DCCP 655 struct perf_tool tool;
80#endif56 struct syscalltbl *sctbl;
81 57 struct {
82#ifndef SOCK_CLOEXEC58 int max;
83# define SOCK_CLOEXEC 0200000059 struct syscall *table;
84#endif60 struct {
85 61 struct perf_evsel *sys_enter,
86#ifndef SOCK_NONBLOCK62 *sys_exit;
87# define SOCK_NONBLOCK 0000400063 } events;
88#endif64 } syscalls;
89 65 struct record_opts opts;
90#ifndef MSG_CMSG_CLOEXEC66 struct perf_evlist *evlist;
91# define MSG_CMSG_CLOEXEC 0x4000000067 struct machine *host;
92#endif68 struct thread *current;
93 69 u64 base_time;
94#ifndef PERF_FLAG_FD_NO_GROUP70 FILE *output;
95# define PERF_FLAG_FD_NO_GROUP (1UL << 0)71 unsigned long nr_events;
96#endif72 struct strlist *ev_qualifier;
97 73 struct {
98#ifndef PERF_FLAG_FD_OUTPUT74 size_t nr;
99# define PERF_FLAG_FD_OUTPUT (1UL << 1)75 int *entries;
100#endif76 } ev_qualifier_ids;
101 77 struct intlist *tid_list;
102#ifndef PERF_FLAG_PID_CGROUP78 struct intlist *pid_list;
103# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */79 struct {
104#endif80 size_t nr;
105 81 pid_t *entries;
106#ifndef PERF_FLAG_FD_CLOEXEC82 } filter_pids;
107# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */83 double duration_filter;
108#endif84 double runtime_ms;
109 85 struct {
86 u64 vfs_getname,
87 proc_getname;
88 } stats;
89 unsigned int max_stack;
90 unsigned int min_stack;
91 bool not_ev_qualifier;
92 bool live;
93 bool full_time;
94 bool sched;
95 bool multiple_threads;
96 bool summary;
97 bool summary_only;
98 bool show_comm;
99 bool show_tool_stats;
100 bool trace_syscalls;
101 bool kernel_syscallchains;
102 bool force;
103 bool vfs_getname;
104 int trace_pgfaults;
105 int open_id;
106};
110 107
111struct tp_field {108struct tp_field {
112 int offset;109 int offset;
@@ -371,221 +368,6 @@ static size_t syscall_arg__scnprintf_int(char *bf, size_t size, · 258 unmodified lines
371 368
372#define SCA_INT syscall_arg__scnprintf_int369#define SCA_INT syscall_arg__scnprintf_int
373 370
374static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
375 struct syscall_arg *arg)
376{
377 int printed = 0, prot = arg->val;
378
379 if (prot == PROT_NONE)
380 return scnprintf(bf, size, "NONE");
381#define P_MMAP_PROT(n) \
382 if (prot & PROT_##n) { \
383 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
384 prot &= ~PROT_##n; \
385 }
386
387 P_MMAP_PROT(EXEC);
388 P_MMAP_PROT(READ);
389 P_MMAP_PROT(WRITE);
390#ifdef PROT_SEM
391 P_MMAP_PROT(SEM);
392#endif
393 P_MMAP_PROT(GROWSDOWN);
394 P_MMAP_PROT(GROWSUP);
395#undef P_MMAP_PROT
396
397 if (prot)
398 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
399
400 return printed;
401}
402
403#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
404
405static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
406 struct syscall_arg *arg)
407{
408 int printed = 0, flags = arg->val;
409
410#define P_MMAP_FLAG(n) \
411 if (flags & MAP_##n) { \
412 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
413 flags &= ~MAP_##n; \
414 }
415
416 P_MMAP_FLAG(SHARED);
417 P_MMAP_FLAG(PRIVATE);
418#ifdef MAP_32BIT
419 P_MMAP_FLAG(32BIT);
420#endif
421 P_MMAP_FLAG(ANONYMOUS);
422 P_MMAP_FLAG(DENYWRITE);
423 P_MMAP_FLAG(EXECUTABLE);
424 P_MMAP_FLAG(FILE);
425 P_MMAP_FLAG(FIXED);
426 P_MMAP_FLAG(GROWSDOWN);
427#ifdef MAP_HUGETLB
428 P_MMAP_FLAG(HUGETLB);
429#endif
430 P_MMAP_FLAG(LOCKED);
431 P_MMAP_FLAG(NONBLOCK);
432 P_MMAP_FLAG(NORESERVE);
433 P_MMAP_FLAG(POPULATE);
434 P_MMAP_FLAG(STACK);
435#ifdef MAP_UNINITIALIZED
436 P_MMAP_FLAG(UNINITIALIZED);
437#endif
438#undef P_MMAP_FLAG
439
440 if (flags)
441 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
442
443 return printed;
444}
445
446#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
447
448static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
449 struct syscall_arg *arg)
450{
451 int printed = 0, flags = arg->val;
452
453#define P_MREMAP_FLAG(n) \
454 if (flags & MREMAP_##n) { \
455 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
456 flags &= ~MREMAP_##n; \
457 }
458
459 P_MREMAP_FLAG(MAYMOVE);
460#ifdef MREMAP_FIXED
461 P_MREMAP_FLAG(FIXED);
462#endif
463#undef P_MREMAP_FLAG
464
465 if (flags)
466 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
467
468 return printed;
469}
470
471#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
472
473static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
474 struct syscall_arg *arg)
475{
476 int behavior = arg->val;
477
478 switch (behavior) {
479#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
480 P_MADV_BHV(NORMAL);
481 P_MADV_BHV(RANDOM);
482 P_MADV_BHV(SEQUENTIAL);
483 P_MADV_BHV(WILLNEED);
484 P_MADV_BHV(DONTNEED);
485 P_MADV_BHV(REMOVE);
486 P_MADV_BHV(DONTFORK);
487 P_MADV_BHV(DOFORK);
488 P_MADV_BHV(HWPOISON);
489#ifdef MADV_SOFT_OFFLINE
490 P_MADV_BHV(SOFT_OFFLINE);
491#endif
492 P_MADV_BHV(MERGEABLE);
493 P_MADV_BHV(UNMERGEABLE);
494#ifdef MADV_HUGEPAGE
495 P_MADV_BHV(HUGEPAGE);
496#endif
497#ifdef MADV_NOHUGEPAGE
498 P_MADV_BHV(NOHUGEPAGE);
499#endif
500#ifdef MADV_DONTDUMP
501 P_MADV_BHV(DONTDUMP);
502#endif
503#ifdef MADV_DODUMP
504 P_MADV_BHV(DODUMP);
505#endif
506#undef P_MADV_PHV
507 default: break;
508 }
509
510 return scnprintf(bf, size, "%#x", behavior);
511}
512
513#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
514
515static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
516 struct syscall_arg *arg)
517{
518 int printed = 0, op = arg->val;
519
520 if (op == 0)
521 return scnprintf(bf, size, "NONE");
522#define P_CMD(cmd) \
523 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
524 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
525 op &= ~LOCK_##cmd; \
526 }
527
528 P_CMD(SH);
529 P_CMD(EX);
530 P_CMD(NB);
531 P_CMD(UN);
532 P_CMD(MAND);
533 P_CMD(RW);
534 P_CMD(READ);
535 P_CMD(WRITE);
536#undef P_OP
537
538 if (op)
539 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
540
541 return printed;
542}
543
544#define SCA_FLOCK syscall_arg__scnprintf_flock
545
546static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
547{
548 enum syscall_futex_args {
549 SCF_UADDR = (1 << 0),
550 SCF_OP = (1 << 1),
551 SCF_VAL = (1 << 2),
552 SCF_TIMEOUT = (1 << 3),
553 SCF_UADDR2 = (1 << 4),
554 SCF_VAL3 = (1 << 5),
555 };
556 int op = arg->val;
557 int cmd = op & FUTEX_CMD_MASK;
558 size_t printed = 0;
559
560 switch (cmd) {
561#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
562 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
563 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
564 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
565 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
566 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
567 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
568 P_FUTEX_OP(WAKE_OP); break;
569 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
570 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
571 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
572 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
573 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
574 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
575 default: printed = scnprintf(bf, size, "%#x", cmd); break;
576 }
577
578 if (op & FUTEX_PRIVATE_FLAG)
579 printed += scnprintf(bf + printed, size - printed, "|PRIV");
580
581 if (op & FUTEX_CLOCK_REALTIME)
582 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
583
584 return printed;
585}
586
587#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
588
589static const char *bpf_cmd[] = {371static const char *bpf_cmd[] = {
590 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",372 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
591 "MAP_GET_NEXT_KEY", "PROG_LOAD",373 "MAP_GET_NEXT_KEY", "PROG_LOAD",
@@ -652,110 +434,6 @@ static const char *socket_families[] = { · 60 unmodified lines
652};434};
653static DEFINE_STRARRAY(socket_families);435static DEFINE_STRARRAY(socket_families);
654 436
655#ifndef SOCK_TYPE_MASK
656#define SOCK_TYPE_MASK 0xf
657#endif
658
659static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size,
660 struct syscall_arg *arg)
661{
662 size_t printed;
663 int type = arg->val,
664 flags = type & ~SOCK_TYPE_MASK;
665
666 type &= SOCK_TYPE_MASK;
667 /*
668 * Can't use a strarray, MIPS may override for ABI reasons.
669 */
670 switch (type) {
671#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
672 P_SK_TYPE(STREAM);
673 P_SK_TYPE(DGRAM);
674 P_SK_TYPE(RAW);
675 P_SK_TYPE(RDM);
676 P_SK_TYPE(SEQPACKET);
677 P_SK_TYPE(DCCP);
678 P_SK_TYPE(PACKET);
679#undef P_SK_TYPE
680 default:
681 printed = scnprintf(bf, size, "%#x", type);
682 }
683
684#define P_SK_FLAG(n) \
685 if (flags & SOCK_##n) { \
686 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
687 flags &= ~SOCK_##n; \
688 }
689
690 P_SK_FLAG(CLOEXEC);
691 P_SK_FLAG(NONBLOCK);
692#undef P_SK_FLAG
693
694 if (flags)
695 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
696
697 return printed;
698}
699
700#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
701
702#ifndef MSG_PROBE
703#define MSG_PROBE 0x10
704#endif
705#ifndef MSG_WAITFORONE
706#define MSG_WAITFORONE 0x10000
707#endif
708#ifndef MSG_SENDPAGE_NOTLAST
709#define MSG_SENDPAGE_NOTLAST 0x20000
710#endif
711#ifndef MSG_FASTOPEN
712#define MSG_FASTOPEN 0x20000000
713#endif
714
715static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
716 struct syscall_arg *arg)
717{
718 int printed = 0, flags = arg->val;
719
720 if (flags == 0)
721 return scnprintf(bf, size, "NONE");
722#define P_MSG_FLAG(n) \
723 if (flags & MSG_##n) { \
724 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
725 flags &= ~MSG_##n; \
726 }
727
728 P_MSG_FLAG(OOB);
729 P_MSG_FLAG(PEEK);
730 P_MSG_FLAG(DONTROUTE);
731 P_MSG_FLAG(TRYHARD);
732 P_MSG_FLAG(CTRUNC);
733 P_MSG_FLAG(PROBE);
734 P_MSG_FLAG(TRUNC);
735 P_MSG_FLAG(DONTWAIT);
736 P_MSG_FLAG(EOR);
737 P_MSG_FLAG(WAITALL);
738 P_MSG_FLAG(FIN);
739 P_MSG_FLAG(SYN);
740 P_MSG_FLAG(CONFIRM);
741 P_MSG_FLAG(RST);
742 P_MSG_FLAG(ERRQUEUE);
743 P_MSG_FLAG(NOSIGNAL);
744 P_MSG_FLAG(MORE);
745 P_MSG_FLAG(WAITFORONE);
746 P_MSG_FLAG(SENDPAGE_NOTLAST);
747 P_MSG_FLAG(FASTOPEN);
748 P_MSG_FLAG(CMSG_CLOEXEC);
749#undef P_MSG_FLAG
750
751 if (flags)
752 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
753
754 return printed;
755}
756
757#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
758
759static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,437static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
760 struct syscall_arg *arg)438 struct syscall_arg *arg)
761{439{
@@ -788,116 +466,6 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size, · 26 unmodified lines
788 466
789#define SCA_FILENAME syscall_arg__scnprintf_filename467#define SCA_FILENAME syscall_arg__scnprintf_filename
790 468
791static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
792 struct syscall_arg *arg)
793{
794 int printed = 0, flags = arg->val;
795
796 if (!(flags & O_CREAT))
797 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
798
799 if (flags == 0)
800 return scnprintf(bf, size, "RDONLY");
801#define P_FLAG(n) \
802 if (flags & O_##n) { \
803 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
804 flags &= ~O_##n; \
805 }
806
807 P_FLAG(APPEND);
808 P_FLAG(ASYNC);
809 P_FLAG(CLOEXEC);
810 P_FLAG(CREAT);
811 P_FLAG(DIRECT);
812 P_FLAG(DIRECTORY);
813 P_FLAG(EXCL);
814 P_FLAG(LARGEFILE);
815 P_FLAG(NOATIME);
816 P_FLAG(NOCTTY);
817#ifdef O_NONBLOCK
818 P_FLAG(NONBLOCK);
819#elif O_NDELAY
820 P_FLAG(NDELAY);
821#endif
822#ifdef O_PATH
823 P_FLAG(PATH);
824#endif
825 P_FLAG(RDWR);
826#ifdef O_DSYNC
827 if ((flags & O_SYNC) == O_SYNC)
828 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
829 else {
830 P_FLAG(DSYNC);
831 }
832#else
833 P_FLAG(SYNC);
834#endif
835 P_FLAG(TRUNC);
836 P_FLAG(WRONLY);
837#undef P_FLAG
838
839 if (flags)
840 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
841
842 return printed;
843}
844
845#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
846
847static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
848 struct syscall_arg *arg)
849{
850 int printed = 0, flags = arg->val;
851
852 if (flags == 0)
853 return 0;
854
855#define P_FLAG(n) \
856 if (flags & PERF_FLAG_##n) { \
857 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
858 flags &= ~PERF_FLAG_##n; \
859 }
860
861 P_FLAG(FD_NO_GROUP);
862 P_FLAG(FD_OUTPUT);
863 P_FLAG(PID_CGROUP);
864 P_FLAG(FD_CLOEXEC);
865#undef P_FLAG
866
867 if (flags)
868 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
869
870 return printed;
871}
872
873#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
874
875static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size,
876 struct syscall_arg *arg)
877{
878 int printed = 0, flags = arg->val;
879
880 if (flags == 0)
881 return scnprintf(bf, size, "NONE");
882#define P_FLAG(n) \
883 if (flags & EFD_##n) { \
884 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
885 flags &= ~EFD_##n; \
886 }
887
888 P_FLAG(SEMAPHORE);
889 P_FLAG(CLOEXEC);
890 P_FLAG(NONBLOCK);
891#undef P_FLAG
892
893 if (flags)
894 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
895
896 return printed;
897}
898
899#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
900
901static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,469static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
902 struct syscall_arg *arg)470 struct syscall_arg *arg)
903{471{
@@ -921,59 +489,6 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size, · 17 unmodified lines
921 489
922#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags490#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
923 491
924static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
925{
926 int sig = arg->val;
927
928 switch (sig) {
929#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
930 P_SIGNUM(HUP);
931 P_SIGNUM(INT);
932 P_SIGNUM(QUIT);
933 P_SIGNUM(ILL);
934 P_SIGNUM(TRAP);
935 P_SIGNUM(ABRT);
936 P_SIGNUM(BUS);
937 P_SIGNUM(FPE);
938 P_SIGNUM(KILL);
939 P_SIGNUM(USR1);
940 P_SIGNUM(SEGV);
941 P_SIGNUM(USR2);
942 P_SIGNUM(PIPE);
943 P_SIGNUM(ALRM);
944 P_SIGNUM(TERM);
945 P_SIGNUM(CHLD);
946 P_SIGNUM(CONT);
947 P_SIGNUM(STOP);
948 P_SIGNUM(TSTP);
949 P_SIGNUM(TTIN);
950 P_SIGNUM(TTOU);
951 P_SIGNUM(URG);
952 P_SIGNUM(XCPU);
953 P_SIGNUM(XFSZ);
954 P_SIGNUM(VTALRM);
955 P_SIGNUM(PROF);
956 P_SIGNUM(WINCH);
957 P_SIGNUM(IO);
958 P_SIGNUM(PWR);
959 P_SIGNUM(SYS);
960#ifdef SIGEMT
961 P_SIGNUM(EMT);
962#endif
963#ifdef SIGSTKFLT
964 P_SIGNUM(STKFLT);
965#endif
966#ifdef SIGSWI
967 P_SIGNUM(SWI);
968#endif
969 default: break;
970 }
971
972 return scnprintf(bf, size, "%#x", sig);
973}
974
975#define SCA_SIGNUM syscall_arg__scnprintf_signum
976
977#if defined(__i386__) || defined(__x86_64__)492#if defined(__i386__) || defined(__x86_64__)
978/*493/*
979 * FIXME: Make this available to all arches.494 * FIXME: Make this available to all arches.
@@ -1001,16 +516,62 @@ static const char *tioctls[] = { · 21 unmodified lines
1001static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);516static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
1002#endif /* defined(__i386__) || defined(__x86_64__) */517#endif /* defined(__i386__) || defined(__x86_64__) */
1003 518
519#ifndef GRND_NONBLOCK
520#define GRND_NONBLOCK 0x0001
521#endif
522#ifndef GRND_RANDOM
523#define GRND_RANDOM 0x0002
524#endif
525
526static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
527 struct syscall_arg *arg)
528{
529 int printed = 0, flags = arg->val;
530
531#define P_FLAG(n) \
532 if (flags & GRND_##n) { \
533 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
534 flags &= ~GRND_##n; \
535 }
536
537 P_FLAG(RANDOM);
538 P_FLAG(NONBLOCK);
539#undef P_FLAG
540
541 if (flags)
542 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
543
544 return printed;
545}
546
547#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
548
1004#define STRARRAY(arg, name, array) \549#define STRARRAY(arg, name, array) \
1005 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \550 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
1006 .arg_parm = { [arg] = &strarray__##array, }551 .arg_parm = { [arg] = &strarray__##array, }
1007 552
553#include "trace/beauty/eventfd.c"
554#include "trace/beauty/flock.c"
555#include "trace/beauty/futex_op.c"
556#include "trace/beauty/mmap.c"
557#include "trace/beauty/mode_t.c"
558#include "trace/beauty/msg_flags.c"
559#include "trace/beauty/open_flags.c"
560#include "trace/beauty/perf_event_open.c"
561#include "trace/beauty/pid.c"
562#include "trace/beauty/sched_policy.c"
563#include "trace/beauty/seccomp.c"
564#include "trace/beauty/signum.c"
565#include "trace/beauty/socket_type.c"
566#include "trace/beauty/waitid_options.c"
567
1008static struct syscall_fmt {568static struct syscall_fmt {
1009 const char *name;569 const char *name;
1010 const char *alias;570 const char *alias;
1011 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);571 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1012 void *arg_parm[6];572 void *arg_parm[6];
1013 bool errmsg;573 bool errmsg;
574 bool errpid;
1014 bool timeout;575 bool timeout;
1015 bool hexret;576 bool hexret;
1016} syscall_fmts[] = {577} syscall_fmts[] = {
@@ -1028,6 +589,7 @@ static struct syscall_fmt { · 11 unmodified lines
1028 { .name = "chroot", .errmsg = true,589 { .name = "chroot", .errmsg = true,
1029 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },590 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1030 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },591 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
592 { .name = "clone", .errpid = true, },
1031 { .name = "close", .errmsg = true,593 { .name = "close", .errmsg = true,
1032 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },594 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
1033 { .name = "connect", .errmsg = true, },595 { .name = "connect", .errmsg = true, },
@@ -1093,6 +655,11 @@ static struct syscall_fmt { · 59 unmodified lines
1093 { .name = "getdents64", .errmsg = true,655 { .name = "getdents64", .errmsg = true,
1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },656 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1095 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },657 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
658 { .name = "getpid", .errpid = true, },
659 { .name = "getpgid", .errpid = true, },
660 { .name = "getppid", .errpid = true, },
661 { .name = "getrandom", .errmsg = true,
662 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
1096 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },663 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1097 { .name = "getxattr", .errmsg = true,664 { .name = "getxattr", .errmsg = true,
1098 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },665 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
@@ -1186,8 +753,7 @@ static struct syscall_fmt { · 87 unmodified lines
1186 [1] = SCA_FILENAME, /* filename */753 [1] = SCA_FILENAME, /* filename */
1187 [2] = SCA_OPEN_FLAGS, /* flags */ }, },754 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1188 { .name = "perf_event_open", .errmsg = true,755 { .name = "perf_event_open", .errmsg = true,
1189 .arg_scnprintf = { [1] = SCA_INT, /* pid */756 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
1190 [2] = SCA_INT, /* cpu */
1191 [3] = SCA_FD, /* group_fd */757 [3] = SCA_FD, /* group_fd */
1192 [4] = SCA_PERF_FLAGS, /* flags */ }, },758 [4] = SCA_PERF_FLAGS, /* flags */ }, },
1193 { .name = "pipe2", .errmsg = true,759 { .name = "pipe2", .errmsg = true,
@@ -1234,6 +800,11 @@ static struct syscall_fmt { · 40 unmodified lines
1234 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },800 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1235 { .name = "rt_tgsigqueueinfo", .errmsg = true,801 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1236 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },802 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
803 { .name = "sched_setscheduler", .errmsg = true,
804 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
805 { .name = "seccomp", .errmsg = true,
806 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
807 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
1237 { .name = "select", .errmsg = true, .timeout = true, },808 { .name = "select", .errmsg = true, .timeout = true, },
1238 { .name = "sendmmsg", .errmsg = true,809 { .name = "sendmmsg", .errmsg = true,
1239 .arg_scnprintf = { [0] = SCA_FD, /* fd */810 .arg_scnprintf = { [0] = SCA_FD, /* fd */
@@ -1244,7 +815,9 @@ static struct syscall_fmt { · 4 unmodified lines
1244 { .name = "sendto", .errmsg = true,815 { .name = "sendto", .errmsg = true,
1245 .arg_scnprintf = { [0] = SCA_FD, /* fd */816 .arg_scnprintf = { [0] = SCA_FD, /* fd */
1246 [3] = SCA_MSG_FLAGS, /* flags */ }, },817 [3] = SCA_MSG_FLAGS, /* flags */ }, },
818 { .name = "set_tid_address", .errpid = true, },
1247 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },819 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
820 { .name = "setpgid", .errmsg = true, },
1248 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },821 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1249 { .name = "setxattr", .errmsg = true,822 { .name = "setxattr", .errmsg = true,
1250 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },823 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
@@ -1287,6 +860,10 @@ static struct syscall_fmt { · 36 unmodified lines
1287 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },860 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1288 { .name = "vmsplice", .errmsg = true,861 { .name = "vmsplice", .errmsg = true,
1289 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },862 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
863 { .name = "wait4", .errpid = true,
864 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
865 { .name = "waitid", .errpid = true,
866 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
1290 { .name = "write", .errmsg = true,867 { .name = "write", .errmsg = true,
1291 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },868 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1292 { .name = "writev", .errmsg = true,869 { .name = "writev", .errmsg = true,
@@ -1398,59 +975,6 @@ fail: · 105 unmodified lines
1398 975
1399static const size_t trace__entry_str_size = 2048;976static const size_t trace__entry_str_size = 2048;
1400 977
1401struct trace {
1402 struct perf_tool tool;
1403 struct {
1404 int machine;
1405 int open_id;
1406 } audit;
1407 struct {
1408 int max;
1409 struct syscall *table;
1410 struct {
1411 struct perf_evsel *sys_enter,
1412 *sys_exit;
1413 } events;
1414 } syscalls;
1415 struct record_opts opts;
1416 struct perf_evlist *evlist;
1417 struct machine *host;
1418 struct thread *current;
1419 u64 base_time;
1420 FILE *output;
1421 unsigned long nr_events;
1422 struct strlist *ev_qualifier;
1423 struct {
1424 size_t nr;
1425 int *entries;
1426 } ev_qualifier_ids;
1427 struct intlist *tid_list;
1428 struct intlist *pid_list;
1429 struct {
1430 size_t nr;
1431 pid_t *entries;
1432 } filter_pids;
1433 double duration_filter;
1434 double runtime_ms;
1435 struct {
1436 u64 vfs_getname,
1437 proc_getname;
1438 } stats;
1439 bool not_ev_qualifier;
1440 bool live;
1441 bool full_time;
1442 bool sched;
1443 bool multiple_threads;
1444 bool summary;
1445 bool summary_only;
1446 bool show_comm;
1447 bool show_tool_stats;
1448 bool trace_syscalls;
1449 bool force;
1450 bool vfs_getname;
1451 int trace_pgfaults;
1452};
1453
1454static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)978static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1455{979{
1456 struct thread_trace *ttrace = thread__priv(thread);980 struct thread_trace *ttrace = thread__priv(thread);
@@ -1618,6 +1142,7 @@ static int trace__process_event(struct trace *trace, struct machine *machine, · 161 unmodified lines
1618 color_fprintf(trace->output, PERF_COLOR_RED,1142 color_fprintf(trace->output, PERF_COLOR_RED,
1619 "LOST %" PRIu64 " events!\n", event->lost.lost);1143 "LOST %" PRIu64 " events!\n", event->lost.lost);
1620 ret = machine__process_lost_event(machine, event, sample);1144 ret = machine__process_lost_event(machine, event, sample);
1145 break;
1621 default:1146 default:
1622 ret = machine__process_event(machine, event, sample);1147 ret = machine__process_event(machine, event, sample);
1623 break;1148 break;
@@ -1675,6 +1200,10 @@ static int syscall__set_arg_fmts(struct syscall *sc) · 51 unmodified lines
1675 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];1200 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1676 else if (field->flags & FIELD_IS_POINTER)1201 else if (field->flags & FIELD_IS_POINTER)
1677 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;1202 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1203 else if (strcmp(field->type, "pid_t") == 0)
1204 sc->arg_scnprintf[idx] = SCA_PID;
1205 else if (strcmp(field->type, "umode_t") == 0)
1206 sc->arg_scnprintf[idx] = SCA_MODE_T;
1678 ++idx;1207 ++idx;
1679 }1208 }
1680 1209
@@ -1685,7 +1214,7 @@ static int trace__read_syscall_info(struct trace *trace, int id) · 4 unmodified lines
1685{1214{
1686 char tp_name[128];1215 char tp_name[128];
1687 struct syscall *sc;1216 struct syscall *sc;
1688 const char *name = audit_syscall_to_name(id, trace->audit.machine);1217 const char *name = syscalltbl__name(trace->sctbl, id);
1689 1218
1690 if (name == NULL)1219 if (name == NULL)
1691 return -1;1220 return -1;
@@ -1760,7 +1289,7 @@ static int trace__validate_ev_qualifier(struct trace *trace) · 68 unmodified lines
1760 1289
1761 strlist__for_each(pos, trace->ev_qualifier) {1290 strlist__for_each(pos, trace->ev_qualifier) {
1762 const char *sc = pos->s;1291 const char *sc = pos->s;
1763 int id = audit_name_to_syscall(sc, trace->audit.machine);1292 int id = syscalltbl__id(trace->sctbl, sc);
1764 1293
1765 if (id < 0) {1294 if (id < 0) {
1766 if (err == 0) {1295 if (err == 0) {
@@ -1846,7 +1375,12 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size, · 79 unmodified lines
1846 "%ld", val);1375 "%ld", val);
1847 }1376 }
1848 }1377 }
1849 } else {1378 } else if (IS_ERR(sc->tp_format)) {
1379 /*
1380 * If we managed to read the tracepoint /format file, then we
1381 * may end up not having any args, like with gettid(), so only
1382 * print the raw args when we didn't manage to read it.
1383 */
1850 int i = 0;1384 int i = 0;
1851 1385
1852 while (i < 6) {1386 while (i < 6) {
@@ -1987,7 +1521,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, · 134 unmodified lines
1987 goto out_put;1521 goto out_put;
1988 }1522 }
1989 1523
1990 if (!trace->summary_only)1524 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
1991 trace__printf_interrupted_entry(trace, sample);1525 trace__printf_interrupted_entry(trace, sample);
1992 1526
1993 ttrace->entry_time = sample->time;1527 ttrace->entry_time = sample->time;
@@ -1998,7 +1532,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel, · 4 unmodified lines
1998 args, trace, thread);1532 args, trace, thread);
1999 1533
2000 if (sc->is_exit) {1534 if (sc->is_exit) {
2001 if (!trace->duration_filter && !trace->summary_only) {1535 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
2002 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);1536 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
2003 fprintf(trace->output, "%-70s\n", ttrace->entry_str);1537 fprintf(trace->output, "%-70s\n", ttrace->entry_str);
2004 }1538 }
@@ -2018,6 +1552,29 @@ out_put: · 13 unmodified lines
2018 return err;1552 return err;
2019}1553}
2020 1554
1555static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1556 struct perf_sample *sample,
1557 struct callchain_cursor *cursor)
1558{
1559 struct addr_location al;
1560
1561 if (machine__resolve(trace->host, &al, sample) < 0 ||
1562 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1563 return -1;
1564
1565 return 0;
1566}
1567
1568static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1569{
1570 /* TODO: user-configurable print_opts */
1571 const unsigned int print_opts = EVSEL__PRINT_SYM |
1572 EVSEL__PRINT_DSO |
1573 EVSEL__PRINT_UNKNOWN_AS_ADDR;
1574
1575 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
1576}
1577
2021static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,1578static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2022 union perf_event *event __maybe_unused,1579 union perf_event *event __maybe_unused,
2023 struct perf_sample *sample)1580 struct perf_sample *sample)
@@ -2025,7 +1582,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, · 1 unmodified line
2025 long ret;1582 long ret;
2026 u64 duration = 0;1583 u64 duration = 0;
2027 struct thread *thread;1584 struct thread *thread;
2028 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1;1585 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1, callchain_ret = 0;
2029 struct syscall *sc = trace__syscall_info(trace, evsel, id);1586 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2030 struct thread_trace *ttrace;1587 struct thread_trace *ttrace;
2031 1588
@@ -2042,7 +1599,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, · 10 unmodified lines
2042 1599
2043 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);1600 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
2044 1601
2045 if (id == trace->audit.open_id && ret >= 0 && ttrace->filename.pending_open) {1602 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
2046 trace__set_fd_pathname(thread, ret, ttrace->filename.name);1603 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
2047 ttrace->filename.pending_open = false;1604 ttrace->filename.pending_open = false;
2048 ++trace->stats.vfs_getname;1605 ++trace->stats.vfs_getname;
@@ -2057,6 +1614,15 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, · 8 unmodified lines
2057 } else if (trace->duration_filter)1614 } else if (trace->duration_filter)
2058 goto out;1615 goto out;
2059 1616
1617 if (sample->callchain) {
1618 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1619 if (callchain_ret == 0) {
1620 if (callchain_cursor.nr < trace->min_stack)
1621 goto out;
1622 callchain_ret = 1;
1623 }
1624 }
1625
2060 if (trace->summary_only)1626 if (trace->summary_only)
2061 goto out;1627 goto out;
2062 1628
@@ -2073,7 +1639,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, · 10 unmodified lines
2073 if (sc->fmt == NULL) {1639 if (sc->fmt == NULL) {
2074signed_print:1640signed_print:
2075 fprintf(trace->output, ") = %ld", ret);1641 fprintf(trace->output, ") = %ld", ret);
2076 } else if (ret < 0 && sc->fmt->errmsg) {1642 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
2077 char bf[STRERR_BUFSIZE];1643 char bf[STRERR_BUFSIZE];
2078 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),1644 const char *emsg = strerror_r(-ret, bf, sizeof(bf)),
2079 *e = audit_errno_to_name(-ret);1645 *e = audit_errno_to_name(-ret);
@@ -2083,10 +1649,24 @@ signed_print: · 3 unmodified lines
2083 fprintf(trace->output, ") = 0 Timeout");1649 fprintf(trace->output, ") = 0 Timeout");
2084 else if (sc->fmt->hexret)1650 else if (sc->fmt->hexret)
2085 fprintf(trace->output, ") = %#lx", ret);1651 fprintf(trace->output, ") = %#lx", ret);
2086 else1652 else if (sc->fmt->errpid) {
1653 struct thread *child = machine__find_thread(trace->host, ret, ret);
1654
1655 if (child != NULL) {
1656 fprintf(trace->output, ") = %ld", ret);
1657 if (child->comm_set)
1658 fprintf(trace->output, " (%s)", thread__comm_str(child));
1659 thread__put(child);
1660 }
1661 } else
2087 goto signed_print;1662 goto signed_print;
2088 1663
2089 fputc('\n', trace->output);1664 fputc('\n', trace->output);
1665
1666 if (callchain_ret > 0)
1667 trace__fprintf_callchain(trace, sample);
1668 else if (callchain_ret < 0)
1669 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2090out:1670out:
2091 ttrace->entry_pending = false;1671 ttrace->entry_pending = false;
2092 err = 0;1672 err = 0;
@@ -2217,6 +1797,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, · 124 unmodified lines
2217 union perf_event *event __maybe_unused,1797 union perf_event *event __maybe_unused,
2218 struct perf_sample *sample)1798 struct perf_sample *sample)
2219{1799{
1800 int callchain_ret = 0;
1801
1802 if (sample->callchain) {
1803 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1804 if (callchain_ret == 0) {
1805 if (callchain_cursor.nr < trace->min_stack)
1806 goto out;
1807 callchain_ret = 1;
1808 }
1809 }
1810
2220 trace__printf_interrupted_entry(trace, sample);1811 trace__printf_interrupted_entry(trace, sample);
2221 trace__fprintf_tstamp(trace, sample->time, trace->output);1812 trace__fprintf_tstamp(trace, sample->time, trace->output);
2222 1813
@@ -2234,6 +1825,12 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel, · 11 unmodified lines
2234 }1825 }
2235 1826
2236 fprintf(trace->output, ")\n");1827 fprintf(trace->output, ")\n");
1828
1829 if (callchain_ret > 0)
1830 trace__fprintf_callchain(trace, sample);
1831 else if (callchain_ret < 0)
1832 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
1833out:
2237 return 0;1834 return 0;
2238}1835}
2239 1836
@@ -2264,8 +1861,19 @@ static int trace__pgfault(struct trace *trace, · 24 unmodified lines
2264 char map_type = 'd';1861 char map_type = 'd';
2265 struct thread_trace *ttrace;1862 struct thread_trace *ttrace;
2266 int err = -1;1863 int err = -1;
1864 int callchain_ret = 0;
2267 1865
2268 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);1866 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1867
1868 if (sample->callchain) {
1869 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1870 if (callchain_ret == 0) {
1871 if (callchain_cursor.nr < trace->min_stack)
1872 goto out_put;
1873 callchain_ret = 1;
1874 }
1875 }
1876
2269 ttrace = thread__trace(thread, trace->output);1877 ttrace = thread__trace(thread, trace->output);
2270 if (ttrace == NULL)1878 if (ttrace == NULL)
2271 goto out_put;1879 goto out_put;
@@ -2307,6 +1915,11 @@ static int trace__pgfault(struct trace *trace, · 35 unmodified lines
2307 print_location(trace->output, sample, &al, true, false);1915 print_location(trace->output, sample, &al, true, false);
2308 1916
2309 fprintf(trace->output, " (%c%c)\n", map_type, al.level);1917 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
1918
1919 if (callchain_ret > 0)
1920 trace__fprintf_callchain(trace, sample);
1921 else if (callchain_ret < 0)
1922 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2310out:1923out:
2311 err = 0;1924 err = 0;
2312out_put:1925out_put:
@@ -2326,6 +1939,23 @@ static bool skip_sample(struct trace *trace, struct perf_sample *sample) · 13 unmodified lines
2326 return false;1939 return false;
2327}1940}
2328 1941
1942static void trace__set_base_time(struct trace *trace,
1943 struct perf_evsel *evsel,
1944 struct perf_sample *sample)
1945{
1946 /*
1947 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
1948 * and don't use sample->time unconditionally, we may end up having
1949 * some other event in the future without PERF_SAMPLE_TIME for good
1950 * reason, i.e. we may not be interested in its timestamps, just in
1951 * it taking place, picking some piece of information when it
1952 * appears in our event stream (vfs_getname comes to mind).
1953 */
1954 if (trace->base_time == 0 && !trace->full_time &&
1955 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
1956 trace->base_time = sample->time;
1957}
1958
2329static int trace__process_sample(struct perf_tool *tool,1959static int trace__process_sample(struct perf_tool *tool,
2330 union perf_event *event,1960 union perf_event *event,
2331 struct perf_sample *sample,1961 struct perf_sample *sample,
@@ -2340,8 +1970,7 @@ static int trace__process_sample(struct perf_tool *tool, · 8 unmodified lines
2340 if (skip_sample(trace, sample))1970 if (skip_sample(trace, sample))
2341 return 0;1971 return 0;
2342 1972
2343 if (!trace->full_time && trace->base_time == 0)1973 trace__set_base_time(trace, evsel, sample);
2344 trace->base_time = sample->time;
2345 1974
2346 if (handler) {1975 if (handler) {
2347 ++trace->nr_events;1976 ++trace->nr_events;
@@ -2450,8 +2079,7 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist) · 102 unmodified lines
2450 return true;2079 return true;
2451}2080}
2452 2081
2453static int perf_evlist__add_pgfault(struct perf_evlist *evlist,2082static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
2454 u64 config)
2455{2083{
2456 struct perf_evsel *evsel;2084 struct perf_evsel *evsel;
2457 struct perf_event_attr attr = {2085 struct perf_event_attr attr = {
@@ -2465,13 +2093,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist, · 7 unmodified lines
2465 event_attr_init(&attr);2093 event_attr_init(&attr);
2466 2094
2467 evsel = perf_evsel__new(&attr);2095 evsel = perf_evsel__new(&attr);
2468 if (!evsel)2096 if (evsel)
2469 return -ENOMEM;2097 evsel->handler = trace__pgfault;
2470
2471 evsel->handler = trace__pgfault;
2472 perf_evlist__add(evlist, evsel);
2473 2098
2474 return 0;2099 return evsel;
2475}2100}
2476 2101
2477static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)2102static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
@@ -2479,9 +2104,6 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st · 1 unmodified line
2479 const u32 type = event->header.type;2104 const u32 type = event->header.type;
2480 struct perf_evsel *evsel;2105 struct perf_evsel *evsel;
2481 2106
2482 if (!trace->full_time && trace->base_time == 0)
2483 trace->base_time = sample->time;
2484
2485 if (type != PERF_RECORD_SAMPLE) {2107 if (type != PERF_RECORD_SAMPLE) {
2486 trace__process_event(trace, trace->host, event, sample);2108 trace__process_event(trace, trace->host, event, sample);
2487 return;2109 return;
@@ -2493,6 +2115,8 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st · 5 unmodified lines
2493 return;2115 return;
2494 }2116 }
2495 2117
2118 trace__set_base_time(trace, evsel, sample);
2119
2496 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&2120 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2497 sample->raw_data == NULL) {2121 sample->raw_data == NULL) {
2498 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",2122 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
@@ -2527,6 +2151,15 @@ static int trace__add_syscall_newtp(struct trace *trace) · 28 unmodified lines
2527 perf_evlist__add(evlist, sys_enter);2151 perf_evlist__add(evlist, sys_enter);
2528 perf_evlist__add(evlist, sys_exit);2152 perf_evlist__add(evlist, sys_exit);
2529 2153
2154 if (callchain_param.enabled && !trace->kernel_syscallchains) {
2155 /*
2156 * We're interested only in the user space callchain
2157 * leading to the syscall, allow overriding that for
2158 * debugging reasons using --kernel_syscall_callchains
2159 */
2160 sys_exit->attr.exclude_callchain_kernel = 1;
2161 }
2162
2530 trace->syscalls.events.sys_enter = sys_enter;2163 trace->syscalls.events.sys_enter = sys_enter;
2531 trace->syscalls.events.sys_exit = sys_exit;2164 trace->syscalls.events.sys_exit = sys_exit;
2532 2165
@@ -2565,7 +2198,7 @@ out_enomem: · 32 unmodified lines
2565static int trace__run(struct trace *trace, int argc, const char **argv)2198static int trace__run(struct trace *trace, int argc, const char **argv)
2566{2199{
2567 struct perf_evlist *evlist = trace->evlist;2200 struct perf_evlist *evlist = trace->evlist;
2568 struct perf_evsel *evsel;2201 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
2569 int err = -1, i;2202 int err = -1, i;
2570 unsigned long before;2203 unsigned long before;
2571 const bool forks = argc > 0;2204 const bool forks = argc > 0;
@@ -2579,14 +2212,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv) · 7 unmodified lines
2579 if (trace->trace_syscalls)2212 if (trace->trace_syscalls)
2580 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);2213 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
2581 2214
2582 if ((trace->trace_pgfaults & TRACE_PFMAJ) &&2215 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2583 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) {2216 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2584 goto out_error_mem;2217 if (pgfault_maj == NULL)
2218 goto out_error_mem;
2219 perf_evlist__add(evlist, pgfault_maj);
2585 }2220 }
2586 2221
2587 if ((trace->trace_pgfaults & TRACE_PFMIN) &&2222 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2588 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN))2223 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2589 goto out_error_mem;2224 if (pgfault_min == NULL)
2225 goto out_error_mem;
2226 perf_evlist__add(evlist, pgfault_min);
2227 }
2590 2228
2591 if (trace->sched &&2229 if (trace->sched &&
2592 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",2230 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
@@ -2605,7 +2243,45 @@ static int trace__run(struct trace *trace, int argc, const char **argv) · 12 unmodified lines
2605 goto out_delete_evlist;2243 goto out_delete_evlist;
2606 }2244 }
2607 2245
2608 perf_evlist__config(evlist, &trace->opts);2246 perf_evlist__config(evlist, &trace->opts, NULL);
2247
2248 if (callchain_param.enabled) {
2249 bool use_identifier = false;
2250
2251 if (trace->syscalls.events.sys_exit) {
2252 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2253 &trace->opts, &callchain_param);
2254 use_identifier = true;
2255 }
2256
2257 if (pgfault_maj) {
2258 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2259 use_identifier = true;
2260 }
2261
2262 if (pgfault_min) {
2263 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2264 use_identifier = true;
2265 }
2266
2267 if (use_identifier) {
2268 /*
2269 * Now we have evsels with different sample_ids, use
2270 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2271 * from a fixed position in each ring buffer record.
2272 *
2273 * As of this the changeset introducing this comment, this
2274 * isn't strictly needed, as the fields that can come before
2275 * PERF_SAMPLE_ID are all used, but we'll probably disable
2276 * some of those for things like copying the payload of
2277 * pointer syscall arguments, and for vfs_getname we don't
2278 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2279 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2280 */
2281 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2282 perf_evlist__reset_sample_bit(evlist, ID);
2283 }
2284 }
2609 2285
2610 signal(SIGCHLD, sig_handler);2286 signal(SIGCHLD, sig_handler);
2611 signal(SIGINT, sig_handler);2287 signal(SIGINT, sig_handler);
@@ -2883,15 +2559,29 @@ static size_t trace__fprintf_threads_header(FILE *fp) · 271 unmodified lines
2883 return printed;2559 return printed;
2884}2560}
2885 2561
2562DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2563 struct stats *stats;
2564 double msecs;
2565 int syscall;
2566)
2567{
2568 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2569 struct stats *stats = source->priv;
2570
2571 entry->syscall = source->i;
2572 entry->stats = stats;
2573 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2574}
2575
2886static size_t thread__dump_stats(struct thread_trace *ttrace,2576static size_t thread__dump_stats(struct thread_trace *ttrace,
2887 struct trace *trace, FILE *fp)2577 struct trace *trace, FILE *fp)
2888{2578{
2889 struct stats *stats;
2890 size_t printed = 0;2579 size_t printed = 0;
2891 struct syscall *sc;2580 struct syscall *sc;
2892 struct int_node *inode = intlist__first(ttrace->syscall_stats);2581 struct rb_node *nd;
2582 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
2893 2583
2894 if (inode == NULL)2584 if (syscall_stats == NULL)
2895 return 0;2585 return 0;
2896 2586
2897 printed += fprintf(fp, "\n");2587 printed += fprintf(fp, "\n");
@@ -2900,9 +2590,8 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, · 2 unmodified lines
2900 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");2590 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2901 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");2591 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
2902 2592
2903 /* each int_node is a syscall */2593 resort_rb__for_each(nd, syscall_stats) {
2904 while (inode) {2594 struct stats *stats = syscall_stats_entry->stats;
2905 stats = inode->priv;
2906 if (stats) {2595 if (stats) {
2907 double min = (double)(stats->min) / NSEC_PER_MSEC;2596 double min = (double)(stats->min) / NSEC_PER_MSEC;
2908 double max = (double)(stats->max) / NSEC_PER_MSEC;2597 double max = (double)(stats->max) / NSEC_PER_MSEC;
@@ -2913,34 +2602,23 @@ static size_t thread__dump_stats(struct thread_trace *ttrace, · 4 unmodified lines
2913 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;2602 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2914 avg /= NSEC_PER_MSEC;2603 avg /= NSEC_PER_MSEC;
2915 2604
2916 sc = &trace->syscalls.table[inode->i];2605 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
2917 printed += fprintf(fp, " %-15s", sc->name);2606 printed += fprintf(fp, " %-15s", sc->name);
2918 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",2607 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2919 n, avg * n, min, avg);2608 n, syscall_stats_entry->msecs, min, avg);
2920 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);2609 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
2921 }2610 }
2922
2923 inode = intlist__next(inode);
2924 }2611 }
2925 2612
2613 resort_rb__delete(syscall_stats);
2926 printed += fprintf(fp, "\n\n");2614 printed += fprintf(fp, "\n\n");
2927 2615
2928 return printed;2616 return printed;
2929}2617}
2930 2618
2931/* struct used to pass data to per-thread function */2619static size_t trace__fprintf_thread(FILE *fp, struct thread *thread, struct trace *trace)
2932struct summary_data {
2933 FILE *fp;
2934 struct trace *trace;
2935 size_t printed;
2936};
2937
2938static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2939{2620{
2940 struct summary_data *data = priv;2621 size_t printed = 0;
2941 FILE *fp = data->fp;
2942 size_t printed = data->printed;
2943 struct trace *trace = data->trace;
2944 struct thread_trace *ttrace = thread__priv(thread);2622 struct thread_trace *ttrace = thread__priv(thread);
2945 double ratio;2623 double ratio;
2946 2624
@@ -2956,25 +2634,45 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv) · 9 unmodified lines
2956 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);2634 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2957 if (ttrace->pfmin)2635 if (ttrace->pfmin)
2958 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);2636 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
2959 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);2637 if (trace->sched)
2638 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2639 else if (fputc('\n', fp) != EOF)
2640 ++printed;
2641
2960 printed += thread__dump_stats(ttrace, trace, fp);2642 printed += thread__dump_stats(ttrace, trace, fp);
2961 2643
2962 data->printed += printed;2644 return printed;
2645}
2963 2646
2964 return 0;2647static unsigned long thread__nr_events(struct thread_trace *ttrace)
2648{
2649 return ttrace ? ttrace->nr_events : 0;
2650}
2651
2652DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2653 struct thread *thread;
2654)
2655{
2656 entry->thread = rb_entry(nd, struct thread, rb_node);
2965}2657}
2966 2658
2967static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)2659static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2968{2660{
2969 struct summary_data data = {2661 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2970 .fp = fp,2662 size_t printed = trace__fprintf_threads_header(fp);
2971 .trace = trace2663 struct rb_node *nd;
2972 };2664
2973 data.printed = trace__fprintf_threads_header(fp);2665 if (threads == NULL) {
2666 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2667 return 0;
2668 }
2974 2669
2975 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data);2670 resort_rb__for_each(nd, threads)
2671 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2976 2672
2977 return data.printed;2673 resort_rb__delete(threads);
2674
2675 return printed;
2978}2676}
2979 2677
2980static int trace__set_duration(const struct option *opt, const char *str,2678static int trace__set_duration(const struct option *opt, const char *str,
@@ -3070,10 +2768,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) · 89 unmodified lines
3070 NULL2768 NULL
3071 };2769 };
3072 struct trace trace = {2770 struct trace trace = {
3073 .audit = {
3074 .machine = audit_detect_machine(),
3075 .open_id = audit_name_to_syscall("open", trace.audit.machine),
3076 },
3077 .syscalls = {2771 .syscalls = {
3078 . max = -1,2772 . max = -1,
3079 },2773 },
@@ -3091,6 +2785,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) · 11 unmodified lines
3091 .output = stderr,2785 .output = stderr,
3092 .show_comm = true,2786 .show_comm = true,
3093 .trace_syscalls = true,2787 .trace_syscalls = true,
2788 .kernel_syscallchains = false,
2789 .max_stack = UINT_MAX,
3094 };2790 };
3095 const char *output_name = NULL;2791 const char *output_name = NULL;
3096 const char *ev_qualifier_str = NULL;2792 const char *ev_qualifier_str = NULL;
@@ -3136,10 +2832,24 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) · 39 unmodified lines
3136 "Trace pagefaults", parse_pagefaults, "maj"),2832 "Trace pagefaults", parse_pagefaults, "maj"),
3137 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),2833 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
3138 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),2834 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
2835 OPT_CALLBACK(0, "call-graph", &trace.opts,
2836 "record_mode[,record_size]", record_callchain_help,
2837 &record_parse_callchain_opt),
2838 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
2839 "Show the kernel callchains on the syscall exit path"),
2840 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
2841 "Set the minimum stack depth when parsing the callchain, "
2842 "anything below the specified depth will be ignored."),
2843 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
2844 "Set the maximum stack depth when parsing the callchain, "
2845 "anything beyond the specified depth will be ignored. "
2846 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3139 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,2847 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3140 "per thread proc mmap processing timeout in ms"),2848 "per thread proc mmap processing timeout in ms"),
3141 OPT_END()2849 OPT_END()
3142 };2850 };
2851 bool __maybe_unused max_stack_user_set = true;
2852 bool mmap_pages_user_set = true;
3143 const char * const trace_subcommands[] = { "record", NULL };2853 const char * const trace_subcommands[] = { "record", NULL };
3144 int err;2854 int err;
3145 char bf[BUFSIZ];2855 char bf[BUFSIZ];
@@ -3148,8 +2858,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) · 2 unmodified lines
3148 signal(SIGFPE, sighandler_dump_stack);2858 signal(SIGFPE, sighandler_dump_stack);
3149 2859
3150 trace.evlist = perf_evlist__new();2860 trace.evlist = perf_evlist__new();
2861 trace.sctbl = syscalltbl__new();
3151 2862
3152 if (trace.evlist == NULL) {2863 if (trace.evlist == NULL || trace.sctbl == NULL) {
3153 pr_err("Not enough memory to run!\n");2864 pr_err("Not enough memory to run!\n");
3154 err = -ENOMEM;2865 err = -ENOMEM;
3155 goto out;2866 goto out;
@@ -3158,11 +2869,40 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) · 2 unmodified lines
3158 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,2869 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3159 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);2870 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3160 2871
2872 err = bpf__setup_stdout(trace.evlist);
2873 if (err) {
2874 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
2875 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
2876 goto out;
2877 }
2878
2879 err = -1;
2880
3161 if (trace.trace_pgfaults) {2881 if (trace.trace_pgfaults) {
3162 trace.opts.sample_address = true;2882 trace.opts.sample_address = true;
3163 trace.opts.sample_time = true;2883 trace.opts.sample_time = true;
3164 }2884 }
3165 2885
2886 if (trace.opts.mmap_pages == UINT_MAX)
2887 mmap_pages_user_set = false;
2888
2889 if (trace.max_stack == UINT_MAX) {
2890 trace.max_stack = sysctl_perf_event_max_stack;
2891 max_stack_user_set = false;
2892 }
2893
2894#ifdef HAVE_DWARF_UNWIND_SUPPORT
2895 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled)
2896 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
2897#endif
2898
2899 if (callchain_param.enabled) {
2900 if (!mmap_pages_user_set && geteuid() == 0)
2901 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
2902
2903 symbol_conf.use_callchain = true;
2904 }
2905
3166 if (trace.evlist->nr_entries > 0)2906 if (trace.evlist->nr_entries > 0)
3167 evlist__set_evsel_handler(trace.evlist, trace__event_handler);2907 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3168 2908
@@ -3179,6 +2919,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) · 10 unmodified lines
3179 return -1;2919 return -1;
3180 }2920 }
3181 2921
2922 if (!trace.trace_syscalls && ev_qualifier_str) {
2923 pr_err("The -e option can't be used with --no-syscalls.\n");
2924 goto out;
2925 }
2926
3182 if (output_name != NULL) {2927 if (output_name != NULL) {
3183 err = trace__open_output(&trace, output_name);2928 err = trace__open_output(&trace, output_name);
3184 if (err < 0) {2929 if (err < 0) {
@@ -3187,6 +2932,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused) · 2 unmodified lines
3187 }2932 }
3188 }2933 }
3189 2934
2935 trace.open_id = syscalltbl__id(trace.sctbl, "open");
2936
3190 if (ev_qualifier_str != NULL) {2937 if (ev_qualifier_str != NULL) {
3191 const char *s = ev_qualifier_str;2938 const char *s = ev_qualifier_str;
3192 struct strlist_config slist_config = {2939 struct strlist_config slist_config = {
tools/perf/config/Makefile+1−4
@@ -27,7 +27,7 @@ NO_PERF_REGS := 1 · 26 unmodified lines
27ifeq ($(ARCH),x86)27ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86)28 $(call detected,CONFIG_X86)
29 ifeq (${IS_64_BIT}, 1)29 ifeq (${IS_64_BIT}, 1)
30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated
31 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S31 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_6432 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64)33 $(call detected,CONFIG_X86_64)
@@ -295,9 +295,6 @@ ifndef NO_LIBELF · 261 unmodified lines
295 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT295 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
296 endif296 endif
297 297
298 # include ARCH specific config
299 -include $(src-perf)/arch/$(ARCH)/Makefile
300
301 ifndef NO_DWARF298 ifndef NO_DWARF
302 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)299 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
303 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);300 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
tools/perf/jvmti/jvmti_agent.c+41−2
@@ -92,6 +92,22 @@ error: · 91 unmodified lines
92 return ret;92 return ret;
93}93}
94 94
95static int use_arch_timestamp;
96
97static inline uint64_t
98get_arch_timestamp(void)
99{
100#if defined(__i386__) || defined(__x86_64__)
101 unsigned int low, high;
102
103 asm volatile("rdtsc" : "=a" (low), "=d" (high));
104
105 return low | ((uint64_t)high) << 32;
106#else
107 return 0;
108#endif
109}
110
95#define NSEC_PER_SEC 1000000000111#define NSEC_PER_SEC 1000000000
96static int perf_clk_id = CLOCK_MONOTONIC;112static int perf_clk_id = CLOCK_MONOTONIC;
97 113
@@ -107,6 +123,9 @@ perf_get_timestamp(void) · 9 unmodified lines
107 struct timespec ts;123 struct timespec ts;
108 int ret;124 int ret;
109 125
126 if (use_arch_timestamp)
127 return get_arch_timestamp();
128
110 ret = clock_gettime(perf_clk_id, &ts);129 ret = clock_gettime(perf_clk_id, &ts);
111 if (ret)130 if (ret)
112 return 0;131 return 0;
@@ -203,6 +222,17 @@ perf_close_marker_file(void) · 90 unmodified lines
203 munmap(marker_addr, pgsz);222 munmap(marker_addr, pgsz);
204}223}
205 224
225static void
226init_arch_timestamp(void)
227{
228 char *str = getenv("JITDUMP_USE_ARCH_TIMESTAMP");
229
230 if (!str || !*str || !strcmp(str, "0"))
231 return;
232
233 use_arch_timestamp = 1;
234}
235
206void *jvmti_open(void)236void *jvmti_open(void)
207{237{
208 int pad_cnt;238 int pad_cnt;
@@ -211,11 +241,17 @@ void *jvmti_open(void) · 2 unmodified lines
211 int fd;241 int fd;
212 FILE *fp;242 FILE *fp;
213 243
244 init_arch_timestamp();
245
214 /*246 /*
215 * check if clockid is supported247 * check if clockid is supported
216 */248 */
217 if (!perf_get_timestamp())249 if (!perf_get_timestamp()) {
218 warnx("jvmti: kernel does not support %d clock id", perf_clk_id);250 if (use_arch_timestamp)
251 warnx("jvmti: arch timestamp not supported");
252 else
253 warnx("jvmti: kernel does not support %d clock id", perf_clk_id);
254 }
219 255
220 memset(&header, 0, sizeof(header));256 memset(&header, 0, sizeof(header));
221 257
@@ -263,6 +299,9 @@ void *jvmti_open(void) · 41 unmodified lines
263 299
264 header.timestamp = perf_get_timestamp();300 header.timestamp = perf_get_timestamp();
265 301
302 if (use_arch_timestamp)
303 header.flags |= JITDUMP_FLAGS_ARCH_TIMESTAMP;
304
266 if (!fwrite(&header, sizeof(header), 1, fp)) {305 if (!fwrite(&header, sizeof(header), 1, fp)) {
267 warn("jvmti: cannot write dumpfile header");306 warn("jvmti: cannot write dumpfile header");
268 goto error;307 goto error;
tools/perf/perf.c+11−5
@@ -17,6 +17,7 @@ · 16 unmodified lines
17#include <subcmd/parse-options.h>17#include <subcmd/parse-options.h>
18#include "util/bpf-loader.h"18#include "util/bpf-loader.h"
19#include "util/debug.h"19#include "util/debug.h"
20#include <api/fs/fs.h>
20#include <api/fs/tracing_path.h>21#include <api/fs/tracing_path.h>
21#include <pthread.h>22#include <pthread.h>
22#include <stdlib.h>23#include <stdlib.h>
@@ -308,9 +309,11 @@ static int handle_alias(int *argcp, const char ***argv) · 285 unmodified lines
308 if (*argcp > 1) {309 if (*argcp > 1) {
309 struct strbuf buf;310 struct strbuf buf;
310 311
311 strbuf_init(&buf, PATH_MAX);312 if (strbuf_init(&buf, PATH_MAX) < 0 ||
312 strbuf_addstr(&buf, alias_string);313 strbuf_addstr(&buf, alias_string) < 0 ||
313 sq_quote_argv(&buf, (*argv) + 1, PATH_MAX);314 sq_quote_argv(&buf, (*argv) + 1,
315 PATH_MAX) < 0)
316 die("Failed to allocate memory.");
314 free(alias_string);317 free(alias_string);
315 alias_string = buf.buf;318 alias_string = buf.buf;
316 }319 }
@@ -533,6 +536,7 @@ int main(int argc, const char **argv) · 216 unmodified lines
533{536{
534 const char *cmd;537 const char *cmd;
535 char sbuf[STRERR_BUFSIZE];538 char sbuf[STRERR_BUFSIZE];
539 int value;
536 540
537 /* libsubcmd init */541 /* libsubcmd init */
538 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);542 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
@@ -542,6 +546,9 @@ int main(int argc, const char **argv) · 3 unmodified lines
542 page_size = sysconf(_SC_PAGE_SIZE);546 page_size = sysconf(_SC_PAGE_SIZE);
543 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);547 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
544 548
549 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
550 sysctl_perf_event_max_stack = value;
551
545 cmd = extract_argv0_path(argv[0]);552 cmd = extract_argv0_path(argv[0]);
546 if (!cmd)553 if (!cmd)
547 cmd = "perf-help";554 cmd = "perf-help";
@@ -549,6 +556,7 @@ int main(int argc, const char **argv) · 1 unmodified line
549 srandom(time(NULL));556 srandom(time(NULL));
550 557
551 perf_config(perf_default_config, NULL);558 perf_config(perf_default_config, NULL);
559 set_buildid_dir(NULL);
552 560
553 /* get debugfs/tracefs mount point from /proc/mounts */561 /* get debugfs/tracefs mount point from /proc/mounts */
554 tracing_path_mount();562 tracing_path_mount();
@@ -572,7 +580,6 @@ int main(int argc, const char **argv) · 17 unmodified lines
572 }580 }
573 if (!prefixcmp(cmd, "trace")) {581 if (!prefixcmp(cmd, "trace")) {
574#ifdef HAVE_LIBAUDIT_SUPPORT582#ifdef HAVE_LIBAUDIT_SUPPORT
575 set_buildid_dir(NULL);
576 setup_path();583 setup_path();
577 argv[0] = "trace";584 argv[0] = "trace";
578 return cmd_trace(argc, argv, NULL);585 return cmd_trace(argc, argv, NULL);
@@ -587,7 +594,6 @@ int main(int argc, const char **argv) · 8 unmodified lines
587 argc--;594 argc--;
588 handle_options(&argv, &argc, NULL);595 handle_options(&argv, &argc, NULL);
589 commit_pager_choice();596 commit_pager_choice();
590 set_buildid_dir(NULL);
591 597
592 if (argc > 0) {598 if (argc > 0) {
593 if (!prefixcmp(argv[0], "--"))599 if (!prefixcmp(argv[0], "--"))
tools/perf/perf.h+0−1
@@ -52,7 +52,6 @@ struct record_opts { · 51 unmodified lines
52 bool sample_weight;52 bool sample_weight;
53 bool sample_time;53 bool sample_time;
54 bool sample_time_set;54 bool sample_time_set;
55 bool callgraph_set;
56 bool period;55 bool period;
57 bool running_time;56 bool running_time;
58 bool full_auxtrace;57 bool full_auxtrace;
tools/perf/scripts/python/export-to-postgresql.py+32−20
@@ -34,10 +34,9 @@ import datetime · 33 unmodified lines
34#34#
35# ubuntu:35# ubuntu:
36#36#
37# $ sudo apt-get install postgresql37# $ sudo apt-get install postgresql python-pyside.qtsql libqt4-sql-psql
38# $ sudo su - postgres38# $ sudo su - postgres
39# $ createuser <your user id here>39# $ createuser -s <your user id here>
40# Shall the new role be a superuser? (y/n) y
41#40#
42# An example of using this script with Intel PT:41# An example of using this script with Intel PT:
43#42#
@@ -224,11 +223,14 @@ sys.path.append(os.environ['PERF_EXEC_PATH'] + \ · 180 unmodified lines
224 223
225perf_db_export_mode = True224perf_db_export_mode = True
226perf_db_export_calls = False225perf_db_export_calls = False
226perf_db_export_callchains = False
227
227 228
228def usage():229def usage():
229 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>]"230 print >> sys.stderr, "Usage is: export-to-postgresql.py <database name> [<columns>] [<calls>] [<callchains>]"
230 print >> sys.stderr, "where: columns 'all' or 'branches'"231 print >> sys.stderr, "where: columns 'all' or 'branches'"
231 print >> sys.stderr, " calls 'calls' => create calls table"232 print >> sys.stderr, " calls 'calls' => create calls and call_paths table"
233 print >> sys.stderr, " callchains 'callchains' => create call_paths table"
232 raise Exception("Too few arguments")234 raise Exception("Too few arguments")
233 235
234if (len(sys.argv) < 2):236if (len(sys.argv) < 2):
@@ -246,9 +248,11 @@ if columns not in ("all", "branches"): · 11 unmodified lines
246 248
247branches = (columns == "branches")249branches = (columns == "branches")
248 250
249if (len(sys.argv) >= 4):251for i in range(3,len(sys.argv)):
250 if (sys.argv[3] == "calls"):252 if (sys.argv[i] == "calls"):
251 perf_db_export_calls = True253 perf_db_export_calls = True
254 elif (sys.argv[i] == "callchains"):
255 perf_db_export_callchains = True
252 else:256 else:
253 usage()257 usage()
254 258
@@ -359,14 +363,16 @@ else: · 104 unmodified lines
359 'transaction bigint,'363 'transaction bigint,'
360 'data_src bigint,'364 'data_src bigint,'
361 'branch_type integer,'365 'branch_type integer,'
362 'in_tx boolean)')366 'in_tx boolean,'
367 'call_path_id bigint)')
363 368
364if perf_db_export_calls:369if perf_db_export_calls or perf_db_export_callchains:
365 do_query(query, 'CREATE TABLE call_paths ('370 do_query(query, 'CREATE TABLE call_paths ('
366 'id bigint NOT NULL,'371 'id bigint NOT NULL,'
367 'parent_id bigint,'372 'parent_id bigint,'
368 'symbol_id bigint,'373 'symbol_id bigint,'
369 'ip bigint)')374 'ip bigint)')
375if perf_db_export_calls:
370 do_query(query, 'CREATE TABLE calls ('376 do_query(query, 'CREATE TABLE calls ('
371 'id bigint NOT NULL,'377 'id bigint NOT NULL,'
372 'thread_id bigint,'378 'thread_id bigint,'
@@ -428,7 +434,7 @@ do_query(query, 'CREATE VIEW comm_threads_view AS ' · 55 unmodified lines
428 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'434 '(SELECT tid FROM threads WHERE id = thread_id) AS tid'
429 ' FROM comm_threads')435 ' FROM comm_threads')
430 436
431if perf_db_export_calls:437if perf_db_export_calls or perf_db_export_callchains:
432 do_query(query, 'CREATE VIEW call_paths_view AS '438 do_query(query, 'CREATE VIEW call_paths_view AS '
433 'SELECT '439 'SELECT '
434 'c.id,'440 'c.id,'
@@ -444,6 +450,7 @@ if perf_db_export_calls: · 9 unmodified lines
444 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'450 '(SELECT dso_id FROM symbols WHERE id = p.symbol_id) AS parent_dso_id,'
445 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'451 '(SELECT dso FROM symbols_view WHERE id = p.symbol_id) AS parent_dso_short_name'
446 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')452 ' FROM call_paths c INNER JOIN call_paths p ON p.id = c.parent_id')
453if perf_db_export_calls:
447 do_query(query, 'CREATE VIEW calls_view AS '454 do_query(query, 'CREATE VIEW calls_view AS '
448 'SELECT '455 'SELECT '
449 'calls.id,'456 'calls.id,'
@@ -541,8 +548,9 @@ dso_file = open_output_file("dso_table.bin") · 91 unmodified lines
541symbol_file = open_output_file("symbol_table.bin")548symbol_file = open_output_file("symbol_table.bin")
542branch_type_file = open_output_file("branch_type_table.bin")549branch_type_file = open_output_file("branch_type_table.bin")
543sample_file = open_output_file("sample_table.bin")550sample_file = open_output_file("sample_table.bin")
544if perf_db_export_calls:551if perf_db_export_calls or perf_db_export_callchains:
545 call_path_file = open_output_file("call_path_table.bin")552 call_path_file = open_output_file("call_path_table.bin")
553if perf_db_export_calls:
546 call_file = open_output_file("call_table.bin")554 call_file = open_output_file("call_table.bin")
547 555
548def trace_begin():556def trace_begin():
@@ -554,8 +562,8 @@ def trace_begin(): · 5 unmodified lines
554 comm_table(0, "unknown")562 comm_table(0, "unknown")
555 dso_table(0, 0, "unknown", "unknown", "")563 dso_table(0, 0, "unknown", "unknown", "")
556 symbol_table(0, 0, 0, 0, 0, "unknown")564 symbol_table(0, 0, 0, 0, 0, "unknown")
557 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)565 sample_table(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
558 if perf_db_export_calls:566 if perf_db_export_calls or perf_db_export_callchains:
559 call_path_table(0, 0, 0, 0)567 call_path_table(0, 0, 0, 0)
560 568
561unhandled_count = 0569unhandled_count = 0
@@ -571,8 +579,9 @@ def trace_end(): · 9 unmodified lines
571 copy_output_file(symbol_file, "symbols")579 copy_output_file(symbol_file, "symbols")
572 copy_output_file(branch_type_file, "branch_types")580 copy_output_file(branch_type_file, "branch_types")
573 copy_output_file(sample_file, "samples")581 copy_output_file(sample_file, "samples")
574 if perf_db_export_calls:582 if perf_db_export_calls or perf_db_export_callchains:
575 copy_output_file(call_path_file, "call_paths")583 copy_output_file(call_path_file, "call_paths")
584 if perf_db_export_calls:
576 copy_output_file(call_file, "calls")585 copy_output_file(call_file, "calls")
577 586
578 print datetime.datetime.today(), "Removing intermediate files..."587 print datetime.datetime.today(), "Removing intermediate files..."
@@ -585,8 +594,9 @@ def trace_end(): · 6 unmodified lines
585 remove_output_file(symbol_file)594 remove_output_file(symbol_file)
586 remove_output_file(branch_type_file)595 remove_output_file(branch_type_file)
587 remove_output_file(sample_file)596 remove_output_file(sample_file)
588 if perf_db_export_calls:597 if perf_db_export_calls or perf_db_export_callchains:
589 remove_output_file(call_path_file)598 remove_output_file(call_path_file)
599 if perf_db_export_calls:
590 remove_output_file(call_file)600 remove_output_file(call_file)
591 os.rmdir(output_dir_name)601 os.rmdir(output_dir_name)
592 print datetime.datetime.today(), "Adding primary keys"602 print datetime.datetime.today(), "Adding primary keys"
@@ -599,8 +609,9 @@ def trace_end(): · 6 unmodified lines
599 do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)')609 do_query(query, 'ALTER TABLE symbols ADD PRIMARY KEY (id)')
600 do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)')610 do_query(query, 'ALTER TABLE branch_types ADD PRIMARY KEY (id)')
601 do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)')611 do_query(query, 'ALTER TABLE samples ADD PRIMARY KEY (id)')
602 if perf_db_export_calls:612 if perf_db_export_calls or perf_db_export_callchains:
603 do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)')613 do_query(query, 'ALTER TABLE call_paths ADD PRIMARY KEY (id)')
614 if perf_db_export_calls:
604 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')615 do_query(query, 'ALTER TABLE calls ADD PRIMARY KEY (id)')
605 616
606 print datetime.datetime.today(), "Adding foreign keys"617 print datetime.datetime.today(), "Adding foreign keys"
@@ -623,10 +634,11 @@ def trace_end(): · 16 unmodified lines
623 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),'634 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id),'
624 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),'635 'ADD CONSTRAINT todsofk FOREIGN KEY (to_dso_id) REFERENCES dsos (id),'
625 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)')636 'ADD CONSTRAINT tosymbolfk FOREIGN KEY (to_symbol_id) REFERENCES symbols (id)')
626 if perf_db_export_calls:637 if perf_db_export_calls or perf_db_export_callchains:
627 do_query(query, 'ALTER TABLE call_paths '638 do_query(query, 'ALTER TABLE call_paths '
628 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),'639 'ADD CONSTRAINT parentfk FOREIGN KEY (parent_id) REFERENCES call_paths (id),'
629 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)')640 'ADD CONSTRAINT symbolfk FOREIGN KEY (symbol_id) REFERENCES symbols (id)')
641 if perf_db_export_calls:
630 do_query(query, 'ALTER TABLE calls '642 do_query(query, 'ALTER TABLE calls '
631 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'643 'ADD CONSTRAINT threadfk FOREIGN KEY (thread_id) REFERENCES threads (id),'
632 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'644 'ADD CONSTRAINT commfk FOREIGN KEY (comm_id) REFERENCES comms (id),'
@@ -694,11 +706,11 @@ def branch_type_table(branch_type, name, *x): · 61 unmodified lines
694 value = struct.pack(fmt, 2, 4, branch_type, n, name)706 value = struct.pack(fmt, 2, 4, branch_type, n, name)
695 branch_type_file.write(value)707 branch_type_file.write(value)
696 708
697def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, *x):709def sample_table(sample_id, evsel_id, machine_id, thread_id, comm_id, dso_id, symbol_id, sym_offset, ip, time, cpu, to_dso_id, to_symbol_id, to_sym_offset, to_ip, period, weight, transaction, data_src, branch_type, in_tx, call_path_id, *x):
698 if branches:710 if branches:
699 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiB", 17, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx)711 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiiiBiq", 18, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 4, branch_type, 1, in_tx, 8, call_path_id)
700 else:712 else:
701 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiB", 21, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx)713 value = struct.pack("!hiqiqiqiqiqiqiqiqiqiqiiiqiqiqiqiqiqiqiqiiiBiq", 22, 8, sample_id, 8, evsel_id, 8, machine_id, 8, thread_id, 8, comm_id, 8, dso_id, 8, symbol_id, 8, sym_offset, 8, ip, 8, time, 4, cpu, 8, to_dso_id, 8, to_symbol_id, 8, to_sym_offset, 8, to_ip, 8, period, 8, weight, 8, transaction, 8, data_src, 4, branch_type, 1, in_tx, 8, call_path_id)
702 sample_file.write(value)714 sample_file.write(value)
703 715
704def call_path_table(cp_id, parent_id, symbol_id, ip, *x):716def call_path_table(cp_id, parent_id, symbol_id, ip, *x):
tools/perf/tests/Build+2−0
@@ -37,6 +37,8 @@ perf-y += topology.o · 36 unmodified lines
37perf-y += cpumap.o37perf-y += cpumap.o
38perf-y += stat.o38perf-y += stat.o
39perf-y += event_update.o39perf-y += event_update.o
40perf-y += event-times.o
41perf-y += backward-ring-buffer.o
40 42
41$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build43$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
42 $(call rule_mkdir)44 $(call rule_mkdir)
tools/perf/tests/backward-ring-buffer.c+151−0
@@ -0,0 +1,151 @@
1/*
2 * Test backward bit in event attribute, read ring buffer from end to
3 * beginning
4 */
5
6#include <perf.h>
7#include <evlist.h>
8#include <sys/prctl.h>
9#include "tests.h"
10#include "debug.h"
11
12#define NR_ITERS 111
13
14static void testcase(void)
15{
16 int i;
17
18 for (i = 0; i < NR_ITERS; i++) {
19 char proc_name[10];
20
21 snprintf(proc_name, sizeof(proc_name), "p:%d\n", i);
22 prctl(PR_SET_NAME, proc_name);
23 }
24}
25
26static int count_samples(struct perf_evlist *evlist, int *sample_count,
27 int *comm_count)
28{
29 int i;
30
31 for (i = 0; i < evlist->nr_mmaps; i++) {
32 union perf_event *event;
33
34 perf_evlist__mmap_read_catchup(evlist, i);
35 while ((event = perf_evlist__mmap_read_backward(evlist, i)) != NULL) {
36 const u32 type = event->header.type;
37
38 switch (type) {
39 case PERF_RECORD_SAMPLE:
40 (*sample_count)++;
41 break;
42 case PERF_RECORD_COMM:
43 (*comm_count)++;
44 break;
45 default:
46 pr_err("Unexpected record of type %d\n", type);
47 return TEST_FAIL;
48 }
49 }
50 }
51 return TEST_OK;
52}
53
54static int do_test(struct perf_evlist *evlist, int mmap_pages,
55 int *sample_count, int *comm_count)
56{
57 int err;
58 char sbuf[STRERR_BUFSIZE];
59
60 err = perf_evlist__mmap(evlist, mmap_pages, true);
61 if (err < 0) {
62 pr_debug("perf_evlist__mmap: %s\n",
63 strerror_r(errno, sbuf, sizeof(sbuf)));
64 return TEST_FAIL;
65 }
66
67 perf_evlist__enable(evlist);
68 testcase();
69 perf_evlist__disable(evlist);
70
71 err = count_samples(evlist, sample_count, comm_count);
72 perf_evlist__munmap(evlist);
73 return err;
74}
75
76
77int test__backward_ring_buffer(int subtest __maybe_unused)
78{
79 int ret = TEST_SKIP, err, sample_count = 0, comm_count = 0;
80 char pid[16], sbuf[STRERR_BUFSIZE];
81 struct perf_evlist *evlist;
82 struct perf_evsel *evsel __maybe_unused;
83 struct parse_events_error parse_error;
84 struct record_opts opts = {
85 .target = {
86 .uid = UINT_MAX,
87 .uses_mmap = true,
88 },
89 .freq = 0,
90 .mmap_pages = 256,
91 .default_interval = 1,
92 };
93
94 snprintf(pid, sizeof(pid), "%d", getpid());
95 pid[sizeof(pid) - 1] = '\0';
96 opts.target.tid = opts.target.pid = pid;
97
98 evlist = perf_evlist__new();
99 if (!evlist) {
100 pr_debug("No ehough memory to create evlist\n");
101 return TEST_FAIL;
102 }
103
104 err = perf_evlist__create_maps(evlist, &opts.target);
105 if (err < 0) {
106 pr_debug("Not enough memory to create thread/cpu maps\n");
107 goto out_delete_evlist;
108 }
109
110 bzero(&parse_error, sizeof(parse_error));
111 err = parse_events(evlist, "syscalls:sys_enter_prctl", &parse_error);
112 if (err) {
113 pr_debug("Failed to parse tracepoint event, try use root\n");
114 ret = TEST_SKIP;
115 goto out_delete_evlist;
116 }
117
118 perf_evlist__config(evlist, &opts, NULL);
119
120 /* Set backward bit, ring buffer should be writing from end */
121 evlist__for_each(evlist, evsel)
122 evsel->attr.write_backward = 1;
123
124 err = perf_evlist__open(evlist);
125 if (err < 0) {
126 pr_debug("perf_evlist__open: %s\n",
127 strerror_r(errno, sbuf, sizeof(sbuf)));
128 goto out_delete_evlist;
129 }
130
131 ret = TEST_FAIL;
132 err = do_test(evlist, opts.mmap_pages, &sample_count,
133 &comm_count);
134 if (err != TEST_OK)
135 goto out_delete_evlist;
136
137 if ((sample_count != NR_ITERS) || (comm_count != NR_ITERS)) {
138 pr_err("Unexpected counter: sample_count=%d, comm_count=%d\n",
139 sample_count, comm_count);
140 goto out_delete_evlist;
141 }
142
143 err = do_test(evlist, 1, &sample_count, &comm_count);
144 if (err != TEST_OK)
145 goto out_delete_evlist;
146
147 ret = TEST_OK;
148out_delete_evlist:
149 perf_evlist__delete(evlist);
150 return ret;
151}
tools/perf/tests/bpf.c+1−1
@@ -138,7 +138,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void), · 137 unmodified lines
138 perf_evlist__splice_list_tail(evlist, &parse_evlist.list);138 perf_evlist__splice_list_tail(evlist, &parse_evlist.list);
139 evlist->nr_groups = parse_evlist.nr_groups;139 evlist->nr_groups = parse_evlist.nr_groups;
140 140
141 perf_evlist__config(evlist, &opts);141 perf_evlist__config(evlist, &opts, NULL);
142 142
143 err = perf_evlist__open(evlist);143 err = perf_evlist__open(evlist);
144 if (err < 0) {144 if (err < 0) {
tools/perf/tests/builtin-test.c+8−0
@@ -203,6 +203,14 @@ static struct test generic_tests[] = { · 202 unmodified lines
203 .desc = "Test attr update synthesize",203 .desc = "Test attr update synthesize",
204 .func = test__event_update,204 .func = test__event_update,
205 },205 },
206 {
207 .desc = "Test events times",
208 .func = test__event_times,
209 },
210 {
211 .desc = "Test backward reading from ring buffer",
212 .func = test__backward_ring_buffer,
213 },
206 {214 {
207 .func = NULL,215 .func = NULL,
208 },216 },
tools/perf/tests/code-reading.c+1−1
@@ -532,7 +532,7 @@ static int do_test_code_reading(bool try_kcore) · 531 unmodified lines
532 goto out_put;532 goto out_put;
533 }533 }
534 534
535 perf_evlist__config(evlist, &opts);535 perf_evlist__config(evlist, &opts, NULL);
536 536
537 evsel = perf_evlist__first(evlist);537 evsel = perf_evlist__first(evlist);
538 538
tools/perf/tests/dso-data.c+1−1
@@ -202,7 +202,7 @@ static int dsos__create(int cnt, int size) · 201 unmodified lines
202{202{
203 int i;203 int i;
204 204
205 dsos = malloc(sizeof(dsos) * cnt);205 dsos = malloc(sizeof(*dsos) * cnt);
206 TEST_ASSERT_VAL("failed to alloc dsos array", dsos);206 TEST_ASSERT_VAL("failed to alloc dsos array", dsos);
207 207
208 for (i = 0; i < cnt; i++) {208 for (i = 0; i < cnt; i++) {
tools/perf/tests/event-times.c+236−0
@@ -0,0 +1,236 @@
1#include <linux/compiler.h>
2#include <string.h>
3#include "tests.h"
4#include "evlist.h"
5#include "evsel.h"
6#include "util.h"
7#include "debug.h"
8#include "thread_map.h"
9#include "target.h"
10
11static int attach__enable_on_exec(struct perf_evlist *evlist)
12{
13 struct perf_evsel *evsel = perf_evlist__last(evlist);
14 struct target target = {
15 .uid = UINT_MAX,
16 };
17 const char *argv[] = { "true", NULL, };
18 char sbuf[STRERR_BUFSIZE];
19 int err;
20
21 pr_debug("attaching to spawned child, enable on exec\n");
22
23 err = perf_evlist__create_maps(evlist, &target);
24 if (err < 0) {
25 pr_debug("Not enough memory to create thread/cpu maps\n");
26 return err;
27 }
28
29 err = perf_evlist__prepare_workload(evlist, &target, argv, false, NULL);
30 if (err < 0) {
31 pr_debug("Couldn't run the workload!\n");
32 return err;
33 }
34
35 evsel->attr.enable_on_exec = 1;
36
37 err = perf_evlist__open(evlist);
38 if (err < 0) {
39 pr_debug("perf_evlist__open: %s\n",
40 strerror_r(errno, sbuf, sizeof(sbuf)));
41 return err;
42 }
43
44 return perf_evlist__start_workload(evlist) == 1 ? TEST_OK : TEST_FAIL;
45}
46
47static int detach__enable_on_exec(struct perf_evlist *evlist)
48{
49 waitpid(evlist->workload.pid, NULL, 0);
50 return 0;
51}
52
53static int attach__current_disabled(struct perf_evlist *evlist)
54{
55 struct perf_evsel *evsel = perf_evlist__last(evlist);
56 struct thread_map *threads;
57 int err;
58
59 pr_debug("attaching to current thread as disabled\n");
60
61 threads = thread_map__new(-1, getpid(), UINT_MAX);
62 if (threads == NULL) {
63 pr_debug("thread_map__new\n");
64 return -1;
65 }
66
67 evsel->attr.disabled = 1;
68
69 err = perf_evsel__open_per_thread(evsel, threads);
70 if (err) {
71 pr_debug("Failed to open event cpu-clock:u\n");
72 return err;
73 }
74
75 thread_map__put(threads);
76 return perf_evsel__enable(evsel) == 0 ? TEST_OK : TEST_FAIL;
77}
78
79static int attach__current_enabled(struct perf_evlist *evlist)
80{
81 struct perf_evsel *evsel = perf_evlist__last(evlist);
82 struct thread_map *threads;
83 int err;
84
85 pr_debug("attaching to current thread as enabled\n");
86
87 threads = thread_map__new(-1, getpid(), UINT_MAX);
88 if (threads == NULL) {
89 pr_debug("failed to call thread_map__new\n");
90 return -1;
91 }
92
93 err = perf_evsel__open_per_thread(evsel, threads);
94
95 thread_map__put(threads);
96 return err == 0 ? TEST_OK : TEST_FAIL;
97}
98
99static int detach__disable(struct perf_evlist *evlist)
100{
101 struct perf_evsel *evsel = perf_evlist__last(evlist);
102
103 return perf_evsel__enable(evsel);
104}
105
106static int attach__cpu_disabled(struct perf_evlist *evlist)
107{
108 struct perf_evsel *evsel = perf_evlist__last(evlist);
109 struct cpu_map *cpus;
110 int err;
111
112 pr_debug("attaching to CPU 0 as enabled\n");
113
114 cpus = cpu_map__new("0");
115 if (cpus == NULL) {
116 pr_debug("failed to call cpu_map__new\n");
117 return -1;
118 }
119
120 evsel->attr.disabled = 1;
121
122 err = perf_evsel__open_per_cpu(evsel, cpus);
123 if (err) {
124 if (err == -EACCES)
125 return TEST_SKIP;
126
127 pr_debug("Failed to open event cpu-clock:u\n");
128 return err;
129 }
130
131 cpu_map__put(cpus);
132 return perf_evsel__enable(evsel);
133}
134
135static int attach__cpu_enabled(struct perf_evlist *evlist)
136{
137 struct perf_evsel *evsel = perf_evlist__last(evlist);
138 struct cpu_map *cpus;
139 int err;
140
141 pr_debug("attaching to CPU 0 as enabled\n");
142
143 cpus = cpu_map__new("0");
144 if (cpus == NULL) {
145 pr_debug("failed to call cpu_map__new\n");
146 return -1;
147 }
148
149 err = perf_evsel__open_per_cpu(evsel, cpus);
150 if (err == -EACCES)
151 return TEST_SKIP;
152
153 cpu_map__put(cpus);
154 return err ? TEST_FAIL : TEST_OK;
155}
156
157static int test_times(int (attach)(struct perf_evlist *),
158 int (detach)(struct perf_evlist *))
159{
160 struct perf_counts_values count;
161 struct perf_evlist *evlist = NULL;
162 struct perf_evsel *evsel;
163 int err = -1, i;
164
165 evlist = perf_evlist__new();
166 if (!evlist) {
167 pr_debug("failed to create event list\n");
168 goto out_err;
169 }
170
171 err = parse_events(evlist, "cpu-clock:u", NULL);
172 if (err) {
173 pr_debug("failed to parse event cpu-clock:u\n");
174 goto out_err;
175 }
176
177 evsel = perf_evlist__last(evlist);
178 evsel->attr.read_format |=
179 PERF_FORMAT_TOTAL_TIME_ENABLED |
180 PERF_FORMAT_TOTAL_TIME_RUNNING;
181
182 err = attach(evlist);
183 if (err == TEST_SKIP) {
184 pr_debug(" SKIP : not enough rights\n");
185 return err;
186 }
187
188 TEST_ASSERT_VAL("failed to attach", !err);
189
190 for (i = 0; i < 100000000; i++) { }
191
192 TEST_ASSERT_VAL("failed to detach", !detach(evlist));
193
194 perf_evsel__read(evsel, 0, 0, &count);
195
196 err = !(count.ena == count.run);
197
198 pr_debug(" %s: ena %" PRIu64", run %" PRIu64"\n",
199 !err ? "OK " : "FAILED",
200 count.ena, count.run);
201
202out_err:
203 if (evlist)
204 perf_evlist__delete(evlist);
205 return !err ? TEST_OK : TEST_FAIL;
206}
207
208/*
209 * This test creates software event 'cpu-clock'
210 * attaches it in several ways (explained below)
211 * and checks that enabled and running times
212 * match.
213 */
214int test__event_times(int subtest __maybe_unused)
215{
216 int err, ret = 0;
217
218#define _T(attach, detach) \
219 err = test_times(attach, detach); \
220 if (err && (ret == TEST_OK || ret == TEST_SKIP)) \
221 ret = err;
222
223 /* attach on newly spawned process after exec */
224 _T(attach__enable_on_exec, detach__enable_on_exec)
225 /* attach on current process as enabled */
226 _T(attach__current_enabled, detach__disable)
227 /* attach on current process as disabled */
228 _T(attach__current_disabled, detach__disable)
229 /* attach on cpu as disabled */
230 _T(attach__cpu_disabled, detach__disable)
231 /* attach on cpu as enabled */
232 _T(attach__cpu_enabled, detach__disable)
233
234#undef _T
235 return ret;
236}
tools/perf/tests/event_update.c+1−1
@@ -30,7 +30,7 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused, · 29 unmodified lines
30 30
31 TEST_ASSERT_VAL("wrong id", ev->id == 123);31 TEST_ASSERT_VAL("wrong id", ev->id == 123);
32 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE);32 TEST_ASSERT_VAL("wrong id", ev->type == PERF_EVENT_UPDATE__SCALE);
33 TEST_ASSERT_VAL("wrong scale", ev_data->scale = 0.123);33 TEST_ASSERT_VAL("wrong scale", ev_data->scale == 0.123);
34 return 0;34 return 0;
35}35}
36 36
tools/perf/tests/hists_common.c+1−1
@@ -161,7 +161,7 @@ void print_hists_in(struct hists *hists) · 160 unmodified lines
161 struct rb_root *root;161 struct rb_root *root;
162 struct rb_node *node;162 struct rb_node *node;
163 163
164 if (sort__need_collapse)164 if (hists__has(hists, need_collapse))
165 root = &hists->entries_collapsed;165 root = &hists->entries_collapsed;
166 else166 else
167 root = hists->entries_in;167 root = hists->entries_in;
tools/perf/tests/hists_cumulate.c+2−2
@@ -101,7 +101,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) · 100 unmodified lines
101 if (machine__resolve(machine, &al, &sample) < 0)101 if (machine__resolve(machine, &al, &sample) < 0)
102 goto out;102 goto out;
103 103
104 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,104 if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
105 NULL) < 0) {105 NULL) < 0) {
106 addr_location__put(&al);106 addr_location__put(&al);
107 goto out;107 goto out;
@@ -126,7 +126,7 @@ static void del_hist_entries(struct hists *hists) · 18 unmodified lines
126 struct rb_root *root_out;126 struct rb_root *root_out;
127 struct rb_node *node;127 struct rb_node *node;
128 128
129 if (sort__need_collapse)129 if (hists__has(hists, need_collapse))
130 root_in = &hists->entries_collapsed;130 root_in = &hists->entries_collapsed;
131 else131 else
132 root_in = hists->entries_in;132 root_in = hists->entries_in;
tools/perf/tests/hists_filter.c+1−1
@@ -81,7 +81,7 @@ static int add_hist_entries(struct perf_evlist *evlist, · 80 unmodified lines
81 81
82 al.socket = fake_samples[i].socket;82 al.socket = fake_samples[i].socket;
83 if (hist_entry_iter__add(&iter, &al,83 if (hist_entry_iter__add(&iter, &al,
84 PERF_MAX_STACK_DEPTH, NULL) < 0) {84 sysctl_perf_event_max_stack, NULL) < 0) {
85 addr_location__put(&al);85 addr_location__put(&al);
86 goto out;86 goto out;
87 }87 }
tools/perf/tests/hists_link.c+2−2
@@ -145,7 +145,7 @@ static int __validate_match(struct hists *hists) · 144 unmodified lines
145 /*145 /*
146 * Only entries from fake_common_samples should have a pair.146 * Only entries from fake_common_samples should have a pair.
147 */147 */
148 if (sort__need_collapse)148 if (hists__has(hists, need_collapse))
149 root = &hists->entries_collapsed;149 root = &hists->entries_collapsed;
150 else150 else
151 root = hists->entries_in;151 root = hists->entries_in;
@@ -197,7 +197,7 @@ static int __validate_link(struct hists *hists, int idx) · 45 unmodified lines
197 * and some entries will have no pair. However every entry197 * and some entries will have no pair. However every entry
198 * in other hists should have (dummy) pair.198 * in other hists should have (dummy) pair.
199 */199 */
200 if (sort__need_collapse)200 if (hists__has(hists, need_collapse))
201 root = &hists->entries_collapsed;201 root = &hists->entries_collapsed;
202 else202 else
203 root = hists->entries_in;203 root = hists->entries_in;
tools/perf/tests/hists_output.c+2−2
@@ -67,7 +67,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine) · 66 unmodified lines
67 if (machine__resolve(machine, &al, &sample) < 0)67 if (machine__resolve(machine, &al, &sample) < 0)
68 goto out;68 goto out;
69 69
70 if (hist_entry_iter__add(&iter, &al, PERF_MAX_STACK_DEPTH,70 if (hist_entry_iter__add(&iter, &al, sysctl_perf_event_max_stack,
71 NULL) < 0) {71 NULL) < 0) {
72 addr_location__put(&al);72 addr_location__put(&al);
73 goto out;73 goto out;
@@ -92,7 +92,7 @@ static void del_hist_entries(struct hists *hists) · 18 unmodified lines
92 struct rb_root *root_out;92 struct rb_root *root_out;
93 struct rb_node *node;93 struct rb_node *node;
94 94
95 if (sort__need_collapse)95 if (hists__has(hists, need_collapse))
96 root_in = &hists->entries_collapsed;96 root_in = &hists->entries_collapsed;
97 else97 else
98 root_in = hists->entries_in;98 root_in = hists->entries_in;
tools/perf/tests/keep-tracking.c+1−1
@@ -80,7 +80,7 @@ int test__keep_tracking(int subtest __maybe_unused) · 79 unmodified lines
80 CHECK__(parse_events(evlist, "dummy:u", NULL));80 CHECK__(parse_events(evlist, "dummy:u", NULL));
81 CHECK__(parse_events(evlist, "cycles:u", NULL));81 CHECK__(parse_events(evlist, "cycles:u", NULL));
82 82
83 perf_evlist__config(evlist, &opts);83 perf_evlist__config(evlist, &opts, NULL);
84 84
85 evsel = perf_evlist__first(evlist);85 evsel = perf_evlist__first(evlist);
86 86
tools/perf/tests/openat-syscall-tp-fields.c+1−1
@@ -44,7 +44,7 @@ int test__syscall_openat_tp_fields(int subtest __maybe_unused) · 43 unmodified lines
44 goto out_delete_evlist;44 goto out_delete_evlist;
45 }45 }
46 46
47 perf_evsel__config(evsel, &opts);47 perf_evsel__config(evsel, &opts, NULL);
48 48
49 thread_map__set_pid(evlist->threads, 0, getpid());49 thread_map__set_pid(evlist->threads, 0, getpid());
50 50
tools/perf/tests/perf-record.c+1−1
@@ -99,7 +99,7 @@ int test__PERF_RECORD(int subtest __maybe_unused) · 98 unmodified lines
99 perf_evsel__set_sample_bit(evsel, CPU);99 perf_evsel__set_sample_bit(evsel, CPU);
100 perf_evsel__set_sample_bit(evsel, TID);100 perf_evsel__set_sample_bit(evsel, TID);
101 perf_evsel__set_sample_bit(evsel, TIME);101 perf_evsel__set_sample_bit(evsel, TIME);
102 perf_evlist__config(evlist, &opts);102 perf_evlist__config(evlist, &opts, NULL);
103 103
104 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);104 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
105 if (err < 0) {105 if (err < 0) {
tools/perf/tests/switch-tracking.c+1−1
@@ -417,7 +417,7 @@ int test__switch_tracking(int subtest __maybe_unused) · 416 unmodified lines
417 perf_evsel__set_sample_bit(tracking_evsel, TIME);417 perf_evsel__set_sample_bit(tracking_evsel, TIME);
418 418
419 /* Config events */419 /* Config events */
420 perf_evlist__config(evlist, &opts);420 perf_evlist__config(evlist, &opts, NULL);
421 421
422 /* Check moved event is still at the front */422 /* Check moved event is still at the front */
423 if (cycles_evsel != perf_evlist__first(evlist)) {423 if (cycles_evsel != perf_evlist__first(evlist)) {
tools/perf/tests/tests.h+2−0
@@ -85,6 +85,8 @@ int test__synthesize_stat_config(int subtest); · 84 unmodified lines
85int test__synthesize_stat(int subtest);85int test__synthesize_stat(int subtest);
86int test__synthesize_stat_round(int subtest);86int test__synthesize_stat_round(int subtest);
87int test__event_update(int subtest);87int test__event_update(int subtest);
88int test__event_times(int subtest);
89int test__backward_ring_buffer(int subtest);
88 90
89#if defined(__arm__) || defined(__aarch64__)91#if defined(__arm__) || defined(__aarch64__)
90#ifdef HAVE_DWARF_UNWIND_SUPPORT92#ifdef HAVE_DWARF_UNWIND_SUPPORT
tools/perf/tests/vmlinux-kallsyms.c+10−1
@@ -54,8 +54,14 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) · 53 unmodified lines
54 * Step 3:54 * Step 3:
55 *55 *
56 * Load and split /proc/kallsyms into multiple maps, one per module.56 * Load and split /proc/kallsyms into multiple maps, one per module.
57 * Do not use kcore, as this test was designed before kcore support
58 * and has parts that only make sense if using the non-kcore code.
59 * XXX: extend it to stress the kcorre code as well, hint: the list
60 * of modules extracted from /proc/kcore, in its current form, can't
61 * be compacted against the list of modules found in the "vmlinux"
62 * code and with the one got from /proc/modules from the "kallsyms" code.
57 */63 */
58 if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, NULL) <= 0) {64 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true, NULL) <= 0) {
59 pr_debug("dso__load_kallsyms ");65 pr_debug("dso__load_kallsyms ");
60 goto out;66 goto out;
61 }67 }
@@ -157,6 +163,9 @@ next_pair: · 95 unmodified lines
157 163
158 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",164 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
159 mem_start, sym->name, pair->name);165 mem_start, sym->name, pair->name);
166 } else {
167 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n",
168 mem_start, sym->name, first_pair->name);
160 }169 }
161 }170 }
162 } else171 } else
tools/perf/trace/beauty/eventfd.c+38−0
@@ -0,0 +1,38 @@
1#include <sys/eventfd.h>
2
3#ifndef EFD_SEMAPHORE
4#define EFD_SEMAPHORE 1
5#endif
6
7#ifndef EFD_NONBLOCK
8#define EFD_NONBLOCK 00004000
9#endif
10
11#ifndef EFD_CLOEXEC
12#define EFD_CLOEXEC 02000000
13#endif
14
15static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg)
16{
17 int printed = 0, flags = arg->val;
18
19 if (flags == 0)
20 return scnprintf(bf, size, "NONE");
21#define P_FLAG(n) \
22 if (flags & EFD_##n) { \
23 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
24 flags &= ~EFD_##n; \
25 }
26
27 P_FLAG(SEMAPHORE);
28 P_FLAG(CLOEXEC);
29 P_FLAG(NONBLOCK);
30#undef P_FLAG
31
32 if (flags)
33 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
34
35 return printed;
36}
37
38#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
tools/perf/trace/beauty/flock.c+31−0
@@ -0,0 +1,31 @@
1
2static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
3 struct syscall_arg *arg)
4{
5 int printed = 0, op = arg->val;
6
7 if (op == 0)
8 return scnprintf(bf, size, "NONE");
9#define P_CMD(cmd) \
10 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
11 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
12 op &= ~LOCK_##cmd; \
13 }
14
15 P_CMD(SH);
16 P_CMD(EX);
17 P_CMD(NB);
18 P_CMD(UN);
19 P_CMD(MAND);
20 P_CMD(RW);
21 P_CMD(READ);
22 P_CMD(WRITE);
23#undef P_OP
24
25 if (op)
26 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
27
28 return printed;
29}
30
31#define SCA_FLOCK syscall_arg__scnprintf_flock
tools/perf/trace/beauty/futex_op.c+44−0
@@ -0,0 +1,44 @@
1#include <linux/futex.h>
2
3static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
4{
5 enum syscall_futex_args {
6 SCF_UADDR = (1 << 0),
7 SCF_OP = (1 << 1),
8 SCF_VAL = (1 << 2),
9 SCF_TIMEOUT = (1 << 3),
10 SCF_UADDR2 = (1 << 4),
11 SCF_VAL3 = (1 << 5),
12 };
13 int op = arg->val;
14 int cmd = op & FUTEX_CMD_MASK;
15 size_t printed = 0;
16
17 switch (cmd) {
18#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
19 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
20 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
21 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
22 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
23 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
24 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
25 P_FUTEX_OP(WAKE_OP); break;
26 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
27 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
28 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
29 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
30 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
31 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
32 default: printed = scnprintf(bf, size, "%#x", cmd); break;
33 }
34
35 if (op & FUTEX_PRIVATE_FLAG)
36 printed += scnprintf(bf + printed, size - printed, "|PRIV");
37
38 if (op & FUTEX_CLOCK_REALTIME)
39 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
40
41 return printed;
42}
43
44#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
tools/perf/trace/beauty/mmap.c+158−0
@@ -0,0 +1,158 @@
1#include <sys/mman.h>
2
3static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
4 struct syscall_arg *arg)
5{
6 int printed = 0, prot = arg->val;
7
8 if (prot == PROT_NONE)
9 return scnprintf(bf, size, "NONE");
10#define P_MMAP_PROT(n) \
11 if (prot & PROT_##n) { \
12 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
13 prot &= ~PROT_##n; \
14 }
15
16 P_MMAP_PROT(EXEC);
17 P_MMAP_PROT(READ);
18 P_MMAP_PROT(WRITE);
19#ifdef PROT_SEM
20 P_MMAP_PROT(SEM);
21#endif
22 P_MMAP_PROT(GROWSDOWN);
23 P_MMAP_PROT(GROWSUP);
24#undef P_MMAP_PROT
25
26 if (prot)
27 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
28
29 return printed;
30}
31
32#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
33
34#ifndef MAP_STACK
35# define MAP_STACK 0x20000
36#endif
37
38static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
39 struct syscall_arg *arg)
40{
41 int printed = 0, flags = arg->val;
42
43#define P_MMAP_FLAG(n) \
44 if (flags & MAP_##n) { \
45 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
46 flags &= ~MAP_##n; \
47 }
48
49 P_MMAP_FLAG(SHARED);
50 P_MMAP_FLAG(PRIVATE);
51#ifdef MAP_32BIT
52 P_MMAP_FLAG(32BIT);
53#endif
54 P_MMAP_FLAG(ANONYMOUS);
55 P_MMAP_FLAG(DENYWRITE);
56 P_MMAP_FLAG(EXECUTABLE);
57 P_MMAP_FLAG(FILE);
58 P_MMAP_FLAG(FIXED);
59 P_MMAP_FLAG(GROWSDOWN);
60#ifdef MAP_HUGETLB
61 P_MMAP_FLAG(HUGETLB);
62#endif
63 P_MMAP_FLAG(LOCKED);
64 P_MMAP_FLAG(NONBLOCK);
65 P_MMAP_FLAG(NORESERVE);
66 P_MMAP_FLAG(POPULATE);
67 P_MMAP_FLAG(STACK);
68#ifdef MAP_UNINITIALIZED
69 P_MMAP_FLAG(UNINITIALIZED);
70#endif
71#undef P_MMAP_FLAG
72
73 if (flags)
74 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
75
76 return printed;
77}
78
79#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
80
81static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
82 struct syscall_arg *arg)
83{
84 int printed = 0, flags = arg->val;
85
86#define P_MREMAP_FLAG(n) \
87 if (flags & MREMAP_##n) { \
88 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
89 flags &= ~MREMAP_##n; \
90 }
91
92 P_MREMAP_FLAG(MAYMOVE);
93#ifdef MREMAP_FIXED
94 P_MREMAP_FLAG(FIXED);
95#endif
96#undef P_MREMAP_FLAG
97
98 if (flags)
99 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
100
101 return printed;
102}
103
104#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
105
106#ifndef MADV_HWPOISON
107#define MADV_HWPOISON 100
108#endif
109
110#ifndef MADV_MERGEABLE
111#define MADV_MERGEABLE 12
112#endif
113
114#ifndef MADV_UNMERGEABLE
115#define MADV_UNMERGEABLE 13
116#endif
117
118static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
119 struct syscall_arg *arg)
120{
121 int behavior = arg->val;
122
123 switch (behavior) {
124#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
125 P_MADV_BHV(NORMAL);
126 P_MADV_BHV(RANDOM);
127 P_MADV_BHV(SEQUENTIAL);
128 P_MADV_BHV(WILLNEED);
129 P_MADV_BHV(DONTNEED);
130 P_MADV_BHV(REMOVE);
131 P_MADV_BHV(DONTFORK);
132 P_MADV_BHV(DOFORK);
133 P_MADV_BHV(HWPOISON);
134#ifdef MADV_SOFT_OFFLINE
135 P_MADV_BHV(SOFT_OFFLINE);
136#endif
137 P_MADV_BHV(MERGEABLE);
138 P_MADV_BHV(UNMERGEABLE);
139#ifdef MADV_HUGEPAGE
140 P_MADV_BHV(HUGEPAGE);
141#endif
142#ifdef MADV_NOHUGEPAGE
143 P_MADV_BHV(NOHUGEPAGE);
144#endif
145#ifdef MADV_DONTDUMP
146 P_MADV_BHV(DONTDUMP);
147#endif
148#ifdef MADV_DODUMP
149 P_MADV_BHV(DODUMP);
150#endif
151#undef P_MADV_PHV
152 default: break;
153 }
154
155 return scnprintf(bf, size, "%#x", behavior);
156}
157
158#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
tools/perf/trace/beauty/mode_t.c+68−0
@@ -0,0 +1,68 @@
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <unistd.h>
4
5/* From include/linux/stat.h */
6#ifndef S_IRWXUGO
7#define S_IRWXUGO (S_IRWXU|S_IRWXG|S_IRWXO)
8#endif
9#ifndef S_IALLUGO
10#define S_IALLUGO (S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO)
11#endif
12#ifndef S_IRUGO
13#define S_IRUGO (S_IRUSR|S_IRGRP|S_IROTH)
14#endif
15#ifndef S_IWUGO
16#define S_IWUGO (S_IWUSR|S_IWGRP|S_IWOTH)
17#endif
18#ifndef S_IXUGO
19#define S_IXUGO (S_IXUSR|S_IXGRP|S_IXOTH)
20#endif
21
22static size_t syscall_arg__scnprintf_mode_t(char *bf, size_t size, struct syscall_arg *arg)
23{
24 int printed = 0, mode = arg->val;
25
26#define P_MODE(n) \
27 if ((mode & S_##n) == S_##n) { \
28 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
29 mode &= ~S_##n; \
30 }
31
32 P_MODE(IALLUGO);
33 P_MODE(IRWXUGO);
34 P_MODE(IRUGO);
35 P_MODE(IWUGO);
36 P_MODE(IXUGO);
37 P_MODE(IFMT);
38 P_MODE(IFSOCK);
39 P_MODE(IFLNK);
40 P_MODE(IFREG);
41 P_MODE(IFBLK);
42 P_MODE(IFDIR);
43 P_MODE(IFCHR);
44 P_MODE(IFIFO);
45 P_MODE(ISUID);
46 P_MODE(ISGID);
47 P_MODE(ISVTX);
48 P_MODE(IRWXU);
49 P_MODE(IRUSR);
50 P_MODE(IWUSR);
51 P_MODE(IXUSR);
52 P_MODE(IRWXG);
53 P_MODE(IRGRP);
54 P_MODE(IWGRP);
55 P_MODE(IXGRP);
56 P_MODE(IRWXO);
57 P_MODE(IROTH);
58 P_MODE(IWOTH);
59 P_MODE(IXOTH);
60#undef P_MODE
61
62 if (mode)
63 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", mode);
64
65 return printed;
66}
67
68#define SCA_MODE_T syscall_arg__scnprintf_mode_t
tools/perf/trace/beauty/msg_flags.c+62−0
@@ -0,0 +1,62 @@
1#include <sys/types.h>
2#include <sys/socket.h>
3
4#ifndef MSG_PROBE
5#define MSG_PROBE 0x10
6#endif
7#ifndef MSG_WAITFORONE
8#define MSG_WAITFORONE 0x10000
9#endif
10#ifndef MSG_SENDPAGE_NOTLAST
11#define MSG_SENDPAGE_NOTLAST 0x20000
12#endif
13#ifndef MSG_FASTOPEN
14#define MSG_FASTOPEN 0x20000000
15#endif
16#ifndef MSG_CMSG_CLOEXEC
17# define MSG_CMSG_CLOEXEC 0x40000000
18#endif
19
20static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
21 struct syscall_arg *arg)
22{
23 int printed = 0, flags = arg->val;
24
25 if (flags == 0)
26 return scnprintf(bf, size, "NONE");
27#define P_MSG_FLAG(n) \
28 if (flags & MSG_##n) { \
29 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
30 flags &= ~MSG_##n; \
31 }
32
33 P_MSG_FLAG(OOB);
34 P_MSG_FLAG(PEEK);
35 P_MSG_FLAG(DONTROUTE);
36 P_MSG_FLAG(TRYHARD);
37 P_MSG_FLAG(CTRUNC);
38 P_MSG_FLAG(PROBE);
39 P_MSG_FLAG(TRUNC);
40 P_MSG_FLAG(DONTWAIT);
41 P_MSG_FLAG(EOR);
42 P_MSG_FLAG(WAITALL);
43 P_MSG_FLAG(FIN);
44 P_MSG_FLAG(SYN);
45 P_MSG_FLAG(CONFIRM);
46 P_MSG_FLAG(RST);
47 P_MSG_FLAG(ERRQUEUE);
48 P_MSG_FLAG(NOSIGNAL);
49 P_MSG_FLAG(MORE);
50 P_MSG_FLAG(WAITFORONE);
51 P_MSG_FLAG(SENDPAGE_NOTLAST);
52 P_MSG_FLAG(FASTOPEN);
53 P_MSG_FLAG(CMSG_CLOEXEC);
54#undef P_MSG_FLAG
55
56 if (flags)
57 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
58
59 return printed;
60}
61
62#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
tools/perf/trace/beauty/open_flags.c+56−0
@@ -0,0 +1,56 @@
1
2static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
3 struct syscall_arg *arg)
4{
5 int printed = 0, flags = arg->val;
6
7 if (!(flags & O_CREAT))
8 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
9
10 if (flags == 0)
11 return scnprintf(bf, size, "RDONLY");
12#define P_FLAG(n) \
13 if (flags & O_##n) { \
14 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
15 flags &= ~O_##n; \
16 }
17
18 P_FLAG(APPEND);
19 P_FLAG(ASYNC);
20 P_FLAG(CLOEXEC);
21 P_FLAG(CREAT);
22 P_FLAG(DIRECT);
23 P_FLAG(DIRECTORY);
24 P_FLAG(EXCL);
25 P_FLAG(LARGEFILE);
26 P_FLAG(NOATIME);
27 P_FLAG(NOCTTY);
28#ifdef O_NONBLOCK
29 P_FLAG(NONBLOCK);
30#elif O_NDELAY
31 P_FLAG(NDELAY);
32#endif
33#ifdef O_PATH
34 P_FLAG(PATH);
35#endif
36 P_FLAG(RDWR);
37#ifdef O_DSYNC
38 if ((flags & O_SYNC) == O_SYNC)
39 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
40 else {
41 P_FLAG(DSYNC);
42 }
43#else
44 P_FLAG(SYNC);
45#endif
46 P_FLAG(TRUNC);
47 P_FLAG(WRONLY);
48#undef P_FLAG
49
50 if (flags)
51 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
52
53 return printed;
54}
55
56#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
tools/perf/trace/beauty/perf_event_open.c+43−0
@@ -0,0 +1,43 @@
1#ifndef PERF_FLAG_FD_NO_GROUP
2# define PERF_FLAG_FD_NO_GROUP (1UL << 0)
3#endif
4
5#ifndef PERF_FLAG_FD_OUTPUT
6# define PERF_FLAG_FD_OUTPUT (1UL << 1)
7#endif
8
9#ifndef PERF_FLAG_PID_CGROUP
10# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
11#endif
12
13#ifndef PERF_FLAG_FD_CLOEXEC
14# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
15#endif
16
17static size_t syscall_arg__scnprintf_perf_flags(char *bf, size_t size,
18 struct syscall_arg *arg)
19{
20 int printed = 0, flags = arg->val;
21
22 if (flags == 0)
23 return 0;
24
25#define P_FLAG(n) \
26 if (flags & PERF_FLAG_##n) { \
27 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
28 flags &= ~PERF_FLAG_##n; \
29 }
30
31 P_FLAG(FD_NO_GROUP);
32 P_FLAG(FD_OUTPUT);
33 P_FLAG(PID_CGROUP);
34 P_FLAG(FD_CLOEXEC);
35#undef P_FLAG
36
37 if (flags)
38 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
39
40 return printed;
41}
42
43#define SCA_PERF_FLAGS syscall_arg__scnprintf_perf_flags
tools/perf/trace/beauty/pid.c+21−0
@@ -0,0 +1,21 @@
1static size_t syscall_arg__scnprintf_pid(char *bf, size_t size, struct syscall_arg *arg)
2{
3 int pid = arg->val;
4 struct trace *trace = arg->trace;
5 size_t printed = scnprintf(bf, size, "%d", pid);
6 struct thread *thread = machine__findnew_thread(trace->host, pid, pid);
7
8 if (thread != NULL) {
9 if (!thread->comm_set)
10 thread__set_comm_from_proc(thread);
11
12 if (thread->comm_set)
13 printed += scnprintf(bf + printed, size - printed,
14 " (%s)", thread__comm_str(thread));
15 thread__put(thread);
16 }
17
18 return printed;
19}
20
21#define SCA_PID syscall_arg__scnprintf_pid
tools/perf/trace/beauty/sched_policy.c+44−0
@@ -0,0 +1,44 @@
1#include <sched.h>
2
3/*
4 * Not defined anywhere else, probably, just to make sure we
5 * catch future flags
6 */
7#define SCHED_POLICY_MASK 0xff
8
9#ifndef SCHED_DEADLINE
10#define SCHED_DEADLINE 6
11#endif
12
13static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size,
14 struct syscall_arg *arg)
15{
16 const char *policies[] = {
17 "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "DEADLINE",
18 };
19 size_t printed;
20 int policy = arg->val,
21 flags = policy & ~SCHED_POLICY_MASK;
22
23 policy &= SCHED_POLICY_MASK;
24 if (policy <= SCHED_DEADLINE)
25 printed = scnprintf(bf, size, "%s", policies[policy]);
26 else
27 printed = scnprintf(bf, size, "%#x", policy);
28
29#define P_POLICY_FLAG(n) \
30 if (flags & SCHED_##n) { \
31 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
32 flags &= ~SCHED_##n; \
33 }
34
35 P_POLICY_FLAG(RESET_ON_FORK);
36#undef P_POLICY_FLAG
37
38 if (flags)
39 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
40
41 return printed;
42}
43
44#define SCA_SCHED_POLICY syscall_arg__scnprintf_sched_policy
tools/perf/trace/beauty/seccomp.c+52−0
@@ -0,0 +1,52 @@
1#include <linux/seccomp.h>
2
3#ifndef SECCOMP_SET_MODE_STRICT
4#define SECCOMP_SET_MODE_STRICT 0
5#endif
6#ifndef SECCOMP_SET_MODE_FILTER
7#define SECCOMP_SET_MODE_FILTER 1
8#endif
9
10static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
11{
12 int op = arg->val;
13 size_t printed = 0;
14
15 switch (op) {
16#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
17 P_SECCOMP_SET_MODE_OP(STRICT);
18 P_SECCOMP_SET_MODE_OP(FILTER);
19#undef P_SECCOMP_SET_MODE_OP
20 default: printed = scnprintf(bf, size, "%#x", op); break;
21 }
22
23 return printed;
24}
25
26#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
27
28#ifndef SECCOMP_FILTER_FLAG_TSYNC
29#define SECCOMP_FILTER_FLAG_TSYNC 1
30#endif
31
32static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
33 struct syscall_arg *arg)
34{
35 int printed = 0, flags = arg->val;
36
37#define P_FLAG(n) \
38 if (flags & SECCOMP_FILTER_FLAG_##n) { \
39 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
40 flags &= ~SECCOMP_FILTER_FLAG_##n; \
41 }
42
43 P_FLAG(TSYNC);
44#undef P_FLAG
45
46 if (flags)
47 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
48
49 return printed;
50}
51
52#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
tools/perf/trace/beauty/signum.c+53−0
@@ -0,0 +1,53 @@
1
2static size_t syscall_arg__scnprintf_signum(char *bf, size_t size, struct syscall_arg *arg)
3{
4 int sig = arg->val;
5
6 switch (sig) {
7#define P_SIGNUM(n) case SIG##n: return scnprintf(bf, size, #n)
8 P_SIGNUM(HUP);
9 P_SIGNUM(INT);
10 P_SIGNUM(QUIT);
11 P_SIGNUM(ILL);
12 P_SIGNUM(TRAP);
13 P_SIGNUM(ABRT);
14 P_SIGNUM(BUS);
15 P_SIGNUM(FPE);
16 P_SIGNUM(KILL);
17 P_SIGNUM(USR1);
18 P_SIGNUM(SEGV);
19 P_SIGNUM(USR2);
20 P_SIGNUM(PIPE);
21 P_SIGNUM(ALRM);
22 P_SIGNUM(TERM);
23 P_SIGNUM(CHLD);
24 P_SIGNUM(CONT);
25 P_SIGNUM(STOP);
26 P_SIGNUM(TSTP);
27 P_SIGNUM(TTIN);
28 P_SIGNUM(TTOU);
29 P_SIGNUM(URG);
30 P_SIGNUM(XCPU);
31 P_SIGNUM(XFSZ);
32 P_SIGNUM(VTALRM);
33 P_SIGNUM(PROF);
34 P_SIGNUM(WINCH);
35 P_SIGNUM(IO);
36 P_SIGNUM(PWR);
37 P_SIGNUM(SYS);
38#ifdef SIGEMT
39 P_SIGNUM(EMT);
40#endif
41#ifdef SIGSTKFLT
42 P_SIGNUM(STKFLT);
43#endif
44#ifdef SIGSWI
45 P_SIGNUM(SWI);
46#endif
47 default: break;
48 }
49
50 return scnprintf(bf, size, "%#x", sig);
51}
52
53#define SCA_SIGNUM syscall_arg__scnprintf_signum
tools/perf/trace/beauty/socket_type.c+60−0
@@ -0,0 +1,60 @@
1#include <sys/types.h>
2#include <sys/socket.h>
3
4#ifndef SOCK_DCCP
5# define SOCK_DCCP 6
6#endif
7
8#ifndef SOCK_CLOEXEC
9# define SOCK_CLOEXEC 02000000
10#endif
11
12#ifndef SOCK_NONBLOCK
13# define SOCK_NONBLOCK 00004000
14#endif
15
16#ifndef SOCK_TYPE_MASK
17#define SOCK_TYPE_MASK 0xf
18#endif
19
20static size_t syscall_arg__scnprintf_socket_type(char *bf, size_t size, struct syscall_arg *arg)
21{
22 size_t printed;
23 int type = arg->val,
24 flags = type & ~SOCK_TYPE_MASK;
25
26 type &= SOCK_TYPE_MASK;
27 /*
28 * Can't use a strarray, MIPS may override for ABI reasons.
29 */
30 switch (type) {
31#define P_SK_TYPE(n) case SOCK_##n: printed = scnprintf(bf, size, #n); break;
32 P_SK_TYPE(STREAM);
33 P_SK_TYPE(DGRAM);
34 P_SK_TYPE(RAW);
35 P_SK_TYPE(RDM);
36 P_SK_TYPE(SEQPACKET);
37 P_SK_TYPE(DCCP);
38 P_SK_TYPE(PACKET);
39#undef P_SK_TYPE
40 default:
41 printed = scnprintf(bf, size, "%#x", type);
42 }
43
44#define P_SK_FLAG(n) \
45 if (flags & SOCK_##n) { \
46 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
47 flags &= ~SOCK_##n; \
48 }
49
50 P_SK_FLAG(CLOEXEC);
51 P_SK_FLAG(NONBLOCK);
52#undef P_SK_FLAG
53
54 if (flags)
55 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
56
57 return printed;
58}
59
60#define SCA_SK_TYPE syscall_arg__scnprintf_socket_type
tools/perf/trace/beauty/waitid_options.c+26−0
@@ -0,0 +1,26 @@
1#include <sys/types.h>
2#include <sys/wait.h>
3
4static size_t syscall_arg__scnprintf_waitid_options(char *bf, size_t size,
5 struct syscall_arg *arg)
6{
7 int printed = 0, options = arg->val;
8
9#define P_OPTION(n) \
10 if (options & W##n) { \
11 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
12 options &= ~W##n; \
13 }
14
15 P_OPTION(NOHANG);
16 P_OPTION(UNTRACED);
17 P_OPTION(CONTINUED);
18#undef P_OPTION
19
20 if (options)
21 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", options);
22
23 return printed;
24}
25
26#define SCA_WAITID_OPTIONS syscall_arg__scnprintf_waitid_options
tools/perf/ui/browsers/hists.c+20−20
@@ -1607,9 +1607,8 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows · 1606 unmodified lines
1607 1607
1608 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));1608 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists));
1609 dummy_hpp.buf[ret] = '\0';1609 dummy_hpp.buf[ret] = '\0';
1610 rtrim(dummy_hpp.buf);
1611 1610
1612 start = ltrim(dummy_hpp.buf);1611 start = trim(dummy_hpp.buf);
1613 ret = strlen(start);1612 ret = strlen(start);
1614 1613
1615 if (start != dummy_hpp.buf)1614 if (start != dummy_hpp.buf)
@@ -1897,11 +1896,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser, · 281 unmodified lines
1897 bool first = true;1896 bool first = true;
1898 int ret;1897 int ret;
1899 1898
1900 if (symbol_conf.use_callchain)1899 if (symbol_conf.use_callchain) {
1901 folded_sign = hist_entry__folded(he);1900 folded_sign = hist_entry__folded(he);
1902
1903 if (symbol_conf.use_callchain)
1904 printed += fprintf(fp, "%c ", folded_sign);1901 printed += fprintf(fp, "%c ", folded_sign);
1902 }
1905 1903
1906 hists__for_each_format(browser->hists, fmt) {1904 hists__for_each_format(browser->hists, fmt) {
1907 if (perf_hpp__should_skip(fmt, he->hists))1905 if (perf_hpp__should_skip(fmt, he->hists))
@@ -2137,7 +2135,7 @@ static int hists__browser_title(struct hists *hists, · 229 unmodified lines
2137 printed += snprintf(bf + printed, size - printed,2135 printed += snprintf(bf + printed, size - printed,
2138 ", UID: %s", hists->uid_filter_str);2136 ", UID: %s", hists->uid_filter_str);
2139 if (thread) {2137 if (thread) {
2140 if (sort__has_thread) {2138 if (hists__has(hists, thread)) {
2141 printed += scnprintf(bf + printed, size - printed,2139 printed += scnprintf(bf + printed, size - printed,
2142 ", Thread: %s(%d)",2140 ", Thread: %s(%d)",
2143 (thread->comm_set ? thread__comm_str(thread) : ""),2141 (thread->comm_set ? thread__comm_str(thread) : ""),
@@ -2322,7 +2320,8 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act) · 178 unmodified lines
2322{2320{
2323 struct thread *thread = act->thread;2321 struct thread *thread = act->thread;
2324 2322
2325 if ((!sort__has_thread && !sort__has_comm) || thread == NULL)2323 if ((!hists__has(browser->hists, thread) &&
2324 !hists__has(browser->hists, comm)) || thread == NULL)
2326 return 0;2325 return 0;
2327 2326
2328 if (browser->hists->thread_filter) {2327 if (browser->hists->thread_filter) {
@@ -2331,7 +2330,7 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act) · 2 unmodified lines
2331 thread__zput(browser->hists->thread_filter);2330 thread__zput(browser->hists->thread_filter);
2332 ui_helpline__pop();2331 ui_helpline__pop();
2333 } else {2332 } else {
2334 if (sort__has_thread) {2333 if (hists__has(browser->hists, thread)) {
2335 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"",2334 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"",
2336 thread->comm_set ? thread__comm_str(thread) : "",2335 thread->comm_set ? thread__comm_str(thread) : "",
2337 thread->tid);2336 thread->tid);
@@ -2356,10 +2355,11 @@ add_thread_opt(struct hist_browser *browser, struct popup_action *act, · 18 unmodified lines
2356{2355{
2357 int ret;2356 int ret;
2358 2357
2359 if ((!sort__has_thread && !sort__has_comm) || thread == NULL)2358 if ((!hists__has(browser->hists, thread) &&
2359 !hists__has(browser->hists, comm)) || thread == NULL)
2360 return 0;2360 return 0;
2361 2361
2362 if (sort__has_thread) {2362 if (hists__has(browser->hists, thread)) {
2363 ret = asprintf(optstr, "Zoom %s %s(%d) thread",2363 ret = asprintf(optstr, "Zoom %s %s(%d) thread",
2364 browser->hists->thread_filter ? "out of" : "into",2364 browser->hists->thread_filter ? "out of" : "into",
2365 thread->comm_set ? thread__comm_str(thread) : "",2365 thread->comm_set ? thread__comm_str(thread) : "",
@@ -2382,7 +2382,7 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act) · 16 unmodified lines
2382{2382{
2383 struct map *map = act->ms.map;2383 struct map *map = act->ms.map;
2384 2384
2385 if (!sort__has_dso || map == NULL)2385 if (!hists__has(browser->hists, dso) || map == NULL)
2386 return 0;2386 return 0;
2387 2387
2388 if (browser->hists->dso_filter) {2388 if (browser->hists->dso_filter) {
@@ -2409,7 +2409,7 @@ static int · 20 unmodified lines
2409add_dso_opt(struct hist_browser *browser, struct popup_action *act,2409add_dso_opt(struct hist_browser *browser, struct popup_action *act,
2410 char **optstr, struct map *map)2410 char **optstr, struct map *map)
2411{2411{
2412 if (!sort__has_dso || map == NULL)2412 if (!hists__has(browser->hists, dso) || map == NULL)
2413 return 0;2413 return 0;
2414 2414
2415 if (asprintf(optstr, "Zoom %s %s DSO",2415 if (asprintf(optstr, "Zoom %s %s DSO",
@@ -2431,10 +2431,10 @@ do_browse_map(struct hist_browser *browser __maybe_unused, · 15 unmodified lines
2431}2431}
2432 2432
2433static int2433static int
2434add_map_opt(struct hist_browser *browser __maybe_unused,2434add_map_opt(struct hist_browser *browser,
2435 struct popup_action *act, char **optstr, struct map *map)2435 struct popup_action *act, char **optstr, struct map *map)
2436{2436{
2437 if (!sort__has_dso || map == NULL)2437 if (!hists__has(browser->hists, dso) || map == NULL)
2438 return 0;2438 return 0;
2439 2439
2440 if (asprintf(optstr, "Browse map details") < 0)2440 if (asprintf(optstr, "Browse map details") < 0)
@@ -2536,7 +2536,7 @@ add_exit_opt(struct hist_browser *browser __maybe_unused, · 95 unmodified lines
2536static int2536static int
2537do_zoom_socket(struct hist_browser *browser, struct popup_action *act)2537do_zoom_socket(struct hist_browser *browser, struct popup_action *act)
2538{2538{
2539 if (!sort__has_socket || act->socket < 0)2539 if (!hists__has(browser->hists, socket) || act->socket < 0)
2540 return 0;2540 return 0;
2541 2541
2542 if (browser->hists->socket_filter > -1) {2542 if (browser->hists->socket_filter > -1) {
@@ -2558,7 +2558,7 @@ static int · 15 unmodified lines
2558add_socket_opt(struct hist_browser *browser, struct popup_action *act,2558add_socket_opt(struct hist_browser *browser, struct popup_action *act,
2559 char **optstr, int socket_id)2559 char **optstr, int socket_id)
2560{2560{
2561 if (!sort__has_socket || socket_id < 0)2561 if (!hists__has(browser->hists, socket) || socket_id < 0)
2562 return 0;2562 return 0;
2563 2563
2564 if (asprintf(optstr, "Zoom %s Processor Socket %d",2564 if (asprintf(optstr, "Zoom %s Processor Socket %d",
@@ -2749,7 +2749,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, · 184 unmodified lines
2749 */2749 */
2750 goto out_free_stack;2750 goto out_free_stack;
2751 case 'a':2751 case 'a':
2752 if (!sort__has_sym) {2752 if (!hists__has(hists, sym)) {
2753 ui_browser__warning(&browser->b, delay_secs * 2,2753 ui_browser__warning(&browser->b, delay_secs * 2,
2754 "Annotation is only available for symbolic views, "2754 "Annotation is only available for symbolic views, "
2755 "include \"sym*\" in --sort to use it.");2755 "include \"sym*\" in --sort to use it.");
@@ -2912,7 +2912,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events, · 156 unmodified lines
2912 continue;2912 continue;
2913 }2913 }
2914 2914
2915 if (!sort__has_sym || browser->selection == NULL)2915 if (!hists__has(hists, sym) || browser->selection == NULL)
2916 goto skip_annotation;2916 goto skip_annotation;
2917 2917
2918 if (sort__mode == SORT_MODE__BRANCH) {2918 if (sort__mode == SORT_MODE__BRANCH) {
@@ -2956,7 +2956,7 @@ skip_annotation: · 37 unmodified lines
2956 goto skip_scripting;2956 goto skip_scripting;
2957 2957
2958 if (browser->he_selection) {2958 if (browser->he_selection) {
2959 if (sort__has_thread && thread) {2959 if (hists__has(hists, thread) && thread) {
2960 nr_options += add_script_opt(browser,2960 nr_options += add_script_opt(browser,
2961 &actions[nr_options],2961 &actions[nr_options],
2962 &options[nr_options],2962 &options[nr_options],
@@ -2971,7 +2971,7 @@ skip_annotation: · 8 unmodified lines
2971 *2971 *
2972 * See hist_browser__show_entry.2972 * See hist_browser__show_entry.
2973 */2973 */
2974 if (sort__has_sym && browser->selection->sym) {2974 if (hists__has(hists, sym) && browser->selection->sym) {
2975 nr_options += add_script_opt(browser,2975 nr_options += add_script_opt(browser,
2976 &actions[nr_options],2976 &actions[nr_options],
2977 &options[nr_options],2977 &options[nr_options],
tools/perf/ui/gtk/hists.c+1−1
@@ -379,7 +379,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists, · 378 unmodified lines
379 gtk_tree_store_set(store, &iter, col_idx++, s, -1);379 gtk_tree_store_set(store, &iter, col_idx++, s, -1);
380 }380 }
381 381
382 if (symbol_conf.use_callchain && sort__has_sym) {382 if (symbol_conf.use_callchain && hists__has(hists, sym)) {
383 if (callchain_param.mode == CHAIN_GRAPH_REL)383 if (callchain_param.mode == CHAIN_GRAPH_REL)
384 total = symbol_conf.cumulate_callchain ?384 total = symbol_conf.cumulate_callchain ?
385 h->stat_acc->period : h->stat.period;385 h->stat_acc->period : h->stat.period;
tools/perf/ui/hist.c+1−1
@@ -635,7 +635,7 @@ unsigned int hists__sort_list_width(struct hists *hists) · 634 unmodified lines
635 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));635 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists));
636 }636 }
637 637
638 if (verbose && sort__has_sym) /* Addr + origin */638 if (verbose && hists__has(hists, sym)) /* Addr + origin */
639 ret += 3 + BITS_PER_LONG / 4;639 ret += 3 + BITS_PER_LONG / 4;
640 640
641 return ret;641 return ret;
tools/perf/ui/stdio/hist.c+1−2
@@ -569,9 +569,8 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, · 568 unmodified lines
569 first_col = false;569 first_col = false;
570 570
571 fmt->header(fmt, hpp, hists_to_evsel(hists));571 fmt->header(fmt, hpp, hists_to_evsel(hists));
572 rtrim(hpp->buf);
573 572
574 header_width += fprintf(fp, "%s", ltrim(hpp->buf));573 header_width += fprintf(fp, "%s", trim(hpp->buf));
575 }574 }
576 }575 }
577 576
tools/perf/util/Build+5−3
@@ -8,6 +8,7 @@ libperf-y += env.o · 7 unmodified lines
8libperf-y += event.o8libperf-y += event.o
9libperf-y += evlist.o9libperf-y += evlist.o
10libperf-y += evsel.o10libperf-y += evsel.o
11libperf-y += evsel_fprintf.o
11libperf-y += find_bit.o12libperf-y += find_bit.o
12libperf-y += kallsyms.o13libperf-y += kallsyms.o
13libperf-y += levenshtein.o14libperf-y += levenshtein.o
@@ -26,9 +27,9 @@ libperf-y += strlist.o · 12 unmodified lines
26libperf-y += strfilter.o27libperf-y += strfilter.o
27libperf-y += top.o28libperf-y += top.o
28libperf-y += usage.o29libperf-y += usage.o
29libperf-y += wrapper.o
30libperf-y += dso.o30libperf-y += dso.o
31libperf-y += symbol.o31libperf-y += symbol.o
32libperf-y += symbol_fprintf.o
32libperf-y += color.o33libperf-y += color.o
33libperf-y += header.o34libperf-y += header.o
34libperf-y += callchain.o35libperf-y += callchain.o
@@ -38,6 +39,7 @@ libperf-y += machine.o · 3 unmodified lines
38libperf-y += map.o39libperf-y += map.o
39libperf-y += pstack.o40libperf-y += pstack.o
40libperf-y += session.o41libperf-y += session.o
42libperf-$(CONFIG_AUDIT) += syscalltbl.o
41libperf-y += ordered-events.o43libperf-y += ordered-events.o
42libperf-y += comm.o44libperf-y += comm.o
43libperf-y += thread.o45libperf-y += thread.o
@@ -69,9 +71,9 @@ libperf-y += stat-shadow.o · 25 unmodified lines
69libperf-y += record.o71libperf-y += record.o
70libperf-y += srcline.o72libperf-y += srcline.o
71libperf-y += data.o73libperf-y += data.o
72libperf-$(CONFIG_X86) += tsc.o74libperf-y += tsc.o
73libperf-$(CONFIG_AUXTRACE) += tsc.o
74libperf-y += cloexec.o75libperf-y += cloexec.o
76libperf-y += call-path.o
75libperf-y += thread-stack.o77libperf-y += thread-stack.o
76libperf-$(CONFIG_AUXTRACE) += auxtrace.o78libperf-$(CONFIG_AUXTRACE) += auxtrace.o
77libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/79libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
tools/perf/util/annotate.c+2−2
@@ -1138,7 +1138,7 @@ fallback: · 1137 unmodified lines
1138 1138
1139 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&1139 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1140 !dso__is_kcore(dso)) {1140 !dso__is_kcore(dso)) {
1141 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";1141 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1142 char *build_id_msg = NULL;1142 char *build_id_msg = NULL;
1143 1143
1144 if (dso->annotate_warned)1144 if (dso->annotate_warned)
@@ -1665,5 +1665,5 @@ int hist_entry__annotate(struct hist_entry *he, size_t privsize) · 520 unmodified lines
1665 1665
1666bool ui__has_annotation(void)1666bool ui__has_annotation(void)
1667{1667{
1668 return use_browser == 1 && sort__has_sym;1668 return use_browser == 1 && perf_hpp_list.sym;
1669}1669}
tools/perf/util/auxtrace.c+7−0
@@ -940,6 +940,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts) · 939 unmodified lines
940 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;940 synth_opts->period = PERF_ITRACE_DEFAULT_PERIOD;
941 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;941 synth_opts->callchain_sz = PERF_ITRACE_DEFAULT_CALLCHAIN_SZ;
942 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;942 synth_opts->last_branch_sz = PERF_ITRACE_DEFAULT_LAST_BRANCH_SZ;
943 synth_opts->initial_skip = 0;
943}944}
944 945
945/*946/*
@@ -1064,6 +1065,12 @@ int itrace_parse_synth_opts(const struct option *opt, const char *str, · 118 unmodified lines
1064 synth_opts->last_branch_sz = val;1065 synth_opts->last_branch_sz = val;
1065 }1066 }
1066 break;1067 break;
1068 case 's':
1069 synth_opts->initial_skip = strtoul(p, &endptr, 10);
1070 if (p == endptr)
1071 goto out_err;
1072 p = endptr;
1073 break;
1067 case ' ':1074 case ' ':
1068 case ',':1075 case ',':
1069 break;1076 break;
tools/perf/util/auxtrace.h+2−0
@@ -68,6 +68,7 @@ enum itrace_period_type { · 67 unmodified lines
68 * @last_branch_sz: branch context size68 * @last_branch_sz: branch context size
69 * @period: 'instructions' events period69 * @period: 'instructions' events period
70 * @period_type: 'instructions' events period type70 * @period_type: 'instructions' events period type
71 * @initial_skip: skip N events at the beginning.
71 */72 */
72struct itrace_synth_opts {73struct itrace_synth_opts {
73 bool set;74 bool set;
@@ -86,6 +87,7 @@ struct itrace_synth_opts { · 12 unmodified lines
86 unsigned int last_branch_sz;87 unsigned int last_branch_sz;
87 unsigned long long period;88 unsigned long long period;
88 enum itrace_period_type period_type;89 enum itrace_period_type period_type;
90 unsigned long initial_skip;
89};91};
90 92
91/**93/**
tools/perf/util/bpf-loader.c+143−0
@@ -842,6 +842,58 @@ bpf_map_op__new(struct parse_events_term *term) · 841 unmodified lines
842 return op;842 return op;
843}843}
844 844
845static struct bpf_map_op *
846bpf_map_op__clone(struct bpf_map_op *op)
847{
848 struct bpf_map_op *newop;
849
850 newop = memdup(op, sizeof(*op));
851 if (!newop) {
852 pr_debug("Failed to alloc bpf_map_op\n");
853 return NULL;
854 }
855
856 INIT_LIST_HEAD(&newop->list);
857 if (op->key_type == BPF_MAP_KEY_RANGES) {
858 size_t memsz = op->k.array.nr_ranges *
859 sizeof(op->k.array.ranges[0]);
860
861 newop->k.array.ranges = memdup(op->k.array.ranges, memsz);
862 if (!newop->k.array.ranges) {
863 pr_debug("Failed to alloc indices for map\n");
864 free(newop);
865 return NULL;
866 }
867 }
868
869 return newop;
870}
871
872static struct bpf_map_priv *
873bpf_map_priv__clone(struct bpf_map_priv *priv)
874{
875 struct bpf_map_priv *newpriv;
876 struct bpf_map_op *pos, *newop;
877
878 newpriv = zalloc(sizeof(*newpriv));
879 if (!newpriv) {
880 pr_debug("No enough memory to alloc map private\n");
881 return NULL;
882 }
883 INIT_LIST_HEAD(&newpriv->ops_list);
884
885 list_for_each_entry(pos, &priv->ops_list, list) {
886 newop = bpf_map_op__clone(pos);
887 if (!newop) {
888 bpf_map_priv__purge(newpriv);
889 return NULL;
890 }
891 list_add_tail(&newop->list, &newpriv->ops_list);
892 }
893
894 return newpriv;
895}
896
845static int897static int
846bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)898bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
847{899{
@@ -1417,6 +1469,89 @@ int bpf__apply_obj_config(void) · 569 unmodified lines
1417 return 0;1469 return 0;
1418}1470}
1419 1471
1472#define bpf__for_each_map(pos, obj, objtmp) \
1473 bpf_object__for_each_safe(obj, objtmp) \
1474 bpf_map__for_each(pos, obj)
1475
1476#define bpf__for_each_stdout_map(pos, obj, objtmp) \
1477 bpf__for_each_map(pos, obj, objtmp) \
1478 if (bpf_map__get_name(pos) && \
1479 (strcmp("__bpf_stdout__", \
1480 bpf_map__get_name(pos)) == 0))
1481
1482int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
1483{
1484 struct bpf_map_priv *tmpl_priv = NULL;
1485 struct bpf_object *obj, *tmp;
1486 struct perf_evsel *evsel = NULL;
1487 struct bpf_map *map;
1488 int err;
1489 bool need_init = false;
1490
1491 bpf__for_each_stdout_map(map, obj, tmp) {
1492 struct bpf_map_priv *priv;
1493
1494 err = bpf_map__get_private(map, (void **)&priv);
1495 if (err)
1496 return -BPF_LOADER_ERRNO__INTERNAL;
1497
1498 /*
1499 * No need to check map type: type should have been
1500 * verified by kernel.
1501 */
1502 if (!need_init && !priv)
1503 need_init = !priv;
1504 if (!tmpl_priv && priv)
1505 tmpl_priv = priv;
1506 }
1507
1508 if (!need_init)
1509 return 0;
1510
1511 if (!tmpl_priv) {
1512 err = parse_events(evlist, "bpf-output/no-inherit=1,name=__bpf_stdout__/",
1513 NULL);
1514 if (err) {
1515 pr_debug("ERROR: failed to create bpf-output event\n");
1516 return -err;
1517 }
1518
1519 evsel = perf_evlist__last(evlist);
1520 }
1521
1522 bpf__for_each_stdout_map(map, obj, tmp) {
1523 struct bpf_map_priv *priv;
1524
1525 err = bpf_map__get_private(map, (void **)&priv);
1526 if (err)
1527 return -BPF_LOADER_ERRNO__INTERNAL;
1528 if (priv)
1529 continue;
1530
1531 if (tmpl_priv) {
1532 priv = bpf_map_priv__clone(tmpl_priv);
1533 if (!priv)
1534 return -ENOMEM;
1535
1536 err = bpf_map__set_private(map, priv, bpf_map_priv__clear);
1537 if (err) {
1538 bpf_map_priv__clear(map, priv);
1539 return err;
1540 }
1541 } else if (evsel) {
1542 struct bpf_map_op *op;
1543
1544 op = bpf_map__add_newop(map, NULL);
1545 if (IS_ERR(op))
1546 return PTR_ERR(op);
1547 op->op_type = BPF_MAP_OP_SET_EVSEL;
1548 op->v.evsel = evsel;
1549 }
1550 }
1551
1552 return 0;
1553}
1554
1420#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)1555#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
1421#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)1556#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
1422#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)1557#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
@@ -1590,3 +1725,11 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size) · 167 unmodified lines
1590 bpf__strerror_end(buf, size);1725 bpf__strerror_end(buf, size);
1591 return 0;1726 return 0;
1592}1727}
1728
1729int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
1730 int err, char *buf, size_t size)
1731{
1732 bpf__strerror_head(err, buf, size);
1733 bpf__strerror_end(buf, size);
1734 return 0;
1735}
tools/perf/util/bpf-loader.h+19−0
@@ -79,6 +79,11 @@ int bpf__strerror_config_obj(struct bpf_object *obj, · 78 unmodified lines
79 size_t size);79 size_t size);
80int bpf__apply_obj_config(void);80int bpf__apply_obj_config(void);
81int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);81int bpf__strerror_apply_obj_config(int err, char *buf, size_t size);
82
83int bpf__setup_stdout(struct perf_evlist *evlist);
84int bpf__strerror_setup_stdout(struct perf_evlist *evlist, int err,
85 char *buf, size_t size);
86
82#else87#else
83static inline struct bpf_object *88static inline struct bpf_object *
84bpf__prepare_load(const char *filename __maybe_unused,89bpf__prepare_load(const char *filename __maybe_unused,
@@ -124,6 +129,12 @@ bpf__apply_obj_config(void) · 39 unmodified lines
124 return 0;129 return 0;
125}130}
126 131
132static inline int
133bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
134{
135 return 0;
136}
137
127static inline int138static inline int
128__bpf_strerror(char *buf, size_t size)139__bpf_strerror(char *buf, size_t size)
129{140{
@@ -177,5 +188,13 @@ bpf__strerror_apply_obj_config(int err __maybe_unused, · 47 unmodified lines
177{188{
178 return __bpf_strerror(buf, size);189 return __bpf_strerror(buf, size);
179}190}
191
192static inline int
193bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
194 int err __maybe_unused, char *buf,
195 size_t size)
196{
197 return __bpf_strerror(buf, size);
198}
180#endif199#endif
181#endif200#endif
tools/perf/util/build-id.c+7−29
@@ -261,14 +261,14 @@ static int machine__write_buildid_table(struct machine *machine, int fd) · 260 unmodified lines
261 261
262 if (dso__is_vdso(pos)) {262 if (dso__is_vdso(pos)) {
263 name = pos->short_name;263 name = pos->short_name;
264 name_len = pos->short_name_len + 1;264 name_len = pos->short_name_len;
265 } else if (dso__is_kcore(pos)) {265 } else if (dso__is_kcore(pos)) {
266 machine__mmap_name(machine, nm, sizeof(nm));266 machine__mmap_name(machine, nm, sizeof(nm));
267 name = nm;267 name = nm;
268 name_len = strlen(nm) + 1;268 name_len = strlen(nm);
269 } else {269 } else {
270 name = pos->long_name;270 name = pos->long_name;
271 name_len = pos->long_name_len + 1;271 name_len = pos->long_name_len;
272 }272 }
273 273
274 in_kernel = pos->kernel ||274 in_kernel = pos->kernel ||
@@ -365,39 +365,17 @@ static char *build_id_cache__dirname_from_path(const char *name, · 90 unmodified lines
365int build_id_cache__list_build_ids(const char *pathname,365int build_id_cache__list_build_ids(const char *pathname,
366 struct strlist **result)366 struct strlist **result)
367{367{
368 struct strlist *list;
369 char *dir_name;368 char *dir_name;
370 DIR *dir;
371 struct dirent *d;
372 int ret = 0;369 int ret = 0;
373 370
374 list = strlist__new(NULL, NULL);
375 dir_name = build_id_cache__dirname_from_path(pathname, false, false);371 dir_name = build_id_cache__dirname_from_path(pathname, false, false);
376 if (!list || !dir_name) {372 if (!dir_name)
377 ret = -ENOMEM;373 return -ENOMEM;
378 goto out;
379 }
380 374
381 /* List up all dirents */375 *result = lsdir(dir_name, lsdir_no_dot_filter);
382 dir = opendir(dir_name);376 if (!*result)
383 if (!dir) {
384 ret = -errno;377 ret = -errno;
385 goto out;
386 }
387
388 while ((d = readdir(dir)) != NULL) {
389 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
390 continue;
391 strlist__add(list, d->d_name);
392 }
393 closedir(dir);
394
395out:
396 free(dir_name);378 free(dir_name);
397 if (ret)
398 strlist__delete(list);
399 else
400 *result = list;
401 379
402 return ret;380 return ret;
403}381}
tools/perf/util/cache.h+0−19
@@ -40,25 +40,6 @@ int split_cmdline(char *cmdline, const char ***argv); · 39 unmodified lines
40 40
41#define alloc_nr(x) (((x)+16)*3/2)41#define alloc_nr(x) (((x)+16)*3/2)
42 42
43/*
44 * Realloc the buffer pointed at by variable 'x' so that it can hold
45 * at least 'nr' entries; the number of entries currently allocated
46 * is 'alloc', using the standard growing factor alloc_nr() macro.
47 *
48 * DO NOT USE any expression with side-effect for 'x' or 'alloc'.
49 */
50#define ALLOC_GROW(x, nr, alloc) \
51 do { \
52 if ((nr) > alloc) { \
53 if (alloc_nr(alloc) < (nr)) \
54 alloc = (nr); \
55 else \
56 alloc = alloc_nr(alloc); \
57 x = xrealloc((x), alloc * sizeof(*(x))); \
58 } \
59 } while(0)
60
61
62static inline int is_absolute_path(const char *path)43static inline int is_absolute_path(const char *path)
63{44{
64 return path[0] == '/';45 return path[0] == '/';
tools/perf/util/call-path.c+122−0
@@ -0,0 +1,122 @@
1/*
2 * call-path.h: Manipulate a tree data structure containing function call paths
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#include <linux/rbtree.h>
17#include <linux/list.h>
18
19#include "util.h"
20#include "call-path.h"
21
22static void call_path__init(struct call_path *cp, struct call_path *parent,
23 struct symbol *sym, u64 ip, bool in_kernel)
24{
25 cp->parent = parent;
26 cp->sym = sym;
27 cp->ip = sym ? 0 : ip;
28 cp->db_id = 0;
29 cp->in_kernel = in_kernel;
30 RB_CLEAR_NODE(&cp->rb_node);
31 cp->children = RB_ROOT;
32}
33
34struct call_path_root *call_path_root__new(void)
35{
36 struct call_path_root *cpr;
37
38 cpr = zalloc(sizeof(struct call_path_root));
39 if (!cpr)
40 return NULL;
41 call_path__init(&cpr->call_path, NULL, NULL, 0, false);
42 INIT_LIST_HEAD(&cpr->blocks);
43 return cpr;
44}
45
46void call_path_root__free(struct call_path_root *cpr)
47{
48 struct call_path_block *pos, *n;
49
50 list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
51 list_del(&pos->node);
52 free(pos);
53 }
54 free(cpr);
55}
56
57static struct call_path *call_path__new(struct call_path_root *cpr,
58 struct call_path *parent,
59 struct symbol *sym, u64 ip,
60 bool in_kernel)
61{
62 struct call_path_block *cpb;
63 struct call_path *cp;
64 size_t n;
65
66 if (cpr->next < cpr->sz) {
67 cpb = list_last_entry(&cpr->blocks, struct call_path_block,
68 node);
69 } else {
70 cpb = zalloc(sizeof(struct call_path_block));
71 if (!cpb)
72 return NULL;
73 list_add_tail(&cpb->node, &cpr->blocks);
74 cpr->sz += CALL_PATH_BLOCK_SIZE;
75 }
76
77 n = cpr->next++ & CALL_PATH_BLOCK_MASK;
78 cp = &cpb->cp[n];
79
80 call_path__init(cp, parent, sym, ip, in_kernel);
81
82 return cp;
83}
84
85struct call_path *call_path__findnew(struct call_path_root *cpr,
86 struct call_path *parent,
87 struct symbol *sym, u64 ip, u64 ks)
88{
89 struct rb_node **p;
90 struct rb_node *node_parent = NULL;
91 struct call_path *cp;
92 bool in_kernel = ip >= ks;
93
94 if (sym)
95 ip = 0;
96
97 if (!parent)
98 return call_path__new(cpr, parent, sym, ip, in_kernel);
99
100 p = &parent->children.rb_node;
101 while (*p != NULL) {
102 node_parent = *p;
103 cp = rb_entry(node_parent, struct call_path, rb_node);
104
105 if (cp->sym == sym && cp->ip == ip)
106 return cp;
107
108 if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
109 p = &(*p)->rb_left;
110 else
111 p = &(*p)->rb_right;
112 }
113
114 cp = call_path__new(cpr, parent, sym, ip, in_kernel);
115 if (!cp)
116 return NULL;
117
118 rb_link_node(&cp->rb_node, node_parent, p);
119 rb_insert_color(&cp->rb_node, &parent->children);
120
121 return cp;
122}
tools/perf/util/call-path.h+77−0
@@ -0,0 +1,77 @@
1/*
2 * call-path.h: Manipulate a tree data structure containing function call paths
3 * Copyright (c) 2014, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 */
15
16#ifndef __PERF_CALL_PATH_H
17#define __PERF_CALL_PATH_H
18
19#include <sys/types.h>
20
21#include <linux/types.h>
22#include <linux/rbtree.h>
23
24/**
25 * struct call_path - node in list of calls leading to a function call.
26 * @parent: call path to the parent function call
27 * @sym: symbol of function called
28 * @ip: only if sym is null, the ip of the function
29 * @db_id: id used for db-export
30 * @in_kernel: whether function is a in the kernel
31 * @rb_node: node in parent's tree of called functions
32 * @children: tree of call paths of functions called
33 *
34 * In combination with the call_return structure, the call_path structure
35 * defines a context-sensitve call-graph.
36 */
37struct call_path {
38 struct call_path *parent;
39 struct symbol *sym;
40 u64 ip;
41 u64 db_id;
42 bool in_kernel;
43 struct rb_node rb_node;
44 struct rb_root children;
45};
46
47#define CALL_PATH_BLOCK_SHIFT 8
48#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
49#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
50
51struct call_path_block {
52 struct call_path cp[CALL_PATH_BLOCK_SIZE];
53 struct list_head node;
54};
55
56/**
57 * struct call_path_root - root of all call paths.
58 * @call_path: root call path
59 * @blocks: list of blocks to store call paths
60 * @next: next free space
61 * @sz: number of spaces
62 */
63struct call_path_root {
64 struct call_path call_path;
65 struct list_head blocks;
66 size_t next;
67 size_t sz;
68};
69
70struct call_path_root *call_path_root__new(void);
71void call_path_root__free(struct call_path_root *cpr);
72
73struct call_path *call_path__findnew(struct call_path_root *cpr,
74 struct call_path *parent,
75 struct symbol *sym, u64 ip, u64 ks);
76
77#endif
tools/perf/util/callchain.c+6−3
@@ -109,6 +109,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt) · 108 unmodified lines
109 bool record_opt_set = false;109 bool record_opt_set = false;
110 bool try_stack_size = false;110 bool try_stack_size = false;
111 111
112 callchain_param.enabled = true;
112 symbol_conf.use_callchain = true;113 symbol_conf.use_callchain = true;
113 114
114 if (!arg)115 if (!arg)
@@ -117,6 +118,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt) · 2 unmodified lines
117 while ((tok = strtok((char *)arg, ",")) != NULL) {118 while ((tok = strtok((char *)arg, ",")) != NULL) {
118 if (!strncmp(tok, "none", strlen(tok))) {119 if (!strncmp(tok, "none", strlen(tok))) {
119 callchain_param.mode = CHAIN_NONE;120 callchain_param.mode = CHAIN_NONE;
121 callchain_param.enabled = false;
120 symbol_conf.use_callchain = false;122 symbol_conf.use_callchain = false;
121 return 0;123 return 0;
122 }124 }
@@ -788,7 +790,8 @@ int callchain_cursor_append(struct callchain_cursor *cursor, · 665 unmodified lines
788 return 0;790 return 0;
789}791}
790 792
791int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,793int sample__resolve_callchain(struct perf_sample *sample,
794 struct callchain_cursor *cursor, struct symbol **parent,
792 struct perf_evsel *evsel, struct addr_location *al,795 struct perf_evsel *evsel, struct addr_location *al,
793 int max_stack)796 int max_stack)
794{797{
@@ -796,8 +799,8 @@ int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent · 1 unmodified line
796 return 0;799 return 0;
797 800
798 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||801 if (symbol_conf.use_callchain || symbol_conf.cumulate_callchain ||
799 sort__has_parent) {802 perf_hpp_list.parent) {
800 return thread__resolve_callchain(al->thread, evsel, sample,803 return thread__resolve_callchain(al->thread, cursor, evsel, sample,
801 parent, al, max_stack);804 parent, al, max_stack);
802 }805 }
803 return 0;806 return 0;
tools/perf/util/callchain.h+8−1
@@ -212,7 +212,14 @@ struct hist_entry; · 211 unmodified lines
212int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);212int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset);
213int record_callchain_opt(const struct option *opt, const char *arg, int unset);213int record_callchain_opt(const struct option *opt, const char *arg, int unset);
214 214
215int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent,215struct record_opts;
216
217int record_opts__parse_callchain(struct record_opts *record,
218 struct callchain_param *callchain,
219 const char *arg, bool unset);
220
221int sample__resolve_callchain(struct perf_sample *sample,
222 struct callchain_cursor *cursor, struct symbol **parent,
216 struct perf_evsel *evsel, struct addr_location *al,223 struct perf_evsel *evsel, struct addr_location *al,
217 int max_stack);224 int max_stack);
218int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);225int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
tools/perf/util/config.c+191−31
@@ -13,6 +13,7 @@ · 12 unmodified lines
13#include <subcmd/exec-cmd.h>13#include <subcmd/exec-cmd.h>
14#include "util/hist.h" /* perf_hist_config */14#include "util/hist.h" /* perf_hist_config */
15#include "util/llvm-utils.h" /* perf_llvm_config */15#include "util/llvm-utils.h" /* perf_llvm_config */
16#include "config.h"
16 17
17#define MAXNAME (256)18#define MAXNAME (256)
18 19
@@ -377,6 +378,21 @@ const char *perf_config_dirname(const char *name, const char *value) · 358 unmodified lines
377 return value;378 return value;
378}379}
379 380
381static int perf_buildid_config(const char *var, const char *value)
382{
383 /* same dir for all commands */
384 if (!strcmp(var, "buildid.dir")) {
385 const char *dir = perf_config_dirname(var, value);
386
387 if (!dir)
388 return -1;
389 strncpy(buildid_dir, dir, MAXPATHLEN-1);
390 buildid_dir[MAXPATHLEN-1] = '\0';
391 }
392
393 return 0;
394}
395
380static int perf_default_core_config(const char *var __maybe_unused,396static int perf_default_core_config(const char *var __maybe_unused,
381 const char *value __maybe_unused)397 const char *value __maybe_unused)
382{398{
@@ -412,6 +428,9 @@ int perf_default_config(const char *var, const char *value, · 29 unmodified lines
412 if (!prefixcmp(var, "llvm."))428 if (!prefixcmp(var, "llvm."))
413 return perf_llvm_config(var, value);429 return perf_llvm_config(var, value);
414 430
431 if (!prefixcmp(var, "buildid."))
432 return perf_buildid_config(var, value);
433
415 /* Add other config variables here. */434 /* Add other config variables here. */
416 return 0;435 return 0;
417}436}
@@ -506,41 +525,185 @@ out: · 88 unmodified lines
506 return ret;525 return ret;
507}526}
508 527
509/*528static struct perf_config_section *find_section(struct list_head *sections,
510 * Call this to report error for your variable that should not529 const char *section_name)
511 * get a boolean value (i.e. "[my] var" means "true").
512 */
513int config_error_nonbool(const char *var)
514{530{
515 return error("Missing value for '%s'", var);531 struct perf_config_section *section;
532
533 list_for_each_entry(section, sections, node)
534 if (!strcmp(section->name, section_name))
535 return section;
536
537 return NULL;
538}
539
540static struct perf_config_item *find_config_item(const char *name,
541 struct perf_config_section *section)
542{
543 struct perf_config_item *item;
544
545 list_for_each_entry(item, &section->items, node)
546 if (!strcmp(item->name, name))
547 return item;
548
549 return NULL;
516}550}
517 551
518struct buildid_dir_config {552static struct perf_config_section *add_section(struct list_head *sections,
519 char *dir;553 const char *section_name)
520};554{
555 struct perf_config_section *section = zalloc(sizeof(*section));
556
557 if (!section)
558 return NULL;
559
560 INIT_LIST_HEAD(&section->items);
561 section->name = strdup(section_name);
562 if (!section->name) {
563 pr_debug("%s: strdup failed\n", __func__);
564 free(section);
565 return NULL;
566 }
567
568 list_add_tail(&section->node, sections);
569 return section;
570}
521 571
522static int buildid_dir_command_config(const char *var, const char *value,572static struct perf_config_item *add_config_item(struct perf_config_section *section,
523 void *data)573 const char *name)
524{574{
525 struct buildid_dir_config *c = data;575 struct perf_config_item *item = zalloc(sizeof(*item));
526 const char *v;
527 576
528 /* same dir for all commands */577 if (!item)
529 if (!strcmp(var, "buildid.dir")) {578 return NULL;
530 v = perf_config_dirname(var, value);579
531 if (!v)580 item->name = strdup(name);
532 return -1;581 if (!item->name) {
533 strncpy(c->dir, v, MAXPATHLEN-1);582 pr_debug("%s: strdup failed\n", __func__);
534 c->dir[MAXPATHLEN-1] = '\0';583 free(item);
584 return NULL;
535 }585 }
586
587 list_add_tail(&item->node, &section->items);
588 return item;
589}
590
591static int set_value(struct perf_config_item *item, const char *value)
592{
593 char *val = strdup(value);
594
595 if (!val)
596 return -1;
597
598 zfree(&item->value);
599 item->value = val;
536 return 0;600 return 0;
537}601}
538 602
539static void check_buildid_dir_config(void)603static int collect_config(const char *var, const char *value,
604 void *perf_config_set)
540{605{
541 struct buildid_dir_config c;606 int ret = -1;
542 c.dir = buildid_dir;607 char *ptr, *key;
543 perf_config(buildid_dir_command_config, &c);608 char *section_name, *name;
609 struct perf_config_section *section = NULL;
610 struct perf_config_item *item = NULL;
611 struct perf_config_set *set = perf_config_set;
612 struct list_head *sections = &set->sections;
613
614 key = ptr = strdup(var);
615 if (!key) {
616 pr_debug("%s: strdup failed\n", __func__);
617 return -1;
618 }
619
620 section_name = strsep(&ptr, ".");
621 name = ptr;
622 if (name == NULL || value == NULL)
623 goto out_free;
624
625 section = find_section(sections, section_name);
626 if (!section) {
627 section = add_section(sections, section_name);
628 if (!section)
629 goto out_free;
630 }
631
632 item = find_config_item(name, section);
633 if (!item) {
634 item = add_config_item(section, name);
635 if (!item)
636 goto out_free;
637 }
638
639 ret = set_value(item, value);
640 return ret;
641
642out_free:
643 free(key);
644 perf_config_set__delete(set);
645 return -1;
646}
647
648struct perf_config_set *perf_config_set__new(void)
649{
650 struct perf_config_set *set = zalloc(sizeof(*set));
651
652 if (set) {
653 INIT_LIST_HEAD(&set->sections);
654 perf_config(collect_config, set);
655 }
656
657 return set;
658}
659
660static void perf_config_item__delete(struct perf_config_item *item)
661{
662 zfree(&item->name);
663 zfree(&item->value);
664 free(item);
665}
666
667static void perf_config_section__purge(struct perf_config_section *section)
668{
669 struct perf_config_item *item, *tmp;
670
671 list_for_each_entry_safe(item, tmp, &section->items, node) {
672 list_del_init(&item->node);
673 perf_config_item__delete(item);
674 }
675}
676
677static void perf_config_section__delete(struct perf_config_section *section)
678{
679 perf_config_section__purge(section);
680 zfree(&section->name);
681 free(section);
682}
683
684static void perf_config_set__purge(struct perf_config_set *set)
685{
686 struct perf_config_section *section, *tmp;
687
688 list_for_each_entry_safe(section, tmp, &set->sections, node) {
689 list_del_init(&section->node);
690 perf_config_section__delete(section);
691 }
692}
693
694void perf_config_set__delete(struct perf_config_set *set)
695{
696 perf_config_set__purge(set);
697 free(set);
698}
699
700/*
701 * Call this to report error for your variable that should not
702 * get a boolean value (i.e. "[my] var" means "true").
703 */
704int config_error_nonbool(const char *var)
705{
706 return error("Missing value for '%s'", var);
544}707}
545 708
546void set_buildid_dir(const char *dir)709void set_buildid_dir(const char *dir)
@@ -548,16 +711,13 @@ void set_buildid_dir(const char *dir) · 1 unmodified line
548 if (dir)711 if (dir)
549 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);712 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);
550 713
551 /* try config file */
552 if (buildid_dir[0] == '\0')
553 check_buildid_dir_config();
554
555 /* default to $HOME/.debug */714 /* default to $HOME/.debug */
556 if (buildid_dir[0] == '\0') {715 if (buildid_dir[0] == '\0') {
557 char *v = getenv("HOME");716 char *home = getenv("HOME");
558 if (v) {717
718 if (home) {
559 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s",719 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s",
560 v, DEBUG_CACHE_DIR);720 home, DEBUG_CACHE_DIR);
561 } else {721 } else {
562 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1);722 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1);
563 }723 }
tools/perf/util/config.h+26−0
@@ -0,0 +1,26 @@
1#ifndef __PERF_CONFIG_H
2#define __PERF_CONFIG_H
3
4#include <stdbool.h>
5#include <linux/list.h>
6
7struct perf_config_item {
8 char *name;
9 char *value;
10 struct list_head node;
11};
12
13struct perf_config_section {
14 char *name;
15 struct list_head items;
16 struct list_head node;
17};
18
19struct perf_config_set {
20 struct list_head sections;
21};
22
23struct perf_config_set *perf_config_set__new(void);
24void perf_config_set__delete(struct perf_config_set *set);
25
26#endif /* __PERF_CONFIG_H */
tools/perf/util/cpumap.c+12−0
@@ -587,3 +587,15 @@ int cpu__setup_cpunode_map(void) · 586 unmodified lines
587 closedir(dir1);587 closedir(dir1);
588 return 0;588 return 0;
589}589}
590
591bool cpu_map__has(struct cpu_map *cpus, int cpu)
592{
593 int i;
594
595 for (i = 0; i < cpus->nr; ++i) {
596 if (cpus->map[i] == cpu)
597 return true;
598 }
599
600 return false;
601}
tools/perf/util/cpumap.h+2−0
@@ -66,4 +66,6 @@ int cpu__get_node(int cpu); · 65 unmodified lines
66int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,66int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
67 int (*f)(struct cpu_map *map, int cpu, void *data),67 int (*f)(struct cpu_map *map, int cpu, void *data),
68 void *data);68 void *data);
69
70bool cpu_map__has(struct cpu_map *cpus, int cpu);
69#endif /* __PERF_CPUMAP_H */71#endif /* __PERF_CPUMAP_H */
tools/perf/util/data.c+41−0
@@ -136,3 +136,44 @@ ssize_t perf_data_file__write(struct perf_data_file *file, · 135 unmodified lines
136{136{
137 return writen(file->fd, buf, size);137 return writen(file->fd, buf, size);
138}138}
139
140int perf_data_file__switch(struct perf_data_file *file,
141 const char *postfix,
142 size_t pos, bool at_exit)
143{
144 char *new_filepath;
145 int ret;
146
147 if (check_pipe(file))
148 return -EINVAL;
149 if (perf_data_file__is_read(file))
150 return -EINVAL;
151
152 if (asprintf(&new_filepath, "%s.%s", file->path, postfix) < 0)
153 return -ENOMEM;
154
155 /*
156 * Only fire a warning, don't return error, continue fill
157 * original file.
158 */
159 if (rename(file->path, new_filepath))
160 pr_warning("Failed to rename %s to %s\n", file->path, new_filepath);
161
162 if (!at_exit) {
163 close(file->fd);
164 ret = perf_data_file__open(file);
165 if (ret < 0)
166 goto out;
167
168 if (lseek(file->fd, pos, SEEK_SET) == (off_t)-1) {
169 ret = -errno;
170 pr_debug("Failed to lseek to %zu: %s",
171 pos, strerror(errno));
172 goto out;
173 }
174 }
175 ret = file->fd;
176out:
177 free(new_filepath);
178 return ret;
179}
tools/perf/util/data.h+10−1
@@ -46,5 +46,14 @@ int perf_data_file__open(struct perf_data_file *file); · 45 unmodified lines
46void perf_data_file__close(struct perf_data_file *file);46void perf_data_file__close(struct perf_data_file *file);
47ssize_t perf_data_file__write(struct perf_data_file *file,47ssize_t perf_data_file__write(struct perf_data_file *file,
48 void *buf, size_t size);48 void *buf, size_t size);
49 49/*
50 * If at_exit is set, only rename current perf.data to
51 * perf.data.<postfix>, continue write on original file.
52 * Set at_exit when flushing the last output.
53 *
54 * Return value is fd of new output.
55 */
56int perf_data_file__switch(struct perf_data_file *file,
57 const char *postfix,
58 size_t pos, bool at_exit);
50#endif /* __PERF_DATA_H */59#endif /* __PERF_DATA_H */
tools/perf/util/db-export.c+87−2
@@ -23,6 +23,8 @@ · 22 unmodified lines
23#include "event.h"23#include "event.h"
24#include "util.h"24#include "util.h"
25#include "thread-stack.h"25#include "thread-stack.h"
26#include "callchain.h"
27#include "call-path.h"
26#include "db-export.h"28#include "db-export.h"
27 29
28struct deferred_export {30struct deferred_export {
@@ -258,8 +260,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, · 229 unmodified lines
258 if (!al->sym) {260 if (!al->sym) {
259 al->sym = symbol__new(al->addr, 0, 0, "unknown");261 al->sym = symbol__new(al->addr, 0, 0, "unknown");
260 if (al->sym)262 if (al->sym)
261 symbols__insert(&dso->symbols[al->map->type],263 dso__insert_symbol(dso, al->map->type, al->sym);
262 al->sym);
263 }264 }
264 265
265 if (al->sym) {266 if (al->sym) {
@@ -276,6 +277,80 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, · 10 unmodified lines
276 return 0;277 return 0;
277}278}
278 279
280static struct call_path *call_path_from_sample(struct db_export *dbe,
281 struct machine *machine,
282 struct thread *thread,
283 struct perf_sample *sample,
284 struct perf_evsel *evsel)
285{
286 u64 kernel_start = machine__kernel_start(machine);
287 struct call_path *current = &dbe->cpr->call_path;
288 enum chain_order saved_order = callchain_param.order;
289 int err;
290
291 if (!symbol_conf.use_callchain || !sample->callchain)
292 return NULL;
293
294 /*
295 * Since the call path tree must be built starting with the root, we
296 * must use ORDER_CALL for call chain resolution, in order to process
297 * the callchain starting with the root node and ending with the leaf.
298 */
299 callchain_param.order = ORDER_CALLER;
300 err = thread__resolve_callchain(thread, &callchain_cursor, evsel,
301 sample, NULL, NULL,
302 sysctl_perf_event_max_stack);
303 if (err) {
304 callchain_param.order = saved_order;
305 return NULL;
306 }
307 callchain_cursor_commit(&callchain_cursor);
308
309 while (1) {
310 struct callchain_cursor_node *node;
311 struct addr_location al;
312 u64 dso_db_id = 0, sym_db_id = 0, offset = 0;
313
314 memset(&al, 0, sizeof(al));
315
316 node = callchain_cursor_current(&callchain_cursor);
317 if (!node)
318 break;
319 /*
320 * Handle export of symbol and dso for this node by
321 * constructing an addr_location struct and then passing it to
322 * db_ids_from_al() to perform the export.
323 */
324 al.sym = node->sym;
325 al.map = node->map;
326 al.machine = machine;
327 al.addr = node->ip;
328
329 if (al.map && !al.sym)
330 al.sym = dso__find_symbol(al.map->dso, MAP__FUNCTION,
331 al.addr);
332
333 db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
334
335 /* add node to the call path tree if it doesn't exist */
336 current = call_path__findnew(dbe->cpr, current,
337 al.sym, node->ip,
338 kernel_start);
339
340 callchain_cursor_advance(&callchain_cursor);
341 }
342
343 /* Reset the callchain order to its prior value. */
344 callchain_param.order = saved_order;
345
346 if (current == &dbe->cpr->call_path) {
347 /* Bail because the callchain was empty. */
348 return NULL;
349 }
350
351 return current;
352}
353
279int db_export__branch_type(struct db_export *dbe, u32 branch_type,354int db_export__branch_type(struct db_export *dbe, u32 branch_type,
280 const char *name)355 const char *name)
281{356{
@@ -329,6 +404,16 @@ int db_export__sample(struct db_export *dbe, union perf_event *event, · 47 unmodified lines
329 if (err)404 if (err)
330 goto out_put;405 goto out_put;
331 406
407 if (dbe->cpr) {
408 struct call_path *cp = call_path_from_sample(dbe, al->machine,
409 thread, sample,
410 evsel);
411 if (cp) {
412 db_export__call_path(dbe, cp);
413 es.call_path_id = cp->db_id;
414 }
415 }
416
332 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&417 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
333 sample_addr_correlates_sym(&evsel->attr)) {418 sample_addr_correlates_sym(&evsel->attr)) {
334 struct addr_location addr_al;419 struct addr_location addr_al;
tools/perf/util/db-export.h+3−0
@@ -27,6 +27,7 @@ struct dso; · 26 unmodified lines
27struct perf_sample;27struct perf_sample;
28struct addr_location;28struct addr_location;
29struct call_return_processor;29struct call_return_processor;
30struct call_path_root;
30struct call_path;31struct call_path;
31struct call_return;32struct call_return;
32 33
@@ -43,6 +44,7 @@ struct export_sample { · 10 unmodified lines
43 u64 addr_dso_db_id;44 u64 addr_dso_db_id;
44 u64 addr_sym_db_id;45 u64 addr_sym_db_id;
45 u64 addr_offset; /* addr offset from symbol start */46 u64 addr_offset; /* addr offset from symbol start */
47 u64 call_path_id;
46};48};
47 49
48struct db_export {50struct db_export {
@@ -64,6 +66,7 @@ struct db_export { · 15 unmodified lines
64 int (*export_call_return)(struct db_export *dbe,66 int (*export_call_return)(struct db_export *dbe,
65 struct call_return *cr);67 struct call_return *cr);
66 struct call_return_processor *crp;68 struct call_return_processor *crp;
69 struct call_path_root *cpr;
67 u64 evsel_last_db_id;70 u64 evsel_last_db_id;
68 u64 machine_last_db_id;71 u64 machine_last_db_id;
69 u64 thread_last_db_id;72 u64 thread_last_db_id;
tools/perf/util/dso.c+2−2
@@ -38,7 +38,7 @@ int dso__read_binary_type_filename(const struct dso *dso, · 37 unmodified lines
38 enum dso_binary_type type,38 enum dso_binary_type type,
39 char *root_dir, char *filename, size_t size)39 char *root_dir, char *filename, size_t size)
40{40{
41 char build_id_hex[BUILD_ID_SIZE * 2 + 1];41 char build_id_hex[SBUILD_ID_SIZE];
42 int ret = 0;42 int ret = 0;
43 size_t len;43 size_t len;
44 44
@@ -1301,7 +1301,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp) · 1256 unmodified lines
1301 1301
1302size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)1302size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
1303{1303{
1304 char sbuild_id[BUILD_ID_SIZE * 2 + 1];1304 char sbuild_id[SBUILD_ID_SIZE];
1305 1305
1306 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);1306 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1307 return fprintf(fp, "%s", sbuild_id);1307 return fprintf(fp, "%s", sbuild_id);
tools/perf/util/dwarf-aux.c+24−28
@@ -915,8 +915,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) · 914 unmodified lines
915 tmp = "*";915 tmp = "*";
916 else if (tag == DW_TAG_subroutine_type) {916 else if (tag == DW_TAG_subroutine_type) {
917 /* Function pointer */917 /* Function pointer */
918 strbuf_add(buf, "(function_type)", 15);918 return strbuf_add(buf, "(function_type)", 15);
919 return 0;
920 } else {919 } else {
921 if (!dwarf_diename(&type))920 if (!dwarf_diename(&type))
922 return -ENOENT;921 return -ENOENT;
@@ -927,14 +926,10 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf) · 4 unmodified lines
927 else if (tag == DW_TAG_enumeration_type)926 else if (tag == DW_TAG_enumeration_type)
928 tmp = "enum ";927 tmp = "enum ";
929 /* Write a base name */928 /* Write a base name */
930 strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));929 return strbuf_addf(buf, "%s%s", tmp, dwarf_diename(&type));
931 return 0;
932 }930 }
933 ret = die_get_typename(&type, buf);931 ret = die_get_typename(&type, buf);
934 if (ret == 0)932 return ret ? ret : strbuf_addstr(buf, tmp);
935 strbuf_addstr(buf, tmp);
936
937 return ret;
938}933}
939 934
940/**935/**
@@ -951,12 +946,10 @@ int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf) · 10 unmodified lines
951 ret = die_get_typename(vr_die, buf);946 ret = die_get_typename(vr_die, buf);
952 if (ret < 0) {947 if (ret < 0) {
953 pr_debug("Failed to get type, make it unknown.\n");948 pr_debug("Failed to get type, make it unknown.\n");
954 strbuf_add(buf, " (unknown_type)", 14);949 ret = strbuf_add(buf, " (unknown_type)", 14);
955 }950 }
956 951
957 strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));952 return ret < 0 ? ret : strbuf_addf(buf, "\t%s", dwarf_diename(vr_die));
958
959 return 0;
960}953}
961 954
962#ifdef HAVE_DWARF_GETLOCATIONS955#ifdef HAVE_DWARF_GETLOCATIONS
@@ -999,22 +992,24 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die, · 36 unmodified lines
999 }992 }
1000 993
1001 while ((offset = dwarf_ranges(&scopes[1], offset, &base,994 while ((offset = dwarf_ranges(&scopes[1], offset, &base,
1002 &start, &end)) > 0) {995 &start, &end)) > 0) {
1003 start -= entry;996 start -= entry;
1004 end -= entry;997 end -= entry;
1005 998
1006 if (first) {999 if (first) {
1007 strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,1000 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1008 name, start, end);1001 name, start, end);
1009 first = false;1002 first = false;
1010 } else {1003 } else {
1011 strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,1004 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1012 start, end);1005 start, end);
1013 }1006 }
1007 if (ret < 0)
1008 goto out;
1014 }1009 }
1015 1010
1016 if (!first)1011 if (!first)
1017 strbuf_add(buf, "]>", 2);1012 ret = strbuf_add(buf, "]>", 2);
1018 1013
1019out:1014out:
1020 free(scopes);1015 free(scopes);
@@ -1054,31 +1049,32 @@ int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf) · 33 unmodified lines
1054 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)1049 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
1055 return -EINVAL;1050 return -EINVAL;
1056 1051
1057 while ((offset = dwarf_getlocations(1052 while ((offset = dwarf_getlocations(&attr, offset, &base,
1058 &attr, offset, &base,1053 &start, &end, &op, &nops)) > 0) {
1059 &start, &end, &op, &nops)) > 0) {
1060 if (start == 0) {1054 if (start == 0) {
1061 /* Single Location Descriptions */1055 /* Single Location Descriptions */
1062 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);1056 ret = die_get_var_innermost_scope(sp_die, vr_die, buf);
1063 return ret;1057 goto out;
1064 }1058 }
1065 1059
1066 /* Location Lists */1060 /* Location Lists */
1067 start -= entry;1061 start -= entry;
1068 end -= entry;1062 end -= entry;
1069 if (first) {1063 if (first) {
1070 strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,1064 ret = strbuf_addf(buf, "@<%s+[%" PRIu64 "-%" PRIu64,
1071 name, start, end);1065 name, start, end);
1072 first = false;1066 first = false;
1073 } else {1067 } else {
1074 strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,1068 ret = strbuf_addf(buf, ",%" PRIu64 "-%" PRIu64,
1075 start, end);1069 start, end);
1076 }1070 }
1071 if (ret < 0)
1072 goto out;
1077 }1073 }
1078 1074
1079 if (!first)1075 if (!first)
1080 strbuf_add(buf, "]>", 2);1076 ret = strbuf_add(buf, "]>", 2);
1081 1077out:
1082 return ret;1078 return ret;
1083}1079}
1084#else1080#else
tools/perf/util/event.c+1−0
@@ -45,6 +45,7 @@ static const char *perf_event__names[] = { · 44 unmodified lines
45 [PERF_RECORD_STAT] = "STAT",45 [PERF_RECORD_STAT] = "STAT",
46 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND",46 [PERF_RECORD_STAT_ROUND] = "STAT_ROUND",
47 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",47 [PERF_RECORD_EVENT_UPDATE] = "EVENT_UPDATE",
48 [PERF_RECORD_TIME_CONV] = "TIME_CONV",
48};49};
49 50
50const char *perf_event__name(unsigned int id)51const char *perf_event__name(unsigned int id)
tools/perf/util/event.h+9−0
@@ -233,6 +233,7 @@ enum perf_user_event_type { /* above any possible kernel type */ · 232 unmodified lines
233 PERF_RECORD_STAT = 76,233 PERF_RECORD_STAT = 76,
234 PERF_RECORD_STAT_ROUND = 77,234 PERF_RECORD_STAT_ROUND = 77,
235 PERF_RECORD_EVENT_UPDATE = 78,235 PERF_RECORD_EVENT_UPDATE = 78,
236 PERF_RECORD_TIME_CONV = 79,
236 PERF_RECORD_HEADER_MAX237 PERF_RECORD_HEADER_MAX
237};238};
238 239
@@ -469,6 +470,13 @@ struct stat_round_event { · 230 unmodified lines
469 u64 time;470 u64 time;
470};471};
471 472
473struct time_conv_event {
474 struct perf_event_header header;
475 u64 time_shift;
476 u64 time_mult;
477 u64 time_zero;
478};
479
472union perf_event {480union perf_event {
473 struct perf_event_header header;481 struct perf_event_header header;
474 struct mmap_event mmap;482 struct mmap_event mmap;
@@ -497,6 +505,7 @@ union perf_event { · 22 unmodified lines
497 struct stat_config_event stat_config;505 struct stat_config_event stat_config;
498 struct stat_event stat;506 struct stat_event stat;
499 struct stat_round_event stat_round;507 struct stat_round_event stat_round;
508 struct time_conv_event time_conv;
500};509};
501 510
502void perf_event__print_totals(void);511void perf_event__print_totals(void);
tools/perf/util/evlist.c+134−40
@@ -679,53 +679,52 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, · 678 unmodified lines
679 return NULL;679 return NULL;
680}680}
681 681
682union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)682/* When check_messup is true, 'end' must points to a good entry */
683static union perf_event *
684perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
685 u64 end, u64 *prev)
683{686{
684 struct perf_mmap *md = &evlist->mmap[idx];
685 u64 head;
686 u64 old = md->prev;
687 unsigned char *data = md->base + page_size;687 unsigned char *data = md->base + page_size;
688 union perf_event *event = NULL;688 union perf_event *event = NULL;
689 int diff = end - start;
689 690
690 /*691 if (check_messup) {
691 * Check if event was unmapped due to a POLLHUP/POLLERR.
692 */
693 if (!atomic_read(&md->refcnt))
694 return NULL;
695
696 head = perf_mmap__read_head(md);
697 if (evlist->overwrite) {
698 /*692 /*
699 * If we're further behind than half the buffer, there's a chance693 * If we're further behind than half the buffer, there's a chance
700 * the writer will bite our tail and mess up the samples under us.694 * the writer will bite our tail and mess up the samples under us.
701 *695 *
702 * If we somehow ended up ahead of the head, we got messed up.696 * If we somehow ended up ahead of the 'end', we got messed up.
703 *697 *
704 * In either case, truncate and restart at head.698 * In either case, truncate and restart at 'end'.
705 */699 */
706 int diff = head - old;
707 if (diff > md->mask / 2 || diff < 0) {700 if (diff > md->mask / 2 || diff < 0) {
708 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");701 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
709 702
710 /*703 /*
711 * head points to a known good entry, start there.704 * 'end' points to a known good entry, start there.
712 */705 */
713 old = head;706 start = end;
707 diff = 0;
714 }708 }
715 }709 }
716 710
717 if (old != head) {711 if (diff >= (int)sizeof(event->header)) {
718 size_t size;712 size_t size;
719 713
720 event = (union perf_event *)&data[old & md->mask];714 event = (union perf_event *)&data[start & md->mask];
721 size = event->header.size;715 size = event->header.size;
722 716
717 if (size < sizeof(event->header) || diff < (int)size) {
718 event = NULL;
719 goto broken_event;
720 }
721
723 /*722 /*
724 * Event straddles the mmap boundary -- header should always723 * Event straddles the mmap boundary -- header should always
725 * be inside due to u64 alignment of output.724 * be inside due to u64 alignment of output.
726 */725 */
727 if ((old & md->mask) + size != ((old + size) & md->mask)) {726 if ((start & md->mask) + size != ((start + size) & md->mask)) {
728 unsigned int offset = old;727 unsigned int offset = start;
729 unsigned int len = min(sizeof(*event), size), cpy;728 unsigned int len = min(sizeof(*event), size), cpy;
730 void *dst = md->event_copy;729 void *dst = md->event_copy;
731 730
@@ -740,14 +739,83 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) · 8 unmodified lines
740 event = (union perf_event *) md->event_copy;739 event = (union perf_event *) md->event_copy;
741 }740 }
742 741
743 old += size;742 start += size;
744 }743 }
745 744
746 md->prev = old;745broken_event:
746 if (prev)
747 *prev = start;
747 748
748 return event;749 return event;
749}750}
750 751
752union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
753{
754 struct perf_mmap *md = &evlist->mmap[idx];
755 u64 head;
756 u64 old = md->prev;
757
758 /*
759 * Check if event was unmapped due to a POLLHUP/POLLERR.
760 */
761 if (!atomic_read(&md->refcnt))
762 return NULL;
763
764 head = perf_mmap__read_head(md);
765
766 return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev);
767}
768
769union perf_event *
770perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
771{
772 struct perf_mmap *md = &evlist->mmap[idx];
773 u64 head, end;
774 u64 start = md->prev;
775
776 /*
777 * Check if event was unmapped due to a POLLHUP/POLLERR.
778 */
779 if (!atomic_read(&md->refcnt))
780 return NULL;
781
782 head = perf_mmap__read_head(md);
783 if (!head)
784 return NULL;
785
786 /*
787 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
788 * it each time when kernel writes to it, so in fact 'head' is
789 * negative. 'end' pointer is made manually by adding the size of
790 * the ring buffer to 'head' pointer, means the validate data can
791 * read is the whole ring buffer. If 'end' is positive, the ring
792 * buffer has not fully filled, so we must adjust 'end' to 0.
793 *
794 * However, since both 'head' and 'end' is unsigned, we can't
795 * simply compare 'end' against 0. Here we compare '-head' and
796 * the size of the ring buffer, where -head is the number of bytes
797 * kernel write to the ring buffer.
798 */
799 if (-head < (u64)(md->mask + 1))
800 end = 0;
801 else
802 end = head + md->mask + 1;
803
804 return perf_mmap__read(md, false, start, end, &md->prev);
805}
806
807void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
808{
809 struct perf_mmap *md = &evlist->mmap[idx];
810 u64 head;
811
812 if (!atomic_read(&md->refcnt))
813 return;
814
815 head = perf_mmap__read_head(md);
816 md->prev = head;
817}
818
751static bool perf_mmap__empty(struct perf_mmap *md)819static bool perf_mmap__empty(struct perf_mmap *md)
752{820{
753 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;821 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
@@ -986,26 +1054,34 @@ out_unmap: · 232 unmodified lines
986 return -1;1054 return -1;
987}1055}
988 1056
989static size_t perf_evlist__mmap_size(unsigned long pages)1057unsigned long perf_event_mlock_kb_in_pages(void)
990{1058{
991 if (pages == UINT_MAX) {1059 unsigned long pages;
992 int max;1060 int max;
993 1061
994 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {1062 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
995 /*1063 /*
996 * Pick a once upon a time good value, i.e. things look1064 * Pick a once upon a time good value, i.e. things look
997 * strange since we can't read a sysctl value, but lets not1065 * strange since we can't read a sysctl value, but lets not
998 * die yet...1066 * die yet...
999 */1067 */
1000 max = 512;1068 max = 512;
1001 } else {1069 } else {
1002 max -= (page_size / 1024);1070 max -= (page_size / 1024);
1003 }1071 }
1004 1072
1005 pages = (max * 1024) / page_size;1073 pages = (max * 1024) / page_size;
1006 if (!is_power_of_2(pages))1074 if (!is_power_of_2(pages))
1007 pages = rounddown_pow_of_two(pages);1075 pages = rounddown_pow_of_two(pages);
1008 } else if (!is_power_of_2(pages))1076
1077 return pages;
1078}
1079
1080static size_t perf_evlist__mmap_size(unsigned long pages)
1081{
1082 if (pages == UINT_MAX)
1083 pages = perf_event_mlock_kb_in_pages();
1084 else if (!is_power_of_2(pages))
1009 return 0;1085 return 0;
1010 1086
1011 return (pages + 1) * page_size;1087 return (pages + 1) * page_size;
@@ -1192,6 +1268,24 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, · 180 unmodified lines
1192 perf_evlist__propagate_maps(evlist);1268 perf_evlist__propagate_maps(evlist);
1193}1269}
1194 1270
1271void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
1272 enum perf_event_sample_format bit)
1273{
1274 struct perf_evsel *evsel;
1275
1276 evlist__for_each(evlist, evsel)
1277 __perf_evsel__set_sample_bit(evsel, bit);
1278}
1279
1280void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
1281 enum perf_event_sample_format bit)
1282{
1283 struct perf_evsel *evsel;
1284
1285 evlist__for_each(evlist, evsel)
1286 __perf_evsel__reset_sample_bit(evsel, bit);
1287}
1288
1195int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)1289int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
1196{1290{
1197 struct perf_evsel *evsel;1291 struct perf_evsel *evsel;
tools/perf/util/evlist.h+21−1
@@ -87,6 +87,17 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist); · 86 unmodified lines
87int perf_evlist__add_newtp(struct perf_evlist *evlist,87int perf_evlist__add_newtp(struct perf_evlist *evlist,
88 const char *sys, const char *name, void *handler);88 const char *sys, const char *name, void *handler);
89 89
90void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
91 enum perf_event_sample_format bit);
92void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
93 enum perf_event_sample_format bit);
94
95#define perf_evlist__set_sample_bit(evlist, bit) \
96 __perf_evlist__set_sample_bit(evlist, PERF_SAMPLE_##bit)
97
98#define perf_evlist__reset_sample_bit(evlist, bit) \
99 __perf_evlist__reset_sample_bit(evlist, PERF_SAMPLE_##bit)
100
90int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);101int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
91int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid);102int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid);
92int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);103int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
@@ -118,16 +129,23 @@ struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); · 25 unmodified lines
118 129
119union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);130union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
120 131
132union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
133 int idx);
134void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
135
121void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);136void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
122 137
123int perf_evlist__open(struct perf_evlist *evlist);138int perf_evlist__open(struct perf_evlist *evlist);
124void perf_evlist__close(struct perf_evlist *evlist);139void perf_evlist__close(struct perf_evlist *evlist);
125 140
141struct callchain_param;
142
126void perf_evlist__set_id_pos(struct perf_evlist *evlist);143void perf_evlist__set_id_pos(struct perf_evlist *evlist);
127bool perf_can_sample_identifier(void);144bool perf_can_sample_identifier(void);
128bool perf_can_record_switch_events(void);145bool perf_can_record_switch_events(void);
129bool perf_can_record_cpu_wide(void);146bool perf_can_record_cpu_wide(void);
130void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts);147void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
148 struct callchain_param *callchain);
131int record_opts__config(struct record_opts *opts);149int record_opts__config(struct record_opts *opts);
132 150
133int perf_evlist__prepare_workload(struct perf_evlist *evlist,151int perf_evlist__prepare_workload(struct perf_evlist *evlist,
@@ -144,6 +162,8 @@ int perf_evlist__parse_mmap_pages(const struct option *opt, · 10 unmodified lines
144 const char *str,162 const char *str,
145 int unset);163 int unset);
146 164
165unsigned long perf_event_mlock_kb_in_pages(void);
166
147int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,167int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
148 bool overwrite, unsigned int auxtrace_pages,168 bool overwrite, unsigned int auxtrace_pages,
149 bool auxtrace_overwrite);169 bool auxtrace_overwrite);
tools/perf/util/evsel.c+38−101
@@ -226,7 +226,8 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx) · 225 unmodified lines
226 perf_evsel__init(evsel, attr, idx);226 perf_evsel__init(evsel, attr, idx);
227 227
228 if (perf_evsel__is_bpf_output(evsel)) {228 if (perf_evsel__is_bpf_output(evsel)) {
229 evsel->attr.sample_type |= PERF_SAMPLE_RAW;229 evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
230 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
230 evsel->attr.sample_period = 1;231 evsel->attr.sample_period = 1;
231 }232 }
232 233
@@ -561,10 +562,9 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size) · 328 unmodified lines
561 return ret;562 return ret;
562}563}
563 564
564static void565void perf_evsel__config_callchain(struct perf_evsel *evsel,
565perf_evsel__config_callgraph(struct perf_evsel *evsel,566 struct record_opts *opts,
566 struct record_opts *opts,567 struct callchain_param *param)
567 struct callchain_param *param)
568{568{
569 bool function = perf_evsel__is_function_event(evsel);569 bool function = perf_evsel__is_function_event(evsel);
570 struct perf_event_attr *attr = &evsel->attr;570 struct perf_event_attr *attr = &evsel->attr;
@@ -704,7 +704,7 @@ static void apply_config_terms(struct perf_evsel *evsel, · 133 unmodified lines
704 704
705 /* set perf-event callgraph */705 /* set perf-event callgraph */
706 if (param.enabled)706 if (param.enabled)
707 perf_evsel__config_callgraph(evsel, opts, &param);707 perf_evsel__config_callchain(evsel, opts, &param);
708 }708 }
709}709}
710 710
@@ -736,7 +736,8 @@ static void apply_config_terms(struct perf_evsel *evsel, · 25 unmodified lines
736 * enable/disable events specifically, as there's no736 * enable/disable events specifically, as there's no
737 * initial traced exec call.737 * initial traced exec call.
738 */738 */
739void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)739void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
740 struct callchain_param *callchain)
740{741{
741 struct perf_evsel *leader = evsel->leader;742 struct perf_evsel *leader = evsel->leader;
742 struct perf_event_attr *attr = &evsel->attr;743 struct perf_event_attr *attr = &evsel->attr;
@@ -811,8 +812,8 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) · 68 unmodified lines
811 if (perf_evsel__is_function_event(evsel))812 if (perf_evsel__is_function_event(evsel))
812 evsel->attr.exclude_callchain_user = 1;813 evsel->attr.exclude_callchain_user = 1;
813 814
814 if (callchain_param.enabled && !evsel->no_aux_samples)815 if (callchain && callchain->enabled && !evsel->no_aux_samples)
815 perf_evsel__config_callgraph(evsel, opts, &callchain_param);816 perf_evsel__config_callchain(evsel, opts, callchain);
816 817
817 if (opts->sample_intr_regs) {818 if (opts->sample_intr_regs) {
818 attr->sample_regs_intr = opts->sample_intr_regs;819 attr->sample_regs_intr = opts->sample_intr_regs;
@@ -1230,6 +1231,21 @@ static void __p_sample_type(char *buf, size_t size, u64 value) · 411 unmodified lines
1230 __p_bits(buf, size, value, bits);1231 __p_bits(buf, size, value, bits);
1231}1232}
1232 1233
1234static void __p_branch_sample_type(char *buf, size_t size, u64 value)
1235{
1236#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n }
1237 struct bit_names bits[] = {
1238 bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY),
1239 bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL),
1240 bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX),
1241 bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP),
1242 bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES),
1243 { .name = NULL, }
1244 };
1245#undef bit_name
1246 __p_bits(buf, size, value, bits);
1247}
1248
1233static void __p_read_format(char *buf, size_t size, u64 value)1249static void __p_read_format(char *buf, size_t size, u64 value)
1234{1250{
1235#define bit_name(n) { PERF_FORMAT_##n, #n }1251#define bit_name(n) { PERF_FORMAT_##n, #n }
@@ -1248,6 +1264,7 @@ static void __p_read_format(char *buf, size_t size, u64 value) · 12 unmodified lines
1248#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))1264#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val))
1249#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))1265#define p_signed(val) snprintf(buf, BUF_SIZE, "%"PRId64, (int64_t)(val))
1250#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)1266#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
1267#define p_branch_sample_type(val) __p_branch_sample_type(buf, BUF_SIZE, val)
1251#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)1268#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)
1252 1269
1253#define PRINT_ATTRn(_n, _f, _p) \1270#define PRINT_ATTRn(_n, _f, _p) \
@@ -1299,12 +1316,13 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, · 45 unmodified lines
1299 PRINT_ATTRf(comm_exec, p_unsigned);1316 PRINT_ATTRf(comm_exec, p_unsigned);
1300 PRINT_ATTRf(use_clockid, p_unsigned);1317 PRINT_ATTRf(use_clockid, p_unsigned);
1301 PRINT_ATTRf(context_switch, p_unsigned);1318 PRINT_ATTRf(context_switch, p_unsigned);
1319 PRINT_ATTRf(write_backward, p_unsigned);
1302 1320
1303 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);1321 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
1304 PRINT_ATTRf(bp_type, p_unsigned);1322 PRINT_ATTRf(bp_type, p_unsigned);
1305 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);1323 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1306 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);1324 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1307 PRINT_ATTRf(branch_sample_type, p_unsigned);1325 PRINT_ATTRf(branch_sample_type, p_branch_sample_type);
1308 PRINT_ATTRf(sample_regs_user, p_hex);1326 PRINT_ATTRf(sample_regs_user, p_hex);
1309 PRINT_ATTRf(sample_stack_user, p_unsigned);1327 PRINT_ATTRf(sample_stack_user, p_unsigned);
1310 PRINT_ATTRf(clockid, p_signed);1328 PRINT_ATTRf(clockid, p_signed);
@@ -2253,95 +2271,6 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, · 942 unmodified lines
2253 return 0;2271 return 0;
2254}2272}
2255 2273
2256static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
2257{
2258 va_list args;
2259 int ret = 0;
2260
2261 if (!*first) {
2262 ret += fprintf(fp, ",");
2263 } else {
2264 ret += fprintf(fp, ":");
2265 *first = false;
2266 }
2267
2268 va_start(args, fmt);
2269 ret += vfprintf(fp, fmt, args);
2270 va_end(args);
2271 return ret;
2272}
2273
2274static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
2275{
2276 return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
2277}
2278
2279int perf_evsel__fprintf(struct perf_evsel *evsel,
2280 struct perf_attr_details *details, FILE *fp)
2281{
2282 bool first = true;
2283 int printed = 0;
2284
2285 if (details->event_group) {
2286 struct perf_evsel *pos;
2287
2288 if (!perf_evsel__is_group_leader(evsel))
2289 return 0;
2290
2291 if (evsel->nr_members > 1)
2292 printed += fprintf(fp, "%s{", evsel->group_name ?: "");
2293
2294 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
2295 for_each_group_member(pos, evsel)
2296 printed += fprintf(fp, ",%s", perf_evsel__name(pos));
2297
2298 if (evsel->nr_members > 1)
2299 printed += fprintf(fp, "}");
2300 goto out;
2301 }
2302
2303 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
2304
2305 if (details->verbose) {
2306 printed += perf_event_attr__fprintf(fp, &evsel->attr,
2307 __print_attr__fprintf, &first);
2308 } else if (details->freq) {
2309 const char *term = "sample_freq";
2310
2311 if (!evsel->attr.freq)
2312 term = "sample_period";
2313
2314 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
2315 term, (u64)evsel->attr.sample_freq);
2316 }
2317
2318 if (details->trace_fields) {
2319 struct format_field *field;
2320
2321 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2322 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
2323 goto out;
2324 }
2325
2326 field = evsel->tp_format->format.fields;
2327 if (field == NULL) {
2328 printed += comma_fprintf(fp, &first, " (no trace field)");
2329 goto out;
2330 }
2331
2332 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
2333
2334 field = field->next;
2335 while (field) {
2336 printed += comma_fprintf(fp, &first, "%s", field->name);
2337 field = field->next;
2338 }
2339 }
2340out:
2341 fputc('\n', fp);
2342 return ++printed;
2343}
2344
2345bool perf_evsel__fallback(struct perf_evsel *evsel, int err,2274bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2346 char *msg, size_t msgsize)2275 char *msg, size_t msgsize)
2347{2276{
@@ -2416,10 +2345,18 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, · 68 unmodified lines
2416 "Probably the maximum number of open file descriptors has been reached.\n"2345 "Probably the maximum number of open file descriptors has been reached.\n"
2417 "Hint: Try again after reducing the number of events.\n"2346 "Hint: Try again after reducing the number of events.\n"
2418 "Hint: Try increasing the limit with 'ulimit -n <limit>'");2347 "Hint: Try increasing the limit with 'ulimit -n <limit>'");
2348 case ENOMEM:
2349 if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 &&
2350 access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0)
2351 return scnprintf(msg, size,
2352 "Not enough memory to setup event with callchain.\n"
2353 "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
2354 "Hint: Current value: %d", sysctl_perf_event_max_stack);
2355 break;
2419 case ENODEV:2356 case ENODEV:
2420 if (target->cpu_list)2357 if (target->cpu_list)
2421 return scnprintf(msg, size, "%s",2358 return scnprintf(msg, size, "%s",
2422 "No such device - did you specify an out-of-range profile CPU?\n");2359 "No such device - did you specify an out-of-range profile CPU?");
2423 break;2360 break;
2424 case EOPNOTSUPP:2361 case EOPNOTSUPP:
2425 if (evsel->attr.precise_ip)2362 if (evsel->attr.precise_ip)
@@ -2451,7 +2388,7 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, · 25 unmodified lines
2451 return scnprintf(msg, size,2388 return scnprintf(msg, size,
2452 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"2389 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2453 "/bin/dmesg may provide additional information.\n"2390 "/bin/dmesg may provide additional information.\n"
2454 "No CONFIG_PERF_EVENTS=y kernel support configured?\n",2391 "No CONFIG_PERF_EVENTS=y kernel support configured?",
2455 err, strerror_r(err, sbuf, sizeof(sbuf)),2392 err, strerror_r(err, sbuf, sizeof(sbuf)),
2456 perf_evsel__name(evsel));2393 perf_evsel__name(evsel));
2457}2394}
tools/perf/util/evsel.h+26−2
@@ -178,8 +178,14 @@ void perf_evsel__init(struct perf_evsel *evsel, · 177 unmodified lines
178void perf_evsel__exit(struct perf_evsel *evsel);178void perf_evsel__exit(struct perf_evsel *evsel);
179void perf_evsel__delete(struct perf_evsel *evsel);179void perf_evsel__delete(struct perf_evsel *evsel);
180 180
181struct callchain_param;
182
181void perf_evsel__config(struct perf_evsel *evsel,183void perf_evsel__config(struct perf_evsel *evsel,
182 struct record_opts *opts);184 struct record_opts *opts,
185 struct callchain_param *callchain);
186void perf_evsel__config_callchain(struct perf_evsel *evsel,
187 struct record_opts *opts,
188 struct callchain_param *callchain);
183 189
184int __perf_evsel__sample_size(u64 sample_type);190int __perf_evsel__sample_size(u64 sample_type);
185void perf_evsel__calc_id_pos(struct perf_evsel *evsel);191void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
@@ -381,6 +387,24 @@ struct perf_attr_details { · 195 unmodified lines
381int perf_evsel__fprintf(struct perf_evsel *evsel,387int perf_evsel__fprintf(struct perf_evsel *evsel,
382 struct perf_attr_details *details, FILE *fp);388 struct perf_attr_details *details, FILE *fp);
383 389
390#define EVSEL__PRINT_IP (1<<0)
391#define EVSEL__PRINT_SYM (1<<1)
392#define EVSEL__PRINT_DSO (1<<2)
393#define EVSEL__PRINT_SYMOFFSET (1<<3)
394#define EVSEL__PRINT_ONELINE (1<<4)
395#define EVSEL__PRINT_SRCLINE (1<<5)
396#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6)
397
398struct callchain_cursor;
399
400int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
401 unsigned int print_opts,
402 struct callchain_cursor *cursor, FILE *fp);
403
404int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
405 int left_alignment, unsigned int print_opts,
406 struct callchain_cursor *cursor, FILE *fp);
407
384bool perf_evsel__fallback(struct perf_evsel *evsel, int err,408bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
385 char *msg, size_t msgsize);409 char *msg, size_t msgsize);
386int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,410int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
@@ -396,7 +420,7 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \ · 9 unmodified lines
396 (_evsel) && (_evsel)->leader == (_leader); \420 (_evsel) && (_evsel)->leader == (_leader); \
397 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))421 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
398 422
399static inline bool has_branch_callstack(struct perf_evsel *evsel)423static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
400{424{
401 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;425 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
402}426}
tools/perf/util/evsel_fprintf.c+212−0
@@ -0,0 +1,212 @@
1#include <stdio.h>
2#include <stdbool.h>
3#include <traceevent/event-parse.h>
4#include "evsel.h"
5#include "callchain.h"
6#include "map.h"
7#include "symbol.h"
8
9static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
10{
11 va_list args;
12 int ret = 0;
13
14 if (!*first) {
15 ret += fprintf(fp, ",");
16 } else {
17 ret += fprintf(fp, ":");
18 *first = false;
19 }
20
21 va_start(args, fmt);
22 ret += vfprintf(fp, fmt, args);
23 va_end(args);
24 return ret;
25}
26
27static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
28{
29 return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
30}
31
32int perf_evsel__fprintf(struct perf_evsel *evsel,
33 struct perf_attr_details *details, FILE *fp)
34{
35 bool first = true;
36 int printed = 0;
37
38 if (details->event_group) {
39 struct perf_evsel *pos;
40
41 if (!perf_evsel__is_group_leader(evsel))
42 return 0;
43
44 if (evsel->nr_members > 1)
45 printed += fprintf(fp, "%s{", evsel->group_name ?: "");
46
47 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
48 for_each_group_member(pos, evsel)
49 printed += fprintf(fp, ",%s", perf_evsel__name(pos));
50
51 if (evsel->nr_members > 1)
52 printed += fprintf(fp, "}");
53 goto out;
54 }
55
56 printed += fprintf(fp, "%s", perf_evsel__name(evsel));
57
58 if (details->verbose) {
59 printed += perf_event_attr__fprintf(fp, &evsel->attr,
60 __print_attr__fprintf, &first);
61 } else if (details->freq) {
62 const char *term = "sample_freq";
63
64 if (!evsel->attr.freq)
65 term = "sample_period";
66
67 printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
68 term, (u64)evsel->attr.sample_freq);
69 }
70
71 if (details->trace_fields) {
72 struct format_field *field;
73
74 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
75 printed += comma_fprintf(fp, &first, " (not a tracepoint)");
76 goto out;
77 }
78
79 field = evsel->tp_format->format.fields;
80 if (field == NULL) {
81 printed += comma_fprintf(fp, &first, " (no trace field)");
82 goto out;
83 }
84
85 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
86
87 field = field->next;
88 while (field) {
89 printed += comma_fprintf(fp, &first, "%s", field->name);
90 field = field->next;
91 }
92 }
93out:
94 fputc('\n', fp);
95 return ++printed;
96}
97
98int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
99 unsigned int print_opts, struct callchain_cursor *cursor,
100 FILE *fp)
101{
102 int printed = 0;
103 struct callchain_cursor_node *node;
104 int print_ip = print_opts & EVSEL__PRINT_IP;
105 int print_sym = print_opts & EVSEL__PRINT_SYM;
106 int print_dso = print_opts & EVSEL__PRINT_DSO;
107 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
108 int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
109 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
110 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
111 char s = print_oneline ? ' ' : '\t';
112
113 if (sample->callchain) {
114 struct addr_location node_al;
115
116 callchain_cursor_commit(cursor);
117
118 while (1) {
119 u64 addr = 0;
120
121 node = callchain_cursor_current(cursor);
122 if (!node)
123 break;
124
125 if (node->sym && node->sym->ignore)
126 goto next;
127
128 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
129
130 if (print_ip)
131 printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
132
133 if (node->map)
134 addr = node->map->map_ip(node->map, node->ip);
135
136 if (print_sym) {
137 printed += fprintf(fp, " ");
138 node_al.addr = addr;
139 node_al.map = node->map;
140
141 if (print_symoffset) {
142 printed += __symbol__fprintf_symname_offs(node->sym, &node_al,
143 print_unknown_as_addr, fp);
144 } else {
145 printed += __symbol__fprintf_symname(node->sym, &node_al,
146 print_unknown_as_addr, fp);
147 }
148 }
149
150 if (print_dso) {
151 printed += fprintf(fp, " (");
152 printed += map__fprintf_dsoname(node->map, fp);
153 printed += fprintf(fp, ")");
154 }
155
156 if (print_srcline)
157 printed += map__fprintf_srcline(node->map, addr, "\n ", fp);
158
159 if (!print_oneline)
160 printed += fprintf(fp, "\n");
161next:
162 callchain_cursor_advance(cursor);
163 }
164 }
165
166 return printed;
167}
168
169int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
170 int left_alignment, unsigned int print_opts,
171 struct callchain_cursor *cursor, FILE *fp)
172{
173 int printed = 0;
174 int print_ip = print_opts & EVSEL__PRINT_IP;
175 int print_sym = print_opts & EVSEL__PRINT_SYM;
176 int print_dso = print_opts & EVSEL__PRINT_DSO;
177 int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
178 int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
179 int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
180
181 if (cursor != NULL) {
182 printed += sample__fprintf_callchain(sample, left_alignment,
183 print_opts, cursor, fp);
184 } else if (!(al->sym && al->sym->ignore)) {
185 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
186
187 if (print_ip)
188 printed += fprintf(fp, "%16" PRIx64, sample->ip);
189
190 if (print_sym) {
191 printed += fprintf(fp, " ");
192 if (print_symoffset) {
193 printed += __symbol__fprintf_symname_offs(al->sym, al,
194 print_unknown_as_addr, fp);
195 } else {
196 printed += __symbol__fprintf_symname(al->sym, al,
197 print_unknown_as_addr, fp);
198 }
199 }
200
201 if (print_dso) {
202 printed += fprintf(fp, " (");
203 printed += map__fprintf_dsoname(al->map, fp);
204 printed += fprintf(fp, ")");
205 }
206
207 if (print_srcline)
208 printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
209 }
210
211 return printed;
212}
tools/perf/util/header.c+21−12
@@ -1474,7 +1474,7 @@ static int __event_process_build_id(struct build_id_event *bev, · 1473 unmodified lines
1474 1474
1475 dso = machine__findnew_dso(machine, filename);1475 dso = machine__findnew_dso(machine, filename);
1476 if (dso != NULL) {1476 if (dso != NULL) {
1477 char sbuild_id[BUILD_ID_SIZE * 2 + 1];1477 char sbuild_id[SBUILD_ID_SIZE];
1478 1478
1479 dso__set_build_id(dso, &bev->build_id);1479 dso__set_build_id(dso, &bev->build_id);
1480 1480
@@ -1819,7 +1819,8 @@ static int process_cpu_topology(struct perf_file_section *section, · 338 unmodified lines
1819 1819
1820 ph->env.nr_sibling_cores = nr;1820 ph->env.nr_sibling_cores = nr;
1821 size += sizeof(u32);1821 size += sizeof(u32);
1822 strbuf_init(&sb, 128);1822 if (strbuf_init(&sb, 128) < 0)
1823 goto free_cpu;
1823 1824
1824 for (i = 0; i < nr; i++) {1825 for (i = 0; i < nr; i++) {
1825 str = do_read_string(fd, ph);1826 str = do_read_string(fd, ph);
@@ -1827,7 +1828,8 @@ static int process_cpu_topology(struct perf_file_section *section, · 1 unmodified line
1827 goto error;1828 goto error;
1828 1829
1829 /* include a NULL character at the end */1830 /* include a NULL character at the end */
1830 strbuf_add(&sb, str, strlen(str) + 1);1831 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1832 goto error;
1831 size += string_size(str);1833 size += string_size(str);
1832 free(str);1834 free(str);
1833 }1835 }
@@ -1849,7 +1851,8 @@ static int process_cpu_topology(struct perf_file_section *section, · 15 unmodified lines
1849 goto error;1851 goto error;
1850 1852
1851 /* include a NULL character at the end */1853 /* include a NULL character at the end */
1852 strbuf_add(&sb, str, strlen(str) + 1);1854 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1855 goto error;
1853 size += string_size(str);1856 size += string_size(str);
1854 free(str);1857 free(str);
1855 }1858 }
@@ -1912,13 +1915,14 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse · 56 unmodified lines
1912 /* nr nodes */1915 /* nr nodes */
1913 ret = readn(fd, &nr, sizeof(nr));1916 ret = readn(fd, &nr, sizeof(nr));
1914 if (ret != sizeof(nr))1917 if (ret != sizeof(nr))
1915 goto error;1918 return -1;
1916 1919
1917 if (ph->needs_swap)1920 if (ph->needs_swap)
1918 nr = bswap_32(nr);1921 nr = bswap_32(nr);
1919 1922
1920 ph->env.nr_numa_nodes = nr;1923 ph->env.nr_numa_nodes = nr;
1921 strbuf_init(&sb, 256);1924 if (strbuf_init(&sb, 256) < 0)
1925 return -1;
1922 1926
1923 for (i = 0; i < nr; i++) {1927 for (i = 0; i < nr; i++) {
1924 /* node number */1928 /* node number */
@@ -1940,15 +1944,17 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse · 15 unmodified lines
1940 mem_free = bswap_64(mem_free);1944 mem_free = bswap_64(mem_free);
1941 }1945 }
1942 1946
1943 strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",1947 if (strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
1944 node, mem_total, mem_free);1948 node, mem_total, mem_free) < 0)
1949 goto error;
1945 1950
1946 str = do_read_string(fd, ph);1951 str = do_read_string(fd, ph);
1947 if (!str)1952 if (!str)
1948 goto error;1953 goto error;
1949 1954
1950 /* include a NULL character at the end */1955 /* include a NULL character at the end */
1951 strbuf_add(&sb, str, strlen(str) + 1);1956 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1957 goto error;
1952 free(str);1958 free(str);
1953 }1959 }
1954 ph->env.numa_nodes = strbuf_detach(&sb, NULL);1960 ph->env.numa_nodes = strbuf_detach(&sb, NULL);
@@ -1982,7 +1988,8 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused · 27 unmodified lines
1982 }1988 }
1983 1989
1984 ph->env.nr_pmu_mappings = pmu_num;1990 ph->env.nr_pmu_mappings = pmu_num;
1985 strbuf_init(&sb, 128);1991 if (strbuf_init(&sb, 128) < 0)
1992 return -1;
1986 1993
1987 while (pmu_num) {1994 while (pmu_num) {
1988 if (readn(fd, &type, sizeof(type)) != sizeof(type))1995 if (readn(fd, &type, sizeof(type)) != sizeof(type))
@@ -1994,9 +2001,11 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused · 5 unmodified lines
1994 if (!name)2001 if (!name)
1995 goto error;2002 goto error;
1996 2003
1997 strbuf_addf(&sb, "%u:%s", type, name);2004 if (strbuf_addf(&sb, "%u:%s", type, name) < 0)
2005 goto error;
1998 /* include a NULL character at the end */2006 /* include a NULL character at the end */
1999 strbuf_add(&sb, "", 1);2007 if (strbuf_add(&sb, "", 1) < 0)
2008 goto error;
2000 2009
2001 if (!strcmp(name, "msr"))2010 if (!strcmp(name, "msr"))
2002 ph->env.msr_pmu_type = type;2011 ph->env.msr_pmu_type = type;
tools/perf/util/help-unknown-cmd.c+22−8
@@ -27,16 +27,27 @@ static int levenshtein_compare(const void *p1, const void *p2) · 26 unmodified lines
27 return l1 != l2 ? l1 - l2 : strcmp(s1, s2);27 return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
28}28}
29 29
30static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)30static int add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
31{31{
32 unsigned int i;32 unsigned int i, nr = cmds->cnt + old->cnt;
33 33 void *tmp;
34 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc);34
35 35 if (nr > cmds->alloc) {
36 /* Choose bigger one to alloc */
37 if (alloc_nr(cmds->alloc) < nr)
38 cmds->alloc = nr;
39 else
40 cmds->alloc = alloc_nr(cmds->alloc);
41 tmp = realloc(cmds->names, cmds->alloc * sizeof(*cmds->names));
42 if (!tmp)
43 return -1;
44 cmds->names = tmp;
45 }
36 for (i = 0; i < old->cnt; i++)46 for (i = 0; i < old->cnt; i++)
37 cmds->names[cmds->cnt++] = old->names[i];47 cmds->names[cmds->cnt++] = old->names[i];
38 zfree(&old->names);48 zfree(&old->names);
39 old->cnt = 0;49 old->cnt = 0;
50 return 0;
40}51}
41 52
42const char *help_unknown_cmd(const char *cmd)53const char *help_unknown_cmd(const char *cmd)
@@ -52,8 +63,11 @@ const char *help_unknown_cmd(const char *cmd) · 9 unmodified lines
52 63
53 load_command_list("perf-", &main_cmds, &other_cmds);64 load_command_list("perf-", &main_cmds, &other_cmds);
54 65
55 add_cmd_list(&main_cmds, &aliases);66 if (add_cmd_list(&main_cmds, &aliases) < 0 ||
56 add_cmd_list(&main_cmds, &other_cmds);67 add_cmd_list(&main_cmds, &other_cmds) < 0) {
68 fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n");
69 goto end;
70 }
57 qsort(main_cmds.names, main_cmds.cnt,71 qsort(main_cmds.names, main_cmds.cnt,
58 sizeof(main_cmds.names), cmdname_compare);72 sizeof(main_cmds.names), cmdname_compare);
59 uniq(&main_cmds);73 uniq(&main_cmds);
@@ -99,6 +113,6 @@ const char *help_unknown_cmd(const char *cmd) · 39 unmodified lines
99 for (i = 0; i < n; i++)113 for (i = 0; i < n; i++)
100 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);114 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
101 }115 }
102 116end:
103 exit(1);117 exit(1);
104}118}
tools/perf/util/hist.c+13−10
@@ -295,7 +295,7 @@ static void hists__delete_entry(struct hists *hists, struct hist_entry *he) · 294 unmodified lines
295 root_in = &he->parent_he->hroot_in;295 root_in = &he->parent_he->hroot_in;
296 root_out = &he->parent_he->hroot_out;296 root_out = &he->parent_he->hroot_out;
297 } else {297 } else {
298 if (sort__need_collapse)298 if (hists__has(hists, need_collapse))
299 root_in = &hists->entries_collapsed;299 root_in = &hists->entries_collapsed;
300 else300 else
301 root_in = hists->entries_in;301 root_in = hists->entries_in;
@@ -953,7 +953,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, · 651 unmodified lines
953{953{
954 int err, err2;954 int err, err2;
955 955
956 err = sample__resolve_callchain(iter->sample, &iter->parent,956 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
957 iter->evsel, al, max_stack_depth);957 iter->evsel, al, max_stack_depth);
958 if (err)958 if (err)
959 return err;959 return err;
@@ -1295,8 +1295,9 @@ static int hists__hierarchy_insert_entry(struct hists *hists, · 335 unmodified lines
1295 return ret;1295 return ret;
1296}1296}
1297 1297
1298int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root,1298static int hists__collapse_insert_entry(struct hists *hists,
1299 struct hist_entry *he)1299 struct rb_root *root,
1300 struct hist_entry *he)
1300{1301{
1301 struct rb_node **p = &root->rb_node;1302 struct rb_node **p = &root->rb_node;
1302 struct rb_node *parent = NULL;1303 struct rb_node *parent = NULL;
@@ -1372,7 +1373,7 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog) · 69 unmodified lines
1372 struct hist_entry *n;1373 struct hist_entry *n;
1373 int ret;1374 int ret;
1374 1375
1375 if (!sort__need_collapse)1376 if (!hists__has(hists, need_collapse))
1376 return 0;1377 return 0;
1377 1378
1378 hists->nr_entries = 0;1379 hists->nr_entries = 0;
@@ -1631,7 +1632,7 @@ static void output_resort(struct hists *hists, struct ui_progress *prog, · 252 unmodified lines
1631 return;1632 return;
1632 }1633 }
1633 1634
1634 if (sort__need_collapse)1635 if (hists__has(hists, need_collapse))
1635 root = &hists->entries_collapsed;1636 root = &hists->entries_collapsed;
1636 else1637 else
1637 root = hists->entries_in;1638 root = hists->entries_in;
@@ -2035,7 +2036,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, · 397 unmodified lines
2035 struct hist_entry *he;2036 struct hist_entry *he;
2036 int64_t cmp;2037 int64_t cmp;
2037 2038
2038 if (sort__need_collapse)2039 if (hists__has(hists, need_collapse))
2039 root = &hists->entries_collapsed;2040 root = &hists->entries_collapsed;
2040 else2041 else
2041 root = hists->entries_in;2042 root = hists->entries_in;
@@ -2061,6 +2062,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists, · 19 unmodified lines
2061 if (he) {2062 if (he) {
2062 memset(&he->stat, 0, sizeof(he->stat));2063 memset(&he->stat, 0, sizeof(he->stat));
2063 he->hists = hists;2064 he->hists = hists;
2065 if (symbol_conf.cumulate_callchain)
2066 memset(he->stat_acc, 0, sizeof(he->stat));
2064 rb_link_node(&he->rb_node_in, parent, p);2067 rb_link_node(&he->rb_node_in, parent, p);
2065 rb_insert_color(&he->rb_node_in, root);2068 rb_insert_color(&he->rb_node_in, root);
2066 hists__inc_stats(hists, he);2069 hists__inc_stats(hists, he);
@@ -2075,7 +2078,7 @@ static struct hist_entry *hists__find_entry(struct hists *hists, · 8 unmodified lines
2075{2078{
2076 struct rb_node *n;2079 struct rb_node *n;
2077 2080
2078 if (sort__need_collapse)2081 if (hists__has(hists, need_collapse))
2079 n = hists->entries_collapsed.rb_node;2082 n = hists->entries_collapsed.rb_node;
2080 else2083 else
2081 n = hists->entries_in->rb_node;2084 n = hists->entries_in->rb_node;
@@ -2104,7 +2107,7 @@ void hists__match(struct hists *leader, struct hists *other) · 22 unmodified lines
2104 struct rb_node *nd;2107 struct rb_node *nd;
2105 struct hist_entry *pos, *pair;2108 struct hist_entry *pos, *pair;
2106 2109
2107 if (sort__need_collapse)2110 if (hists__has(leader, need_collapse))
2108 root = &leader->entries_collapsed;2111 root = &leader->entries_collapsed;
2109 else2112 else
2110 root = leader->entries_in;2113 root = leader->entries_in;
@@ -2129,7 +2132,7 @@ int hists__link(struct hists *leader, struct hists *other) · 18 unmodified lines
2129 struct rb_node *nd;2132 struct rb_node *nd;
2130 struct hist_entry *pos, *pair;2133 struct hist_entry *pos, *pair;
2131 2134
2132 if (sort__need_collapse)2135 if (hists__has(other, need_collapse))
2133 root = &other->entries_collapsed;2136 root = &other->entries_collapsed;
2134 else2137 else
2135 root = other->entries_in;2138 root = other->entries_in;
tools/perf/util/hist.h+10−2
@@ -82,6 +82,8 @@ struct hists { · 81 unmodified lines
82 int nr_hpp_node;82 int nr_hpp_node;
83};83};
84 84
85#define hists__has(__h, __f) (__h)->hpp_list->__f
86
85struct hist_entry_iter;87struct hist_entry_iter;
86 88
87struct hist_iter_ops {89struct hist_iter_ops {
@@ -199,8 +201,6 @@ int hists__init(void); · 111 unmodified lines
199int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);201int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);
200 202
201struct rb_root *hists__get_rotate_entries_in(struct hists *hists);203struct rb_root *hists__get_rotate_entries_in(struct hists *hists);
202int hists__collapse_insert_entry(struct hists *hists,
203 struct rb_root *root, struct hist_entry *he);
204 204
205struct perf_hpp {205struct perf_hpp {
206 char *buf;206 char *buf;
@@ -240,6 +240,14 @@ struct perf_hpp_fmt { · 33 unmodified lines
240struct perf_hpp_list {240struct perf_hpp_list {
241 struct list_head fields;241 struct list_head fields;
242 struct list_head sorts;242 struct list_head sorts;
243
244 int need_collapse;
245 int parent;
246 int sym;
247 int dso;
248 int socket;
249 int thread;
250 int comm;
243};251};
244 252
245extern struct perf_hpp_list perf_hpp_list;253extern struct perf_hpp_list perf_hpp_list;
tools/perf/util/intel-bts.c+5−0
@@ -66,6 +66,7 @@ struct intel_bts { · 65 unmodified lines
66 u64 branches_id;66 u64 branches_id;
67 size_t branches_event_size;67 size_t branches_event_size;
68 bool synth_needs_swap;68 bool synth_needs_swap;
69 unsigned long num_events;
69};70};
70 71
71struct intel_bts_queue {72struct intel_bts_queue {
@@ -275,6 +276,10 @@ static int intel_bts_synth_branch_sample(struct intel_bts_queue *btsq, · 203 unmodified lines
275 union perf_event event;276 union perf_event event;
276 struct perf_sample sample = { .ip = 0, };277 struct perf_sample sample = { .ip = 0, };
277 278
279 if (bts->synth_opts.initial_skip &&
280 bts->num_events++ <= bts->synth_opts.initial_skip)
281 return 0;
282
278 event.sample.header.type = PERF_RECORD_SAMPLE;283 event.sample.header.type = PERF_RECORD_SAMPLE;
279 event.sample.header.misc = PERF_RECORD_MISC_USER;284 event.sample.header.misc = PERF_RECORD_MISC_USER;
280 event.sample.header.size = sizeof(struct perf_event_header);285 event.sample.header.size = sizeof(struct perf_event_header);
tools/perf/util/intel-pt-decoder/intel-pt-decoder.c+1−1
@@ -356,7 +356,7 @@ static const char *intel_pt_err_msgs[] = { · 355 unmodified lines
356 356
357int intel_pt__strerror(int code, char *buf, size_t buflen)357int intel_pt__strerror(int code, char *buf, size_t buflen)
358{358{
359 if (code < 1 || code > INTEL_PT_ERR_MAX)359 if (code < 1 || code >= INTEL_PT_ERR_MAX)
360 code = INTEL_PT_ERR_UNK;360 code = INTEL_PT_ERR_UNK;
361 strlcpy(buf, intel_pt_err_msgs[code], buflen);361 strlcpy(buf, intel_pt_err_msgs[code], buflen);
362 return 0;362 return 0;
tools/perf/util/intel-pt.c+20−2
@@ -100,6 +100,8 @@ struct intel_pt { · 99 unmodified lines
100 u64 cyc_bit;100 u64 cyc_bit;
101 u64 noretcomp_bit;101 u64 noretcomp_bit;
102 unsigned max_non_turbo_ratio;102 unsigned max_non_turbo_ratio;
103
104 unsigned long num_events;
103};105};
104 106
105enum switch_state {107enum switch_state {
@@ -972,6 +974,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq) · 866 unmodified lines
972 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))974 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
973 return 0;975 return 0;
974 976
977 if (pt->synth_opts.initial_skip &&
978 pt->num_events++ < pt->synth_opts.initial_skip)
979 return 0;
980
975 event->sample.header.type = PERF_RECORD_SAMPLE;981 event->sample.header.type = PERF_RECORD_SAMPLE;
976 event->sample.header.misc = PERF_RECORD_MISC_USER;982 event->sample.header.misc = PERF_RECORD_MISC_USER;
977 event->sample.header.size = sizeof(struct perf_event_header);983 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1029,6 +1035,10 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq) · 51 unmodified lines
1029 union perf_event *event = ptq->event_buf;1035 union perf_event *event = ptq->event_buf;
1030 struct perf_sample sample = { .ip = 0, };1036 struct perf_sample sample = { .ip = 0, };
1031 1037
1038 if (pt->synth_opts.initial_skip &&
1039 pt->num_events++ < pt->synth_opts.initial_skip)
1040 return 0;
1041
1032 event->sample.header.type = PERF_RECORD_SAMPLE;1042 event->sample.header.type = PERF_RECORD_SAMPLE;
1033 event->sample.header.misc = PERF_RECORD_MISC_USER;1043 event->sample.header.misc = PERF_RECORD_MISC_USER;
1034 event->sample.header.size = sizeof(struct perf_event_header);1044 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1087,6 +1097,10 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq) · 52 unmodified lines
1087 union perf_event *event = ptq->event_buf;1097 union perf_event *event = ptq->event_buf;
1088 struct perf_sample sample = { .ip = 0, };1098 struct perf_sample sample = { .ip = 0, };
1089 1099
1100 if (pt->synth_opts.initial_skip &&
1101 pt->num_events++ < pt->synth_opts.initial_skip)
1102 return 0;
1103
1090 event->sample.header.type = PERF_RECORD_SAMPLE;1104 event->sample.header.type = PERF_RECORD_SAMPLE;
1091 event->sample.header.misc = PERF_RECORD_MISC_USER;1105 event->sample.header.misc = PERF_RECORD_MISC_USER;
1092 event->sample.header.size = sizeof(struct perf_event_header);1106 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1199,14 +1213,18 @@ static int intel_pt_sample(struct intel_pt_queue *ptq) · 106 unmodified lines
1199 ptq->have_sample = false;1213 ptq->have_sample = false;
1200 1214
1201 if (pt->sample_instructions &&1215 if (pt->sample_instructions &&
1202 (state->type & INTEL_PT_INSTRUCTION)) {1216 (state->type & INTEL_PT_INSTRUCTION) &&
1217 (!pt->synth_opts.initial_skip ||
1218 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1203 err = intel_pt_synth_instruction_sample(ptq);1219 err = intel_pt_synth_instruction_sample(ptq);
1204 if (err)1220 if (err)
1205 return err;1221 return err;
1206 }1222 }
1207 1223
1208 if (pt->sample_transactions &&1224 if (pt->sample_transactions &&
1209 (state->type & INTEL_PT_TRANSACTION)) {1225 (state->type & INTEL_PT_TRANSACTION) &&
1226 (!pt->synth_opts.initial_skip ||
1227 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1210 err = intel_pt_synth_transaction_sample(ptq);1228 err = intel_pt_synth_transaction_sample(ptq);
1211 if (err)1229 if (err)
1212 return err;1230 return err;
tools/perf/util/jitdump.c+34−7
@@ -17,6 +17,7 @@ · 16 unmodified lines
17#include "strlist.h"17#include "strlist.h"
18#include <elf.h>18#include <elf.h>
19 19
20#include "tsc.h"
20#include "session.h"21#include "session.h"
21#include "jit.h"22#include "jit.h"
22#include "jitdump.h"23#include "jitdump.h"
@@ -33,6 +34,7 @@ struct jit_buf_desc { · 10 unmodified lines
33 size_t bufsize;34 size_t bufsize;
34 FILE *in;35 FILE *in;
35 bool needs_bswap; /* handles cross-endianess */36 bool needs_bswap; /* handles cross-endianess */
37 bool use_arch_timestamp;
36 void *debug_data;38 void *debug_data;
37 size_t nr_debug_entries;39 size_t nr_debug_entries;
38 uint32_t code_load_count;40 uint32_t code_load_count;
@@ -158,13 +160,16 @@ jit_open(struct jit_buf_desc *jd, const char *name) · 119 unmodified lines
158 header.flags = bswap_64(header.flags);160 header.flags = bswap_64(header.flags);
159 }161 }
160 162
163 jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP;
164
161 if (verbose > 2)165 if (verbose > 2)
162 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n",166 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n",
163 header.version,167 header.version,
164 header.total_size,168 header.total_size,
165 (unsigned long long)header.timestamp,169 (unsigned long long)header.timestamp,
166 header.pid,170 header.pid,
167 header.elf_mach);171 header.elf_mach,
172 jd->use_arch_timestamp);
168 173
169 if (header.flags & JITDUMP_FLAGS_RESERVED) {174 if (header.flags & JITDUMP_FLAGS_RESERVED) {
170 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",175 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
@@ -172,10 +177,15 @@ jit_open(struct jit_buf_desc *jd, const char *name) · 1 unmodified line
172 goto error;177 goto error;
173 }178 }
174 179
180 if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) {
181 pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n");
182 goto error;
183 }
184
175 /*185 /*
176 * validate event is using the correct clockid186 * validate event is using the correct clockid
177 */187 */
178 if (jit_validate_events(jd->session)) {188 if (!jd->use_arch_timestamp && jit_validate_events(jd->session)) {
179 pr_err("error, jitted code must be sampled with perf record -k 1\n");189 pr_err("error, jitted code must be sampled with perf record -k 1\n");
180 goto error;190 goto error;
181 }191 }
@@ -329,6 +339,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event) · 147 unmodified lines
329 return 0;339 return 0;
330}340}
331 341
342static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp)
343{
344 struct perf_tsc_conversion tc;
345
346 if (!jd->use_arch_timestamp)
347 return timestamp;
348
349 tc.time_shift = jd->session->time_conv.time_shift;
350 tc.time_mult = jd->session->time_conv.time_mult;
351 tc.time_zero = jd->session->time_conv.time_zero;
352
353 if (!tc.time_mult)
354 return 0;
355
356 return tsc_to_perf_time(timestamp, &tc);
357}
358
332static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)359static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
333{360{
334 struct perf_sample sample;361 struct perf_sample sample;
@@ -385,7 +412,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) · 50 unmodified lines
385 return -1;412 return -1;
386 }413 }
387 if (stat(filename, &st))414 if (stat(filename, &st))
388 memset(&st, 0, sizeof(stat));415 memset(&st, 0, sizeof(st));
389 416
390 event->mmap2.header.type = PERF_RECORD_MMAP2;417 event->mmap2.header.type = PERF_RECORD_MMAP2;
391 event->mmap2.header.misc = PERF_RECORD_MISC_USER;418 event->mmap2.header.misc = PERF_RECORD_MISC_USER;
@@ -410,7 +437,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) · 18 unmodified lines
410 id->tid = tid;437 id->tid = tid;
411 }438 }
412 if (jd->sample_type & PERF_SAMPLE_TIME)439 if (jd->sample_type & PERF_SAMPLE_TIME)
413 id->time = jr->load.p.timestamp;440 id->time = convert_timestamp(jd, jr->load.p.timestamp);
414 441
415 /*442 /*
416 * create pseudo sample to induce dso hit increment443 * create pseudo sample to induce dso hit increment
@@ -473,7 +500,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) · 56 unmodified lines
473 size++; /* for \0 */500 size++; /* for \0 */
474 501
475 if (stat(filename, &st))502 if (stat(filename, &st))
476 memset(&st, 0, sizeof(stat));503 memset(&st, 0, sizeof(st));
477 504
478 size = PERF_ALIGN(size, sizeof(u64));505 size = PERF_ALIGN(size, sizeof(u64));
479 506
@@ -499,7 +526,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr) · 19 unmodified lines
499 id->tid = tid;526 id->tid = tid;
500 }527 }
501 if (jd->sample_type & PERF_SAMPLE_TIME)528 if (jd->sample_type & PERF_SAMPLE_TIME)
502 id->time = jr->load.p.timestamp;529 id->time = convert_timestamp(jd, jr->load.p.timestamp);
503 530
504 /*531 /*
505 * create pseudo sample to induce dso hit increment532 * create pseudo sample to induce dso hit increment
tools/perf/util/jitdump.h+3−0
@@ -23,9 +23,12 @@ · 22 unmodified lines
23#define JITHEADER_VERSION 123#define JITHEADER_VERSION 1
24 24
25enum jitdump_flags_bits {25enum jitdump_flags_bits {
26 JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT,
26 JITDUMP_FLAGS_MAX_BIT,27 JITDUMP_FLAGS_MAX_BIT,
27};28};
28 29
30#define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << JITDUMP_FLAGS_ARCH_TIMESTAMP_BIT)
31
29#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \32#define JITDUMP_FLAGS_RESERVED (JITDUMP_FLAGS_MAX_BIT < 64 ? \
30 (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)33 (~((1ULL << JITDUMP_FLAGS_MAX_BIT) - 1)) : 0)
31 34
tools/perf/util/machine.c+73−32
@@ -32,6 +32,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid) · 31 unmodified lines
32 32
33 machine->threads = RB_ROOT;33 machine->threads = RB_ROOT;
34 pthread_rwlock_init(&machine->threads_lock, NULL);34 pthread_rwlock_init(&machine->threads_lock, NULL);
35 machine->nr_threads = 0;
35 INIT_LIST_HEAD(&machine->dead_threads);36 INIT_LIST_HEAD(&machine->dead_threads);
36 machine->last_match = NULL;37 machine->last_match = NULL;
37 38
@@ -430,6 +431,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine, · 392 unmodified lines
430 */431 */
431 thread__get(th);432 thread__get(th);
432 machine->last_match = th;433 machine->last_match = th;
434 ++machine->nr_threads;
433 }435 }
434 436
435 return th;437 return th;
@@ -681,11 +683,13 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp) · 245 unmodified lines
681 683
682size_t machine__fprintf(struct machine *machine, FILE *fp)684size_t machine__fprintf(struct machine *machine, FILE *fp)
683{685{
684 size_t ret = 0;686 size_t ret;
685 struct rb_node *nd;687 struct rb_node *nd;
686 688
687 pthread_rwlock_rdlock(&machine->threads_lock);689 pthread_rwlock_rdlock(&machine->threads_lock);
688 690
691 ret = fprintf(fp, "Threads: %u\n", machine->nr_threads);
692
689 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {693 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
690 struct thread *pos = rb_entry(nd, struct thread, rb_node);694 struct thread *pos = rb_entry(nd, struct thread, rb_node);
691 695
@@ -908,11 +912,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid) · 216 unmodified lines
908 return machine__create_kernel_maps(machine);912 return machine__create_kernel_maps(machine);
909}913}
910 914
911int machine__load_kallsyms(struct machine *machine, const char *filename,915int __machine__load_kallsyms(struct machine *machine, const char *filename,
912 enum map_type type, symbol_filter_t filter)916 enum map_type type, bool no_kcore, symbol_filter_t filter)
913{917{
914 struct map *map = machine__kernel_map(machine);918 struct map *map = machine__kernel_map(machine);
915 int ret = dso__load_kallsyms(map->dso, filename, map, filter);919 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter);
916 920
917 if (ret > 0) {921 if (ret > 0) {
918 dso__set_loaded(map->dso, type);922 dso__set_loaded(map->dso, type);
@@ -927,6 +931,12 @@ int machine__load_kallsyms(struct machine *machine, const char *filename, · 8 unmodified lines
927 return ret;931 return ret;
928}932}
929 933
934int machine__load_kallsyms(struct machine *machine, const char *filename,
935 enum map_type type, symbol_filter_t filter)
936{
937 return __machine__load_kallsyms(machine, filename, type, false, filter);
938}
939
930int machine__load_vmlinux_path(struct machine *machine, enum map_type type,940int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
931 symbol_filter_t filter)941 symbol_filter_t filter)
932{942{
@@ -1413,6 +1423,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th, · 480 unmodified lines
1413 pthread_rwlock_wrlock(&machine->threads_lock);1423 pthread_rwlock_wrlock(&machine->threads_lock);
1414 rb_erase_init(&th->rb_node, &machine->threads);1424 rb_erase_init(&th->rb_node, &machine->threads);
1415 RB_CLEAR_NODE(&th->rb_node);1425 RB_CLEAR_NODE(&th->rb_node);
1426 --machine->nr_threads;
1416 /*1427 /*
1417 * Move it first to the dead_threads list, then drop the reference,1428 * Move it first to the dead_threads list, then drop the reference,
1418 * if this is the last reference, then the thread__delete destructor1429 * if this is the last reference, then the thread__delete destructor
@@ -1599,6 +1610,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample, · 180 unmodified lines
1599}1610}
1600 1611
1601static int add_callchain_ip(struct thread *thread,1612static int add_callchain_ip(struct thread *thread,
1613 struct callchain_cursor *cursor,
1602 struct symbol **parent,1614 struct symbol **parent,
1603 struct addr_location *root_al,1615 struct addr_location *root_al,
1604 u8 *cpumode,1616 u8 *cpumode,
@@ -1630,7 +1642,7 @@ static int add_callchain_ip(struct thread *thread, · 25 unmodified lines
1630 * It seems the callchain is corrupted.1642 * It seems the callchain is corrupted.
1631 * Discard all.1643 * Discard all.
1632 */1644 */
1633 callchain_cursor_reset(&callchain_cursor);1645 callchain_cursor_reset(cursor);
1634 return 1;1646 return 1;
1635 }1647 }
1636 return 0;1648 return 0;
@@ -1640,7 +1652,7 @@ static int add_callchain_ip(struct thread *thread, · 3 unmodified lines
1640 }1652 }
1641 1653
1642 if (al.sym != NULL) {1654 if (al.sym != NULL) {
1643 if (sort__has_parent && !*parent &&1655 if (perf_hpp_list.parent && !*parent &&
1644 symbol__match_regex(al.sym, &parent_regex))1656 symbol__match_regex(al.sym, &parent_regex))
1645 *parent = al.sym;1657 *parent = al.sym;
1646 else if (have_ignore_callees && root_al &&1658 else if (have_ignore_callees && root_al &&
@@ -1648,13 +1660,13 @@ static int add_callchain_ip(struct thread *thread, · 1 unmodified line
1648 /* Treat this symbol as the root,1660 /* Treat this symbol as the root,
1649 forgetting its callees. */1661 forgetting its callees. */
1650 *root_al = al;1662 *root_al = al;
1651 callchain_cursor_reset(&callchain_cursor);1663 callchain_cursor_reset(cursor);
1652 }1664 }
1653 }1665 }
1654 1666
1655 if (symbol_conf.hide_unresolved && al.sym == NULL)1667 if (symbol_conf.hide_unresolved && al.sym == NULL)
1656 return 0;1668 return 0;
1657 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym);1669 return callchain_cursor_append(cursor, al.addr, al.map, al.sym);
1658}1670}
1659 1671
1660struct branch_info *sample__resolve_bstack(struct perf_sample *sample,1672struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1724,6 +1736,7 @@ static int remove_loops(struct branch_entry *l, int nr) · 63 unmodified lines
1724 * negative error code on other errors.1736 * negative error code on other errors.
1725 */1737 */
1726static int resolve_lbr_callchain_sample(struct thread *thread,1738static int resolve_lbr_callchain_sample(struct thread *thread,
1739 struct callchain_cursor *cursor,
1727 struct perf_sample *sample,1740 struct perf_sample *sample,
1728 struct symbol **parent,1741 struct symbol **parent,
1729 struct addr_location *root_al,1742 struct addr_location *root_al,
@@ -1756,7 +1769,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, · 26 unmodified lines
1756 */1769 */
1757 int mix_chain_nr = i + 1 + lbr_nr + 1;1770 int mix_chain_nr = i + 1 + lbr_nr + 1;
1758 1771
1759 if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) {1772 if (mix_chain_nr > (int)sysctl_perf_event_max_stack + PERF_MAX_BRANCH_DEPTH) {
1760 pr_warning("corrupted callchain. skipping...\n");1773 pr_warning("corrupted callchain. skipping...\n");
1761 return 0;1774 return 0;
1762 }1775 }
@@ -1778,7 +1791,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, · 15 unmodified lines
1778 ip = lbr_stack->entries[0].to;1791 ip = lbr_stack->entries[0].to;
1779 }1792 }
1780 1793
1781 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);1794 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1782 if (err)1795 if (err)
1783 return (err < 0) ? err : 0;1796 return (err < 0) ? err : 0;
1784 }1797 }
@@ -1789,6 +1802,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread, · 4 unmodified lines
1789}1802}
1790 1803
1791static int thread__resolve_callchain_sample(struct thread *thread,1804static int thread__resolve_callchain_sample(struct thread *thread,
1805 struct callchain_cursor *cursor,
1792 struct perf_evsel *evsel,1806 struct perf_evsel *evsel,
1793 struct perf_sample *sample,1807 struct perf_sample *sample,
1794 struct symbol **parent,1808 struct symbol **parent,
@@ -1803,10 +1817,8 @@ static int thread__resolve_callchain_sample(struct thread *thread, · 8 unmodified lines
1803 int skip_idx = -1;1817 int skip_idx = -1;
1804 int first_call = 0;1818 int first_call = 0;
1805 1819
1806 callchain_cursor_reset(&callchain_cursor);1820 if (perf_evsel__has_branch_callstack(evsel)) {
1807 1821 err = resolve_lbr_callchain_sample(thread, cursor, sample, parent,
1808 if (has_branch_callstack(evsel)) {
1809 err = resolve_lbr_callchain_sample(thread, sample, parent,
1810 root_al, max_stack);1822 root_al, max_stack);
1811 if (err)1823 if (err)
1812 return (err < 0) ? err : 0;1824 return (err < 0) ? err : 0;
@@ -1816,7 +1828,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, · 3 unmodified lines
1816 * Based on DWARF debug information, some architectures skip1828 * Based on DWARF debug information, some architectures skip
1817 * a callchain entry saved by the kernel.1829 * a callchain entry saved by the kernel.
1818 */1830 */
1819 if (chain->nr < PERF_MAX_STACK_DEPTH)1831 if (chain->nr < sysctl_perf_event_max_stack)
1820 skip_idx = arch_skip_callchain_idx(thread, chain);1832 skip_idx = arch_skip_callchain_idx(thread, chain);
1821 1833
1822 /*1834 /*
@@ -1863,10 +1875,10 @@ static int thread__resolve_callchain_sample(struct thread *thread, · 40 unmodified lines
1863 nr = remove_loops(be, nr);1875 nr = remove_loops(be, nr);
1864 1876
1865 for (i = 0; i < nr; i++) {1877 for (i = 0; i < nr; i++) {
1866 err = add_callchain_ip(thread, parent, root_al,1878 err = add_callchain_ip(thread, cursor, parent, root_al,
1867 NULL, be[i].to);1879 NULL, be[i].to);
1868 if (!err)1880 if (!err)
1869 err = add_callchain_ip(thread, parent, root_al,1881 err = add_callchain_ip(thread, cursor, parent, root_al,
1870 NULL, be[i].from);1882 NULL, be[i].from);
1871 if (err == -EINVAL)1883 if (err == -EINVAL)
1872 break;1884 break;
@@ -1877,7 +1889,7 @@ static int thread__resolve_callchain_sample(struct thread *thread, · 4 unmodified lines
1877 }1889 }
1878 1890
1879check_calls:1891check_calls:
1880 if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) {1892 if (chain->nr > sysctl_perf_event_max_stack && (int)chain->nr > max_stack) {
1881 pr_warning("corrupted callchain. skipping...\n");1893 pr_warning("corrupted callchain. skipping...\n");
1882 return 0;1894 return 0;
1883 }1895 }
@@ -1896,7 +1908,7 @@ check_calls: · 12 unmodified lines
1896#endif1908#endif
1897 ip = chain->ips[j];1909 ip = chain->ips[j];
1898 1910
1899 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip);1911 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1900 1912
1901 if (err)1913 if (err)
1902 return (err < 0) ? err : 0;1914 return (err < 0) ? err : 0;
@@ -1915,19 +1927,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg) · 12 unmodified lines
1915 entry->map, entry->sym);1927 entry->map, entry->sym);
1916}1928}
1917 1929
1918int thread__resolve_callchain(struct thread *thread,1930static int thread__resolve_callchain_unwind(struct thread *thread,
1919 struct perf_evsel *evsel,1931 struct callchain_cursor *cursor,
1920 struct perf_sample *sample,1932 struct perf_evsel *evsel,
1921 struct symbol **parent,1933 struct perf_sample *sample,
1922 struct addr_location *root_al,1934 int max_stack)
1923 int max_stack)
1924{1935{
1925 int ret = thread__resolve_callchain_sample(thread, evsel,
1926 sample, parent,
1927 root_al, max_stack);
1928 if (ret)
1929 return ret;
1930
1931 /* Can we do dwarf post unwind? */1936 /* Can we do dwarf post unwind? */
1932 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&1937 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
1933 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))1938 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
@@ -1938,9 +1943,45 @@ int thread__resolve_callchain(struct thread *thread, · 4 unmodified lines
1938 (!sample->user_stack.size))1943 (!sample->user_stack.size))
1939 return 0;1944 return 0;
1940 1945
1941 return unwind__get_entries(unwind_entry, &callchain_cursor,1946 return unwind__get_entries(unwind_entry, cursor,
1942 thread, sample, max_stack);1947 thread, sample, max_stack);
1948}
1949
1950int thread__resolve_callchain(struct thread *thread,
1951 struct callchain_cursor *cursor,
1952 struct perf_evsel *evsel,
1953 struct perf_sample *sample,
1954 struct symbol **parent,
1955 struct addr_location *root_al,
1956 int max_stack)
1957{
1958 int ret = 0;
1959
1960 callchain_cursor_reset(&callchain_cursor);
1943 1961
1962 if (callchain_param.order == ORDER_CALLEE) {
1963 ret = thread__resolve_callchain_sample(thread, cursor,
1964 evsel, sample,
1965 parent, root_al,
1966 max_stack);
1967 if (ret)
1968 return ret;
1969 ret = thread__resolve_callchain_unwind(thread, cursor,
1970 evsel, sample,
1971 max_stack);
1972 } else {
1973 ret = thread__resolve_callchain_unwind(thread, cursor,
1974 evsel, sample,
1975 max_stack);
1976 if (ret)
1977 return ret;
1978 ret = thread__resolve_callchain_sample(thread, cursor,
1979 evsel, sample,
1980 parent, root_al,
1981 max_stack);
1982 }
1983
1984 return ret;
1944}1985}
1945 1986
1946int machine__for_each_thread(struct machine *machine,1987int machine__for_each_thread(struct machine *machine,
tools/perf/util/machine.h+7−0
@@ -31,6 +31,7 @@ struct machine { · 30 unmodified lines
31 char *root_dir;31 char *root_dir;
32 struct rb_root threads;32 struct rb_root threads;
33 pthread_rwlock_t threads_lock;33 pthread_rwlock_t threads_lock;
34 unsigned int nr_threads;
34 struct list_head dead_threads;35 struct list_head dead_threads;
35 struct thread *last_match;36 struct thread *last_match;
36 struct vdso_info *vdso_info;37 struct vdso_info *vdso_info;
@@ -141,7 +142,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample, · 104 unmodified lines
141 struct addr_location *al);142 struct addr_location *al);
142struct mem_info *sample__resolve_mem(struct perf_sample *sample,143struct mem_info *sample__resolve_mem(struct perf_sample *sample,
143 struct addr_location *al);144 struct addr_location *al);
145
146struct callchain_cursor;
147
144int thread__resolve_callchain(struct thread *thread,148int thread__resolve_callchain(struct thread *thread,
149 struct callchain_cursor *cursor,
145 struct perf_evsel *evsel,150 struct perf_evsel *evsel,
146 struct perf_sample *sample,151 struct perf_sample *sample,
147 struct symbol **parent,152 struct symbol **parent,
@@ -211,6 +216,8 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine, · 63 unmodified lines
211struct map *machine__findnew_module_map(struct machine *machine, u64 start,216struct map *machine__findnew_module_map(struct machine *machine, u64 start,
212 const char *filename);217 const char *filename);
213 218
219int __machine__load_kallsyms(struct machine *machine, const char *filename,
220 enum map_type type, bool no_kcore, symbol_filter_t filter);
214int machine__load_kallsyms(struct machine *machine, const char *filename,221int machine__load_kallsyms(struct machine *machine, const char *filename,
215 enum map_type type, symbol_filter_t filter);222 enum map_type type, symbol_filter_t filter);
216int machine__load_vmlinux_path(struct machine *machine, enum map_type type,223int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
tools/perf/util/map.c+15−1
@@ -289,7 +289,7 @@ int map__load(struct map *map, symbol_filter_t filter) · 288 unmodified lines
289 nr = dso__load(map->dso, map, filter);289 nr = dso__load(map->dso, map, filter);
290 if (nr < 0) {290 if (nr < 0) {
291 if (map->dso->has_build_id) {291 if (map->dso->has_build_id) {
292 char sbuild_id[BUILD_ID_SIZE * 2 + 1];292 char sbuild_id[SBUILD_ID_SIZE];
293 293
294 build_id__sprintf(map->dso->build_id,294 build_id__sprintf(map->dso->build_id,
295 sizeof(map->dso->build_id),295 sizeof(map->dso->build_id),
@@ -431,6 +431,13 @@ u64 map__rip_2objdump(struct map *map, u64 rip) · 135 unmodified lines
431 if (map->dso->rel)431 if (map->dso->rel)
432 return rip - map->pgoff;432 return rip - map->pgoff;
433 433
434 /*
435 * kernel modules also have DSO_TYPE_USER in dso->kernel,
436 * but all kernel modules are ET_REL, so won't get here.
437 */
438 if (map->dso->kernel == DSO_TYPE_USER)
439 return rip + map->dso->text_offset;
440
434 return map->unmap_ip(map, rip) - map->reloc;441 return map->unmap_ip(map, rip) - map->reloc;
435}442}
436 443
@@ -454,6 +461,13 @@ u64 map__objdump_2mem(struct map *map, u64 ip) · 17 unmodified lines
454 if (map->dso->rel)461 if (map->dso->rel)
455 return map->unmap_ip(map, ip + map->pgoff);462 return map->unmap_ip(map, ip + map->pgoff);
456 463
464 /*
465 * kernel modules also have DSO_TYPE_USER in dso->kernel,
466 * but all kernel modules are ET_REL, so won't get here.
467 */
468 if (map->dso->kernel == DSO_TYPE_USER)
469 return map->unmap_ip(map, ip - map->dso->text_offset);
470
457 return ip + map->reloc;471 return ip + map->reloc;
458}472}
459 473
tools/perf/util/ordered-events.c+9−0
@@ -308,3 +308,12 @@ void ordered_events__free(struct ordered_events *oe) · 307 unmodified lines
308 free(event);308 free(event);
309 }309 }
310}310}
311
312void ordered_events__reinit(struct ordered_events *oe)
313{
314 ordered_events__deliver_t old_deliver = oe->deliver;
315
316 ordered_events__free(oe);
317 memset(oe, '\0', sizeof(*oe));
318 ordered_events__init(oe, old_deliver);
319}
tools/perf/util/ordered-events.h+1−0
@@ -49,6 +49,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve · 48 unmodified lines
49int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);49int ordered_events__flush(struct ordered_events *oe, enum oe_flush how);
50void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);50void ordered_events__init(struct ordered_events *oe, ordered_events__deliver_t deliver);
51void ordered_events__free(struct ordered_events *oe);51void ordered_events__free(struct ordered_events *oe);
52void ordered_events__reinit(struct ordered_events *oe);
52 53
53static inline54static inline
54void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)55void ordered_events__set_alloc_size(struct ordered_events *oe, u64 size)
tools/perf/util/pmu.c+11−12
@@ -602,14 +602,13 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v, · 601 unmodified lines
602 602
603static __u64 pmu_format_max_value(const unsigned long *format)603static __u64 pmu_format_max_value(const unsigned long *format)
604{604{
605 int w;605 __u64 w = 0;
606 int fbit;
606 607
607 w = bitmap_weight(format, PERF_PMU_FORMAT_BITS);608 for_each_set_bit(fbit, format, PERF_PMU_FORMAT_BITS)
608 if (!w)609 w |= (1ULL << fbit);
609 return 0;610
610 if (w < 64)611 return w;
611 return (1ULL << w) - 1;
612 return -1;
613}612}
614 613
615/*614/*
@@ -644,20 +643,20 @@ static int pmu_resolve_param_term(struct parse_events_term *term, · 28 unmodified lines
644static char *pmu_formats_string(struct list_head *formats)643static char *pmu_formats_string(struct list_head *formats)
645{644{
646 struct perf_pmu_format *format;645 struct perf_pmu_format *format;
647 char *str;646 char *str = NULL;
648 struct strbuf buf;647 struct strbuf buf = STRBUF_INIT;
649 unsigned i = 0;648 unsigned i = 0;
650 649
651 if (!formats)650 if (!formats)
652 return NULL;651 return NULL;
653 652
654 strbuf_init(&buf, 0);
655 /* sysfs exported terms */653 /* sysfs exported terms */
656 list_for_each_entry(format, formats, list)654 list_for_each_entry(format, formats, list)
657 strbuf_addf(&buf, i++ ? ",%s" : "%s",655 if (strbuf_addf(&buf, i++ ? ",%s" : "%s", format->name) < 0)
658 format->name);656 goto error;
659 657
660 str = strbuf_detach(&buf, NULL);658 str = strbuf_detach(&buf, NULL);
659error:
661 strbuf_release(&buf);660 strbuf_release(&buf);
662 661
663 return str;662 return str;
tools/perf/util/probe-event.c+215−191
@@ -265,6 +265,65 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address) · 264 unmodified lines
265 return true;265 return true;
266}266}
267 267
268/*
269 * NOTE:
270 * '.gnu.linkonce.this_module' section of kernel module elf directly
271 * maps to 'struct module' from linux/module.h. This section contains
272 * actual module name which will be used by kernel after loading it.
273 * But, we cannot use 'struct module' here since linux/module.h is not
274 * exposed to user-space. Offset of 'name' has remained same from long
275 * time, so hardcoding it here.
276 */
277#ifdef __LP64__
278#define MOD_NAME_OFFSET 24
279#else
280#define MOD_NAME_OFFSET 12
281#endif
282
283/*
284 * @module can be module name of module file path. In case of path,
285 * inspect elf and find out what is actual module name.
286 * Caller has to free mod_name after using it.
287 */
288static char *find_module_name(const char *module)
289{
290 int fd;
291 Elf *elf;
292 GElf_Ehdr ehdr;
293 GElf_Shdr shdr;
294 Elf_Data *data;
295 Elf_Scn *sec;
296 char *mod_name = NULL;
297
298 fd = open(module, O_RDONLY);
299 if (fd < 0)
300 return NULL;
301
302 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
303 if (elf == NULL)
304 goto elf_err;
305
306 if (gelf_getehdr(elf, &ehdr) == NULL)
307 goto ret_err;
308
309 sec = elf_section_by_name(elf, &ehdr, &shdr,
310 ".gnu.linkonce.this_module", NULL);
311 if (!sec)
312 goto ret_err;
313
314 data = elf_getdata(sec, NULL);
315 if (!data || !data->d_buf)
316 goto ret_err;
317
318 mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET);
319
320ret_err:
321 elf_end(elf);
322elf_err:
323 close(fd);
324 return mod_name;
325}
326
268#ifdef HAVE_DWARF_SUPPORT327#ifdef HAVE_DWARF_SUPPORT
269 328
270static int kernel_get_module_dso(const char *module, struct dso **pdso)329static int kernel_get_module_dso(const char *module, struct dso **pdso)
@@ -486,8 +545,10 @@ static int get_text_start_address(const char *exec, unsigned long *address) · 215 unmodified lines
486 return -errno;545 return -errno;
487 546
488 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);547 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
489 if (elf == NULL)548 if (elf == NULL) {
490 return -EINVAL;549 ret = -EINVAL;
550 goto out_close;
551 }
491 552
492 if (gelf_getehdr(elf, &ehdr) == NULL)553 if (gelf_getehdr(elf, &ehdr) == NULL)
493 goto out;554 goto out;
@@ -499,6 +560,9 @@ static int get_text_start_address(const char *exec, unsigned long *address) · 5 unmodified lines
499 ret = 0;560 ret = 0;
500out:561out:
501 elf_end(elf);562 elf_end(elf);
563out_close:
564 close(fd);
565
502 return ret;566 return ret;
503}567}
504 568
@@ -583,32 +647,23 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs, · 78 unmodified lines
583 int ntevs, const char *module)647 int ntevs, const char *module)
584{648{
585 int i, ret = 0;649 int i, ret = 0;
586 char *tmp;650 char *mod_name = NULL;
587 651
588 if (!module)652 if (!module)
589 return 0;653 return 0;
590 654
591 tmp = strrchr(module, '/');655 mod_name = find_module_name(module);
592 if (tmp) {
593 /* This is a module path -- get the module name */
594 module = strdup(tmp + 1);
595 if (!module)
596 return -ENOMEM;
597 tmp = strchr(module, '.');
598 if (tmp)
599 *tmp = '\0';
600 tmp = (char *)module; /* For free() */
601 }
602 656
603 for (i = 0; i < ntevs; i++) {657 for (i = 0; i < ntevs; i++) {
604 tevs[i].point.module = strdup(module);658 tevs[i].point.module =
659 strdup(mod_name ? mod_name : module);
605 if (!tevs[i].point.module) {660 if (!tevs[i].point.module) {
606 ret = -ENOMEM;661 ret = -ENOMEM;
607 break;662 break;
608 }663 }
609 }664 }
610 665
611 free(tmp);666 free(mod_name);
612 return ret;667 return ret;
613}668}
614 669
@@ -1618,69 +1673,65 @@ out: · 1003 unmodified lines
1618}1673}
1619 1674
1620/* Compose only probe arg */1675/* Compose only probe arg */
1621int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len)1676char *synthesize_perf_probe_arg(struct perf_probe_arg *pa)
1622{1677{
1623 struct perf_probe_arg_field *field = pa->field;1678 struct perf_probe_arg_field *field = pa->field;
1624 int ret;1679 struct strbuf buf;
1625 char *tmp = buf;1680 char *ret = NULL;
1681 int err;
1682
1683 if (strbuf_init(&buf, 64) < 0)
1684 return NULL;
1626 1685
1627 if (pa->name && pa->var)1686 if (pa->name && pa->var)
1628 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var);1687 err = strbuf_addf(&buf, "%s=%s", pa->name, pa->var);
1629 else1688 else
1630 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var);1689 err = strbuf_addstr(&buf, pa->name ?: pa->var);
1631 if (ret <= 0)1690 if (err)
1632 goto error;1691 goto out;
1633 tmp += ret;
1634 len -= ret;
1635 1692
1636 while (field) {1693 while (field) {
1637 if (field->name[0] == '[')1694 if (field->name[0] == '[')
1638 ret = e_snprintf(tmp, len, "%s", field->name);1695 err = strbuf_addstr(&buf, field->name);
1639 else1696 else
1640 ret = e_snprintf(tmp, len, "%s%s",1697 err = strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".",
1641 field->ref ? "->" : ".", field->name);1698 field->name);
1642 if (ret <= 0)
1643 goto error;
1644 tmp += ret;
1645 len -= ret;
1646 field = field->next;1699 field = field->next;
1700 if (err)
1701 goto out;
1647 }1702 }
1648 1703
1649 if (pa->type) {1704 if (pa->type)
1650 ret = e_snprintf(tmp, len, ":%s", pa->type);1705 if (strbuf_addf(&buf, ":%s", pa->type) < 0)
1651 if (ret <= 0)1706 goto out;
1652 goto error;
1653 tmp += ret;
1654 len -= ret;
1655 }
1656 1707
1657 return tmp - buf;1708 ret = strbuf_detach(&buf, NULL);
1658error:1709out:
1659 pr_debug("Failed to synthesize perf probe argument: %d\n", ret);1710 strbuf_release(&buf);
1660 return ret;1711 return ret;
1661}1712}
1662 1713
1663/* Compose only probe point (not argument) */1714/* Compose only probe point (not argument) */
1664static char *synthesize_perf_probe_point(struct perf_probe_point *pp)1715static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1665{1716{
1666 char *buf, *tmp;1717 struct strbuf buf;
1667 char offs[32] = "", line[32] = "", file[32] = "";1718 char *tmp, *ret = NULL;
1668 int ret, len;1719 int len, err = 0;
1669 1720
1670 buf = zalloc(MAX_CMDLEN);1721 if (strbuf_init(&buf, 64) < 0)
1671 if (buf == NULL) {1722 return NULL;
1672 ret = -ENOMEM;1723
1673 goto error;1724 if (pp->function) {
1674 }1725 if (strbuf_addstr(&buf, pp->function) < 0)
1675 if (pp->offset) {1726 goto out;
1676 ret = e_snprintf(offs, 32, "+%lu", pp->offset);1727 if (pp->offset)
1677 if (ret <= 0)1728 err = strbuf_addf(&buf, "+%lu", pp->offset);
1678 goto error;1729 else if (pp->line)
1679 }1730 err = strbuf_addf(&buf, ":%d", pp->line);
1680 if (pp->line) {1731 else if (pp->retprobe)
1681 ret = e_snprintf(line, 32, ":%d", pp->line);1732 err = strbuf_addstr(&buf, "%return");
1682 if (ret <= 0)1733 if (err)
1683 goto error;1734 goto out;
1684 }1735 }
1685 if (pp->file) {1736 if (pp->file) {
1686 tmp = pp->file;1737 tmp = pp->file;
@@ -1689,25 +1740,15 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp) · 2 unmodified lines
1689 tmp = strchr(pp->file + len - 30, '/');1740 tmp = strchr(pp->file + len - 30, '/');
1690 tmp = tmp ? tmp + 1 : pp->file + len - 30;1741 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1691 }1742 }
1692 ret = e_snprintf(file, 32, "@%s", tmp);1743 err = strbuf_addf(&buf, "@%s", tmp);
1693 if (ret <= 0)1744 if (!err && !pp->function && pp->line)
1694 goto error;1745 err = strbuf_addf(&buf, ":%d", pp->line);
1695 }1746 }
1696 1747 if (!err)
1697 if (pp->function)1748 ret = strbuf_detach(&buf, NULL);
1698 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function,1749out:
1699 offs, pp->retprobe ? "%return" : "", line,1750 strbuf_release(&buf);
1700 file);1751 return ret;
1701 else
1702 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", file, line);
1703 if (ret <= 0)
1704 goto error;
1705
1706 return buf;
1707error:
1708 pr_debug("Failed to synthesize perf probe point: %d\n", ret);
1709 free(buf);
1710 return NULL;
1711}1752}
1712 1753
1713#if 01754#if 0
@@ -1736,45 +1777,32 @@ char *synthesize_perf_probe_command(struct perf_probe_event *pev) · 22 unmodified lines
1736#endif1777#endif
1737 1778
1738static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,1779static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1739 char **buf, size_t *buflen,1780 struct strbuf *buf, int depth)
1740 int depth)
1741{1781{
1742 int ret;1782 int err;
1743 if (ref->next) {1783 if (ref->next) {
1744 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,1784 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
1745 buflen, depth + 1);1785 depth + 1);
1746 if (depth < 0)1786 if (depth < 0)
1747 goto out;1787 return depth;
1748 }
1749
1750 ret = e_snprintf(*buf, *buflen, "%+ld(", ref->offset);
1751 if (ret < 0)
1752 depth = ret;
1753 else {
1754 *buf += ret;
1755 *buflen -= ret;
1756 }1788 }
1757out:1789 err = strbuf_addf(buf, "%+ld(", ref->offset);
1758 return depth;1790 return (err < 0) ? err : depth;
1759
1760}1791}
1761 1792
1762static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,1793static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1763 char *buf, size_t buflen)1794 struct strbuf *buf)
1764{1795{
1765 struct probe_trace_arg_ref *ref = arg->ref;1796 struct probe_trace_arg_ref *ref = arg->ref;
1766 int ret, depth = 0;1797 int depth = 0, err;
1767 char *tmp = buf;
1768 1798
1769 /* Argument name or separator */1799 /* Argument name or separator */
1770 if (arg->name)1800 if (arg->name)
1771 ret = e_snprintf(buf, buflen, " %s=", arg->name);1801 err = strbuf_addf(buf, " %s=", arg->name);
1772 else1802 else
1773 ret = e_snprintf(buf, buflen, " ");1803 err = strbuf_addch(buf, ' ');
1774 if (ret < 0)1804 if (err)
1775 return ret;1805 return err;
1776 buf += ret;
1777 buflen -= ret;
1778 1806
1779 /* Special case: @XXX */1807 /* Special case: @XXX */
1780 if (arg->value[0] == '@' && arg->ref)1808 if (arg->value[0] == '@' && arg->ref)
@@ -1782,59 +1810,44 @@ static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, · 1 unmodified line
1782 1810
1783 /* Dereferencing arguments */1811 /* Dereferencing arguments */
1784 if (ref) {1812 if (ref) {
1785 depth = __synthesize_probe_trace_arg_ref(ref, &buf,1813 depth = __synthesize_probe_trace_arg_ref(ref, buf, 1);
1786 &buflen, 1);
1787 if (depth < 0)1814 if (depth < 0)
1788 return depth;1815 return depth;
1789 }1816 }
1790 1817
1791 /* Print argument value */1818 /* Print argument value */
1792 if (arg->value[0] == '@' && arg->ref)1819 if (arg->value[0] == '@' && arg->ref)
1793 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value,1820 err = strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset);
1794 arg->ref->offset);
1795 else1821 else
1796 ret = e_snprintf(buf, buflen, "%s", arg->value);1822 err = strbuf_addstr(buf, arg->value);
1797 if (ret < 0)
1798 return ret;
1799 buf += ret;
1800 buflen -= ret;
1801 1823
1802 /* Closing */1824 /* Closing */
1803 while (depth--) {1825 while (!err && depth--)
1804 ret = e_snprintf(buf, buflen, ")");1826 err = strbuf_addch(buf, ')');
1805 if (ret < 0)1827
1806 return ret;
1807 buf += ret;
1808 buflen -= ret;
1809 }
1810 /* Print argument type */1828 /* Print argument type */
1811 if (arg->type) {1829 if (!err && arg->type)
1812 ret = e_snprintf(buf, buflen, ":%s", arg->type);1830 err = strbuf_addf(buf, ":%s", arg->type);
1813 if (ret <= 0)
1814 return ret;
1815 buf += ret;
1816 }
1817 1831
1818 return buf - tmp;1832 return err;
1819}1833}
1820 1834
1821char *synthesize_probe_trace_command(struct probe_trace_event *tev)1835char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1822{1836{
1823 struct probe_trace_point *tp = &tev->point;1837 struct probe_trace_point *tp = &tev->point;
1824 char *buf;1838 struct strbuf buf;
1825 int i, len, ret;1839 char *ret = NULL;
1840 int i, err;
1826 1841
1827 buf = zalloc(MAX_CMDLEN);1842 /* Uprobes must have tp->module */
1828 if (buf == NULL)1843 if (tev->uprobes && !tp->module)
1829 return NULL;1844 return NULL;
1830 1845
1831 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',1846 if (strbuf_init(&buf, 32) < 0)
1832 tev->group, tev->event);1847 return NULL;
1833 if (len <= 0)
1834 goto error;
1835 1848
1836 /* Uprobes must have tp->module */1849 if (strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
1837 if (tev->uprobes && !tp->module)1850 tev->group, tev->event) < 0)
1838 goto error;1851 goto error;
1839 /*1852 /*
1840 * If tp->address == 0, then this point must be a1853 * If tp->address == 0, then this point must be a
@@ -1849,34 +1862,25 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev) · 8 unmodified lines
1849 1862
1850 /* Use the tp->address for uprobes */1863 /* Use the tp->address for uprobes */
1851 if (tev->uprobes)1864 if (tev->uprobes)
1852 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx",1865 err = strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
1853 tp->module, tp->address);
1854 else if (!strncmp(tp->symbol, "0x", 2))1866 else if (!strncmp(tp->symbol, "0x", 2))
1855 /* Absolute address. See try_to_find_absolute_address() */1867 /* Absolute address. See try_to_find_absolute_address() */
1856 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx",1868 err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "",
1857 tp->module ?: "", tp->module ? ":" : "",1869 tp->module ? ":" : "", tp->address);
1858 tp->address);
1859 else1870 else
1860 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu",1871 err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
1861 tp->module ?: "", tp->module ? ":" : "",1872 tp->module ? ":" : "", tp->symbol, tp->offset);
1862 tp->symbol, tp->offset);1873 if (err)
1863
1864 if (ret <= 0)
1865 goto error;1874 goto error;
1866 len += ret;
1867 1875
1868 for (i = 0; i < tev->nargs; i++) {1876 for (i = 0; i < tev->nargs; i++)
1869 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len,1877 if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
1870 MAX_CMDLEN - len);
1871 if (ret <= 0)
1872 goto error;1878 goto error;
1873 len += ret;
1874 }
1875 1879
1876 return buf;1880 ret = strbuf_detach(&buf, NULL);
1877error:1881error:
1878 free(buf);1882 strbuf_release(&buf);
1879 return NULL;1883 return ret;
1880}1884}
1881 1885
1882static int find_perf_probe_point_from_map(struct probe_trace_point *tp,1886static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
@@ -1958,7 +1962,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp, · 75 unmodified lines
1958static int convert_to_perf_probe_event(struct probe_trace_event *tev,1962static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1959 struct perf_probe_event *pev, bool is_kprobe)1963 struct perf_probe_event *pev, bool is_kprobe)
1960{1964{
1961 char buf[64] = "";1965 struct strbuf buf = STRBUF_INIT;
1962 int i, ret;1966 int i, ret;
1963 1967
1964 /* Convert event/group name */1968 /* Convert event/group name */
@@ -1981,14 +1985,15 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev, · 16 unmodified lines
1981 if (tev->args[i].name)1985 if (tev->args[i].name)
1982 pev->args[i].name = strdup(tev->args[i].name);1986 pev->args[i].name = strdup(tev->args[i].name);
1983 else {1987 else {
1984 ret = synthesize_probe_trace_arg(&tev->args[i],1988 if ((ret = strbuf_init(&buf, 32)) < 0)
1985 buf, 64);1989 goto error;
1986 pev->args[i].name = strdup(buf);1990 ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
1991 pev->args[i].name = strbuf_detach(&buf, NULL);
1987 }1992 }
1988 if (pev->args[i].name == NULL && ret >= 0)1993 if (pev->args[i].name == NULL && ret >= 0)
1989 ret = -ENOMEM;1994 ret = -ENOMEM;
1990 }1995 }
1991 1996error:
1992 if (ret < 0)1997 if (ret < 0)
1993 clear_perf_probe_event(pev);1998 clear_perf_probe_event(pev);
1994 1999
@@ -2162,35 +2167,38 @@ static int perf_probe_event__sprintf(const char *group, const char *event, · 167 unmodified lines
2162 struct strbuf *result)2167 struct strbuf *result)
2163{2168{
2164 int i, ret;2169 int i, ret;
2165 char buf[128];2170 char *buf;
2166 char *place;
2167 2171
2168 /* Synthesize only event probe point */2172 if (asprintf(&buf, "%s:%s", group, event) < 0)
2169 place = synthesize_perf_probe_point(&pev->point);2173 return -errno;
2170 if (!place)2174 ret = strbuf_addf(result, " %-20s (on ", buf);
2171 return -EINVAL;2175 free(buf);
2176 if (ret)
2177 return ret;
2172 2178
2173 ret = e_snprintf(buf, 128, "%s:%s", group, event);2179 /* Synthesize only event probe point */
2174 if (ret < 0)2180 buf = synthesize_perf_probe_point(&pev->point);
2175 goto out;2181 if (!buf)
2182 return -ENOMEM;
2183 ret = strbuf_addstr(result, buf);
2184 free(buf);
2176 2185
2177 strbuf_addf(result, " %-20s (on %s", buf, place);2186 if (!ret && module)
2178 if (module)2187 ret = strbuf_addf(result, " in %s", module);
2179 strbuf_addf(result, " in %s", module);
2180 2188
2181 if (pev->nargs > 0) {2189 if (!ret && pev->nargs > 0) {
2182 strbuf_add(result, " with", 5);2190 ret = strbuf_add(result, " with", 5);
2183 for (i = 0; i < pev->nargs; i++) {2191 for (i = 0; !ret && i < pev->nargs; i++) {
2184 ret = synthesize_perf_probe_arg(&pev->args[i],2192 buf = synthesize_perf_probe_arg(&pev->args[i]);
2185 buf, 128);2193 if (!buf)
2186 if (ret < 0)2194 return -ENOMEM;
2187 goto out;2195 ret = strbuf_addf(result, " %s", buf);
2188 strbuf_addf(result, " %s", buf);2196 free(buf);
2189 }2197 }
2190 }2198 }
2191 strbuf_addch(result, ')');2199 if (!ret)
2192out:2200 ret = strbuf_addch(result, ')');
2193 free(place);2201
2194 return ret;2202 return ret;
2195}2203}
2196 2204
@@ -2498,7 +2506,8 @@ static int find_probe_functions(struct map *map, char *name, · 301 unmodified lines
2498 2506
2499void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,2507void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
2500 struct probe_trace_event *tev __maybe_unused,2508 struct probe_trace_event *tev __maybe_unused,
2501 struct map *map __maybe_unused) { }2509 struct map *map __maybe_unused,
2510 struct symbol *sym __maybe_unused) { }
2502 2511
2503/*2512/*
2504 * Find probe function addresses from map.2513 * Find probe function addresses from map.
@@ -2516,6 +2525,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, · 11 unmodified lines
2516 struct probe_trace_point *tp;2525 struct probe_trace_point *tp;
2517 int num_matched_functions;2526 int num_matched_functions;
2518 int ret, i, j, skipped = 0;2527 int ret, i, j, skipped = 0;
2528 char *mod_name;
2519 2529
2520 map = get_target_map(pev->target, pev->uprobes);2530 map = get_target_map(pev->target, pev->uprobes);
2521 if (!map) {2531 if (!map) {
@@ -2600,9 +2610,19 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, · 78 unmodified lines
2600 tp->realname = strdup_or_goto(sym->name, nomem_out);2610 tp->realname = strdup_or_goto(sym->name, nomem_out);
2601 2611
2602 tp->retprobe = pp->retprobe;2612 tp->retprobe = pp->retprobe;
2603 if (pev->target)2613 if (pev->target) {
2604 tev->point.module = strdup_or_goto(pev->target,2614 if (pev->uprobes) {
2605 nomem_out);2615 tev->point.module = strdup_or_goto(pev->target,
2616 nomem_out);
2617 } else {
2618 mod_name = find_module_name(pev->target);
2619 tev->point.module =
2620 strdup(mod_name ? mod_name : pev->target);
2621 free(mod_name);
2622 if (!tev->point.module)
2623 goto nomem_out;
2624 }
2625 }
2606 tev->uprobes = pev->uprobes;2626 tev->uprobes = pev->uprobes;
2607 tev->nargs = pev->nargs;2627 tev->nargs = pev->nargs;
2608 if (tev->nargs) {2628 if (tev->nargs) {
@@ -2624,7 +2644,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev, · 15 unmodified lines
2624 strdup_or_goto(pev->args[i].type,2644 strdup_or_goto(pev->args[i].type,
2625 nomem_out);2645 nomem_out);
2626 }2646 }
2627 arch__fix_tev_from_maps(pev, tev, map);2647 arch__fix_tev_from_maps(pev, tev, map, sym);
2628 }2648 }
2629 if (ret == skipped) {2649 if (ret == skipped) {
2630 ret = -ENOENT;2650 ret = -ENOENT;
@@ -2743,9 +2763,13 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev, · 112 unmodified lines
2743{2763{
2744 int ret;2764 int ret;
2745 2765
2746 if (pev->uprobes && !pev->group) {2766 if (!pev->group) {
2747 /* Replace group name if not given */2767 /* Set group name if not given */
2748 ret = convert_exec_to_group(pev->target, &pev->group);2768 if (!pev->uprobes) {
2769 pev->group = strdup(PERFPROBE_GROUP);
2770 ret = pev->group ? 0 : -ENOMEM;
2771 } else
2772 ret = convert_exec_to_group(pev->target, &pev->group);
2749 if (ret != 0) {2773 if (ret != 0) {
2750 pr_warning("Failed to make a group name.\n");2774 pr_warning("Failed to make a group name.\n");
2751 return ret;2775 return ret;
tools/perf/util/probe-event.h+3−2
@@ -120,7 +120,7 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev); · 119 unmodified lines
120/* Events to command string */120/* Events to command string */
121char *synthesize_perf_probe_command(struct perf_probe_event *pev);121char *synthesize_perf_probe_command(struct perf_probe_event *pev);
122char *synthesize_probe_trace_command(struct probe_trace_event *tev);122char *synthesize_probe_trace_command(struct probe_trace_event *tev);
123int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len);123char *synthesize_perf_probe_arg(struct perf_probe_arg *pa);
124 124
125/* Check the perf_probe_event needs debuginfo */125/* Check the perf_probe_event needs debuginfo */
126bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);126bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
@@ -154,7 +154,8 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs, · 27 unmodified lines
154int show_available_funcs(const char *module, struct strfilter *filter, bool user);154int show_available_funcs(const char *module, struct strfilter *filter, bool user);
155bool arch__prefers_symtab(void);155bool arch__prefers_symtab(void);
156void arch__fix_tev_from_maps(struct perf_probe_event *pev,156void arch__fix_tev_from_maps(struct perf_probe_event *pev,
157 struct probe_trace_event *tev, struct map *map);157 struct probe_trace_event *tev, struct map *map,
158 struct symbol *sym);
158 159
159/* If there is no space to write, returns -E2BIG. */160/* If there is no space to write, returns -E2BIG. */
160int e_snprintf(char *str, size_t size, const char *format, ...)161int e_snprintf(char *str, size_t size, const char *format, ...)
tools/perf/util/probe-file.c+1−2
@@ -220,8 +220,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev) · 219 unmodified lines
220 220
221 pr_debug("Writing event: %s\n", buf);221 pr_debug("Writing event: %s\n", buf);
222 if (!probe_event_dry_run) {222 if (!probe_event_dry_run) {
223 ret = write(fd, buf, strlen(buf));223 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
224 if (ret <= 0) {
225 ret = -errno;224 ret = -errno;
226 pr_warning("Failed to write event: %s\n",225 pr_warning("Failed to write event: %s\n",
227 strerror_r(errno, sbuf, sizeof(sbuf)));226 strerror_r(errno, sbuf, sizeof(sbuf)));
tools/perf/util/probe-finder.c+21−15
@@ -553,7 +553,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) · 552 unmodified lines
553static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)553static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
554{554{
555 Dwarf_Die vr_die;555 Dwarf_Die vr_die;
556 char buf[32], *ptr;556 char *buf, *ptr;
557 int ret = 0;557 int ret = 0;
558 558
559 /* Copy raw parameters */559 /* Copy raw parameters */
@@ -563,13 +563,13 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) · 3 unmodified lines
563 if (pf->pvar->name)563 if (pf->pvar->name)
564 pf->tvar->name = strdup(pf->pvar->name);564 pf->tvar->name = strdup(pf->pvar->name);
565 else {565 else {
566 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32);566 buf = synthesize_perf_probe_arg(pf->pvar);
567 if (ret < 0)567 if (!buf)
568 return ret;568 return -ENOMEM;
569 ptr = strchr(buf, ':'); /* Change type separator to _ */569 ptr = strchr(buf, ':'); /* Change type separator to _ */
570 if (ptr)570 if (ptr)
571 *ptr = '_';571 *ptr = '_';
572 pf->tvar->name = strdup(buf);572 pf->tvar->name = buf;
573 }573 }
574 if (pf->tvar->name == NULL)574 if (pf->tvar->name == NULL)
575 return -ENOMEM;575 return -ENOMEM;
@@ -1294,6 +1294,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) · 718 unmodified lines
1294{1294{
1295 struct available_var_finder *af = data;1295 struct available_var_finder *af = data;
1296 struct variable_list *vl;1296 struct variable_list *vl;
1297 struct strbuf buf = STRBUF_INIT;
1297 int tag, ret;1298 int tag, ret;
1298 1299
1299 vl = &af->vls[af->nvls - 1];1300 vl = &af->vls[af->nvls - 1];
@@ -1307,25 +1308,26 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) · 7 unmodified lines
1307 if (ret == 0 || ret == -ERANGE) {1308 if (ret == 0 || ret == -ERANGE) {
1308 int ret2;1309 int ret2;
1309 bool externs = !af->child;1310 bool externs = !af->child;
1310 struct strbuf buf;
1311 1311
1312 strbuf_init(&buf, 64);1312 if (strbuf_init(&buf, 64) < 0)
1313 goto error;
1313 1314
1314 if (probe_conf.show_location_range) {1315 if (probe_conf.show_location_range) {
1315 if (!externs) {1316 if (!externs)
1316 if (ret)1317 ret2 = strbuf_add(&buf,
1317 strbuf_add(&buf, "[INV]\t", 6);1318 ret ? "[INV]\t" : "[VAL]\t", 6);
1318 else1319 else
1319 strbuf_add(&buf, "[VAL]\t", 6);1320 ret2 = strbuf_add(&buf, "[EXT]\t", 6);
1320 } else1321 if (ret2)
1321 strbuf_add(&buf, "[EXT]\t", 6);1322 goto error;
1322 }1323 }
1323 1324
1324 ret2 = die_get_varname(die_mem, &buf);1325 ret2 = die_get_varname(die_mem, &buf);
1325 1326
1326 if (!ret2 && probe_conf.show_location_range &&1327 if (!ret2 && probe_conf.show_location_range &&
1327 !externs) {1328 !externs) {
1328 strbuf_addch(&buf, '\t');1329 if (strbuf_addch(&buf, '\t') < 0)
1330 goto error;
1329 ret2 = die_get_var_range(&af->pf.sp_die,1331 ret2 = die_get_var_range(&af->pf.sp_die,
1330 die_mem, &buf);1332 die_mem, &buf);
1331 }1333 }
@@ -1343,6 +1345,10 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data) · 11 unmodified lines
1343 return DIE_FIND_CB_CONTINUE;1345 return DIE_FIND_CB_CONTINUE;
1344 else1346 else
1345 return DIE_FIND_CB_SIBLING;1347 return DIE_FIND_CB_SIBLING;
1348error:
1349 strbuf_release(&buf);
1350 pr_debug("Error in strbuf\n");
1351 return DIE_FIND_CB_END;
1346}1352}
1347 1353
1348/* Add a found vars into available variables list */1354/* Add a found vars into available variables list */
tools/perf/util/python-ext-sources+1−0
@@ -23,3 +23,4 @@ util/strlist.c · 22 unmodified lines
23util/trace-event.c23util/trace-event.c
24../lib/rbtree.c24../lib/rbtree.c
25util/string.c25util/string.c
26util/symbol_fprintf.c
tools/perf/util/quote.c+20−16
@@ -17,38 +17,42 @@ static inline int need_bs_quote(char c) · 16 unmodified lines
17 return (c == '\'' || c == '!');17 return (c == '\'' || c == '!');
18}18}
19 19
20static void sq_quote_buf(struct strbuf *dst, const char *src)20static int sq_quote_buf(struct strbuf *dst, const char *src)
21{21{
22 char *to_free = NULL;22 char *to_free = NULL;
23 int ret;
23 24
24 if (dst->buf == src)25 if (dst->buf == src)
25 to_free = strbuf_detach(dst, NULL);26 to_free = strbuf_detach(dst, NULL);
26 27
27 strbuf_addch(dst, '\'');28 ret = strbuf_addch(dst, '\'');
28 while (*src) {29 while (!ret && *src) {
29 size_t len = strcspn(src, "'!");30 size_t len = strcspn(src, "'!");
30 strbuf_add(dst, src, len);31 ret = strbuf_add(dst, src, len);
31 src += len;32 src += len;
32 while (need_bs_quote(*src)) {33 while (!ret && need_bs_quote(*src))
33 strbuf_addstr(dst, "'\\");34 ret = strbuf_addf(dst, "'\\%c\'", *src++);
34 strbuf_addch(dst, *src++);
35 strbuf_addch(dst, '\'');
36 }
37 }35 }
38 strbuf_addch(dst, '\'');36 if (!ret)
37 ret = strbuf_addch(dst, '\'');
39 free(to_free);38 free(to_free);
39
40 return ret;
40}41}
41 42
42void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)43int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
43{44{
44 int i;45 int i, ret;
45 46
46 /* Copy into destination buffer. */47 /* Copy into destination buffer. */
47 strbuf_grow(dst, 255);48 ret = strbuf_grow(dst, 255);
48 for (i = 0; argv[i]; ++i) {49 for (i = 0; !ret && argv[i]; ++i) {
49 strbuf_addch(dst, ' ');50 ret = strbuf_addch(dst, ' ');
50 sq_quote_buf(dst, argv[i]);51 if (ret)
52 break;
53 ret = sq_quote_buf(dst, argv[i]);
51 if (maxlen && dst->len > maxlen)54 if (maxlen && dst->len > maxlen)
52 die("Too many or long arguments");55 die("Too many or long arguments");
53 }56 }
57 return ret;
54}58}
tools/perf/util/quote.h+1−1
@@ -24,6 +24,6 @@ · 23 unmodified lines
24 * sq_quote() in a real application.24 * sq_quote() in a real application.
25 */25 */
26 26
27void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);27int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
28 28
29#endif /* __PERF_QUOTE_H */29#endif /* __PERF_QUOTE_H */
tools/perf/util/rb_resort.h+149−0
@@ -0,0 +1,149 @@
1#ifndef _PERF_RESORT_RB_H_
2#define _PERF_RESORT_RB_H_
3/*
4 * Template for creating a class to resort an existing rb_tree according to
5 * a new sort criteria, that must be present in the entries of the source
6 * rb_tree.
7 *
8 * (c) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
9 *
10 * Quick example, resorting threads by its shortname:
11 *
12 * First define the prefix (threads) to be used for the functions and data
13 * structures created, and provide an expression for the sorting, then the
14 * fields to be present in each of the entries in the new, sorted, rb_tree.
15 *
16 * The body of the init function should collect the fields, maybe
17 * pre-calculating them from multiple entries in the original 'entry' from
18 * the rb_tree used as a source for the entries to be sorted:
19
20DEFINE_RB_RESORT_RB(threads, strcmp(a->thread->shortname,
21 b->thread->shortname) < 0,
22 struct thread *thread;
23)
24{
25 entry->thread = rb_entry(nd, struct thread, rb_node);
26}
27
28 * After this it is just a matter of instantiating it and iterating it,
29 * for a few data structures with existing rb_trees, such as 'struct machine',
30 * helpers are available to get the rb_root and the nr_entries:
31
32 DECLARE_RESORT_RB_MACHINE_THREADS(threads, machine_ptr);
33
34 * This will instantiate the new rb_tree and a cursor for it, that can be used as:
35
36 struct rb_node *nd;
37
38 resort_rb__for_each(nd, threads) {
39 struct thread *t = threads_entry;
40 printf("%s: %d\n", t->shortname, t->tid);
41 }
42
43 * Then delete it:
44
45 resort_rb__delete(threads);
46
47 * The name of the data structures and functions will have a _sorted suffix
48 * right before the method names, i.e. will look like:
49 *
50 * struct threads_sorted_entry {}
51 * threads_sorted__insert()
52 */
53
54#define DEFINE_RESORT_RB(__name, __comp, ...) \
55struct __name##_sorted_entry { \
56 struct rb_node rb_node; \
57 __VA_ARGS__ \
58}; \
59static void __name##_sorted__init_entry(struct rb_node *nd, \
60 struct __name##_sorted_entry *entry); \
61 \
62static int __name##_sorted__cmp(struct rb_node *nda, struct rb_node *ndb) \
63{ \
64 struct __name##_sorted_entry *a, *b; \
65 a = rb_entry(nda, struct __name##_sorted_entry, rb_node); \
66 b = rb_entry(ndb, struct __name##_sorted_entry, rb_node); \
67 return __comp; \
68} \
69 \
70struct __name##_sorted { \
71 struct rb_root entries; \
72 struct __name##_sorted_entry nd[0]; \
73}; \
74 \
75static void __name##_sorted__insert(struct __name##_sorted *sorted, \
76 struct rb_node *sorted_nd) \
77{ \
78 struct rb_node **p = &sorted->entries.rb_node, *parent = NULL; \
79 while (*p != NULL) { \
80 parent = *p; \
81 if (__name##_sorted__cmp(sorted_nd, parent)) \
82 p = &(*p)->rb_left; \
83 else \
84 p = &(*p)->rb_right; \
85 } \
86 rb_link_node(sorted_nd, parent, p); \
87 rb_insert_color(sorted_nd, &sorted->entries); \
88} \
89 \
90static void __name##_sorted__sort(struct __name##_sorted *sorted, \
91 struct rb_root *entries) \
92{ \
93 struct rb_node *nd; \
94 unsigned int i = 0; \
95 for (nd = rb_first(entries); nd; nd = rb_next(nd)) { \
96 struct __name##_sorted_entry *snd = &sorted->nd[i++]; \
97 __name##_sorted__init_entry(nd, snd); \
98 __name##_sorted__insert(sorted, &snd->rb_node); \
99 } \
100} \
101 \
102static struct __name##_sorted *__name##_sorted__new(struct rb_root *entries, \
103 int nr_entries) \
104{ \
105 struct __name##_sorted *sorted; \
106 sorted = malloc(sizeof(*sorted) + sizeof(sorted->nd[0]) * nr_entries); \
107 if (sorted) { \
108 sorted->entries = RB_ROOT; \
109 __name##_sorted__sort(sorted, entries); \
110 } \
111 return sorted; \
112} \
113 \
114static void __name##_sorted__delete(struct __name##_sorted *sorted) \
115{ \
116 free(sorted); \
117} \
118 \
119static void __name##_sorted__init_entry(struct rb_node *nd, \
120 struct __name##_sorted_entry *entry)
121
122#define DECLARE_RESORT_RB(__name) \
123struct __name##_sorted_entry *__name##_entry; \
124struct __name##_sorted *__name = __name##_sorted__new
125
126#define resort_rb__for_each(__nd, __name) \
127 for (__nd = rb_first(&__name->entries); \
128 __name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \
129 rb_node), __nd; \
130 __nd = rb_next(__nd))
131
132#define resort_rb__delete(__name) \
133 __name##_sorted__delete(__name), __name = NULL
134
135/*
136 * Helpers for other classes that contains both an rbtree and the
137 * number of entries in it:
138 */
139
140/* For 'struct intlist' */
141#define DECLARE_RESORT_RB_INTLIST(__name, __ilist) \
142 DECLARE_RESORT_RB(__name)(&__ilist->rblist.entries, \
143 __ilist->rblist.nr_entries)
144
145/* For 'struct machine->threads' */
146#define DECLARE_RESORT_RB_MACHINE_THREADS(__name, __machine) \
147 DECLARE_RESORT_RB(__name)(&__machine->threads, __machine->nr_threads)
148
149#endif /* _PERF_RESORT_RB_H_ */
tools/perf/util/record.c+3−2
@@ -129,7 +129,8 @@ bool perf_can_record_cpu_wide(void) · 128 unmodified lines
129 return true;129 return true;
130}130}
131 131
132void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)132void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
133 struct callchain_param *callchain)
133{134{
134 struct perf_evsel *evsel;135 struct perf_evsel *evsel;
135 bool use_sample_identifier = false;136 bool use_sample_identifier = false;
@@ -148,7 +149,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts) · 12 unmodified lines
148 use_comm_exec = perf_can_comm_exec();149 use_comm_exec = perf_can_comm_exec();
149 150
150 evlist__for_each(evlist, evsel) {151 evlist__for_each(evlist, evsel) {
151 perf_evsel__config(evsel, opts);152 perf_evsel__config(evsel, opts, callchain);
152 if (evsel->tracking && use_comm_exec)153 if (evsel->tracking && use_comm_exec)
153 evsel->attr.comm_exec = 1;154 evsel->attr.comm_exec = 1;
154 }155 }
tools/perf/util/scripting-engines/trace-event-perl.c+118−8
@@ -31,6 +31,8 @@ · 30 unmodified lines
31#include <perl.h>31#include <perl.h>
32 32
33#include "../../perf.h"33#include "../../perf.h"
34#include "../callchain.h"
35#include "../machine.h"
34#include "../thread.h"36#include "../thread.h"
35#include "../event.h"37#include "../event.h"
36#include "../trace-event.h"38#include "../trace-event.h"
@@ -248,10 +250,90 @@ static void define_event_symbols(struct event_format *event, · 211 unmodified lines
248 define_event_symbols(event, ev_name, args->next);250 define_event_symbols(event, ev_name, args->next);
249}251}
250 252
253static SV *perl_process_callchain(struct perf_sample *sample,
254 struct perf_evsel *evsel,
255 struct addr_location *al)
256{
257 AV *list;
258
259 list = newAV();
260 if (!list)
261 goto exit;
262
263 if (!symbol_conf.use_callchain || !sample->callchain)
264 goto exit;
265
266 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
267 sample, NULL, NULL,
268 sysctl_perf_event_max_stack) != 0) {
269 pr_err("Failed to resolve callchain. Skipping\n");
270 goto exit;
271 }
272 callchain_cursor_commit(&callchain_cursor);
273
274
275 while (1) {
276 HV *elem;
277 struct callchain_cursor_node *node;
278 node = callchain_cursor_current(&callchain_cursor);
279 if (!node)
280 break;
281
282 elem = newHV();
283 if (!elem)
284 goto exit;
285
286 if (!hv_stores(elem, "ip", newSVuv(node->ip))) {
287 hv_undef(elem);
288 goto exit;
289 }
290
291 if (node->sym) {
292 HV *sym = newHV();
293 if (!sym) {
294 hv_undef(elem);
295 goto exit;
296 }
297 if (!hv_stores(sym, "start", newSVuv(node->sym->start)) ||
298 !hv_stores(sym, "end", newSVuv(node->sym->end)) ||
299 !hv_stores(sym, "binding", newSVuv(node->sym->binding)) ||
300 !hv_stores(sym, "name", newSVpvn(node->sym->name,
301 node->sym->namelen)) ||
302 !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
303 hv_undef(sym);
304 hv_undef(elem);
305 goto exit;
306 }
307 }
308
309 if (node->map) {
310 struct map *map = node->map;
311 const char *dsoname = "[unknown]";
312 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
313 if (symbol_conf.show_kernel_path && map->dso->long_name)
314 dsoname = map->dso->long_name;
315 else if (map->dso->name)
316 dsoname = map->dso->name;
317 }
318 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
319 hv_undef(elem);
320 goto exit;
321 }
322 }
323
324 callchain_cursor_advance(&callchain_cursor);
325 av_push(list, newRV_noinc((SV*)elem));
326 }
327
328exit:
329 return newRV_noinc((SV*)list);
330}
331
251static void perl_process_tracepoint(struct perf_sample *sample,332static void perl_process_tracepoint(struct perf_sample *sample,
252 struct perf_evsel *evsel,333 struct perf_evsel *evsel,
253 struct thread *thread)334 struct addr_location *al)
254{335{
336 struct thread *thread = al->thread;
255 struct event_format *event = evsel->tp_format;337 struct event_format *event = evsel->tp_format;
256 struct format_field *field;338 struct format_field *field;
257 static char handler[256];339 static char handler[256];
@@ -295,6 +377,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, · 37 unmodified lines
295 XPUSHs(sv_2mortal(newSVuv(ns)));377 XPUSHs(sv_2mortal(newSVuv(ns)));
296 XPUSHs(sv_2mortal(newSViv(pid)));378 XPUSHs(sv_2mortal(newSViv(pid)));
297 XPUSHs(sv_2mortal(newSVpv(comm, 0)));379 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
380 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
298 381
299 /* common fields other than pid can be accessed via xsub fns */382 /* common fields other than pid can be accessed via xsub fns */
300 383
@@ -329,6 +412,7 @@ static void perl_process_tracepoint(struct perf_sample *sample, · 28 unmodified lines
329 XPUSHs(sv_2mortal(newSVuv(nsecs)));412 XPUSHs(sv_2mortal(newSVuv(nsecs)));
330 XPUSHs(sv_2mortal(newSViv(pid)));413 XPUSHs(sv_2mortal(newSViv(pid)));
331 XPUSHs(sv_2mortal(newSVpv(comm, 0)));414 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
415 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
332 call_pv("main::trace_unhandled", G_SCALAR);416 call_pv("main::trace_unhandled", G_SCALAR);
333 }417 }
334 SPAGAIN;418 SPAGAIN;
@@ -366,7 +450,7 @@ static void perl_process_event(union perf_event *event, · 31 unmodified lines
366 struct perf_evsel *evsel,450 struct perf_evsel *evsel,
367 struct addr_location *al)451 struct addr_location *al)
368{452{
369 perl_process_tracepoint(sample, evsel, al->thread);453 perl_process_tracepoint(sample, evsel, al);
370 perl_process_event_generic(event, sample, evsel);454 perl_process_event_generic(event, sample, evsel);
371}455}
372 456
@@ -490,7 +574,27 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) · 117 unmodified lines
490 fprintf(ofp, "use Perf::Trace::Util;\n\n");574 fprintf(ofp, "use Perf::Trace::Util;\n\n");
491 575
492 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");576 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n");
493 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n\n");577 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n");
578
579
580 fprintf(ofp, "\n\
581sub print_backtrace\n\
582{\n\
583 my $callchain = shift;\n\
584 for my $node (@$callchain)\n\
585 {\n\
586 if(exists $node->{sym})\n\
587 {\n\
588 printf( \"\\t[\\%%x] \\%%s\\n\", $node->{ip}, $node->{sym}{name});\n\
589 }\n\
590 else\n\
591 {\n\
592 printf( \"\\t[\\%%x]\\n\", $node{ip});\n\
593 }\n\
594 }\n\
595}\n\n\
596");
597
494 598
495 while ((event = trace_find_next_event(pevent, event))) {599 while ((event = trace_find_next_event(pevent, event))) {
496 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);600 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
@@ -502,7 +606,8 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) · 5 unmodified lines
502 fprintf(ofp, "$common_secs, ");606 fprintf(ofp, "$common_secs, ");
503 fprintf(ofp, "$common_nsecs,\n");607 fprintf(ofp, "$common_nsecs,\n");
504 fprintf(ofp, "\t $common_pid, ");608 fprintf(ofp, "\t $common_pid, ");
505 fprintf(ofp, "$common_comm,\n\t ");609 fprintf(ofp, "$common_comm, ");
610 fprintf(ofp, "$common_callchain,\n\t ");
506 611
507 not_first = 0;612 not_first = 0;
508 count = 0;613 count = 0;
@@ -519,7 +624,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) · 10 unmodified lines
519 624
520 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "625 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
521 "$common_secs, $common_nsecs,\n\t "626 "$common_secs, $common_nsecs,\n\t "
522 "$common_pid, $common_comm);\n\n");627 "$common_pid, $common_comm, $common_callchain);\n\n");
523 628
524 fprintf(ofp, "\tprintf(\"");629 fprintf(ofp, "\tprintf(\"");
525 630
@@ -581,17 +686,22 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile) · 55 unmodified lines
581 fprintf(ofp, "$%s", f->name);686 fprintf(ofp, "$%s", f->name);
582 }687 }
583 688
584 fprintf(ofp, ");\n");689 fprintf(ofp, ");\n\n");
690
691 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
692
585 fprintf(ofp, "}\n\n");693 fprintf(ofp, "}\n\n");
586 }694 }
587 695
588 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "696 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
589 "$common_cpu, $common_secs, $common_nsecs,\n\t "697 "$common_cpu, $common_secs, $common_nsecs,\n\t "
590 "$common_pid, $common_comm) = @_;\n\n");698 "$common_pid, $common_comm, $common_callchain) = @_;\n\n");
591 699
592 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "700 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
593 "$common_secs, $common_nsecs,\n\t $common_pid, "701 "$common_secs, $common_nsecs,\n\t $common_pid, "
594 "$common_comm);\n}\n\n");702 "$common_comm, $common_callchain);\n");
703 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
704 fprintf(ofp, "}\n\n");
595 705
596 fprintf(ofp, "sub print_header\n{\n"706 fprintf(ofp, "sub print_header\n{\n"
597 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"707 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
tools/perf/util/scripting-engines/trace-event-python.c+41−6
@@ -41,6 +41,7 @@ · 40 unmodified lines
41#include "../thread-stack.h"41#include "../thread-stack.h"
42#include "../trace-event.h"42#include "../trace-event.h"
43#include "../machine.h"43#include "../machine.h"
44#include "../call-path.h"
44#include "thread_map.h"45#include "thread_map.h"
45#include "cpumap.h"46#include "cpumap.h"
46#include "stat.h"47#include "stat.h"
@@ -323,7 +324,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample, · 276 unmodified lines
323 if (!symbol_conf.use_callchain || !sample->callchain)324 if (!symbol_conf.use_callchain || !sample->callchain)
324 goto exit;325 goto exit;
325 326
326 if (thread__resolve_callchain(al->thread, evsel,327 if (thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
327 sample, NULL, NULL,328 sample, NULL, NULL,
328 scripting_max_stack) != 0) {329 scripting_max_stack) != 0) {
329 pr_err("Failed to resolve callchain. Skipping\n");330 pr_err("Failed to resolve callchain. Skipping\n");
@@ -407,8 +408,11 @@ static void python_process_tracepoint(struct perf_sample *sample, · 77 unmodified lines
407 if (!t)408 if (!t)
408 Py_FatalError("couldn't create Python tuple");409 Py_FatalError("couldn't create Python tuple");
409 410
410 if (!event)411 if (!event) {
411 die("ug! no event found for type %d", (int)evsel->attr.config);412 snprintf(handler_name, sizeof(handler_name),
413 "ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
414 Py_FatalError(handler_name);
415 }
412 416
413 pid = raw_field_value(event, "common_pid", data);417 pid = raw_field_value(event, "common_pid", data);
414 418
@@ -614,7 +618,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso, · 199 unmodified lines
614 struct machine *machine)618 struct machine *machine)
615{619{
616 struct tables *tables = container_of(dbe, struct tables, dbe);620 struct tables *tables = container_of(dbe, struct tables, dbe);
617 char sbuild_id[BUILD_ID_SIZE * 2 + 1];621 char sbuild_id[SBUILD_ID_SIZE];
618 PyObject *t;622 PyObject *t;
619 623
620 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);624 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
@@ -681,7 +685,7 @@ static int python_export_sample(struct db_export *dbe, · 60 unmodified lines
681 struct tables *tables = container_of(dbe, struct tables, dbe);685 struct tables *tables = container_of(dbe, struct tables, dbe);
682 PyObject *t;686 PyObject *t;
683 687
684 t = tuple_new(21);688 t = tuple_new(22);
685 689
686 tuple_set_u64(t, 0, es->db_id);690 tuple_set_u64(t, 0, es->db_id);
687 tuple_set_u64(t, 1, es->evsel->db_id);691 tuple_set_u64(t, 1, es->evsel->db_id);
@@ -704,6 +708,7 @@ static int python_export_sample(struct db_export *dbe, · 16 unmodified lines
704 tuple_set_u64(t, 18, es->sample->data_src);708 tuple_set_u64(t, 18, es->sample->data_src);
705 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);709 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
706 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));710 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
711 tuple_set_u64(t, 21, es->call_path_id);
707 712
708 call_object(tables->sample_handler, t, "sample_table");713 call_object(tables->sample_handler, t, "sample_table");
709 714
@@ -998,8 +1003,10 @@ static void set_table_handlers(struct tables *tables) · 288 unmodified lines
998{1003{
999 const char *perf_db_export_mode = "perf_db_export_mode";1004 const char *perf_db_export_mode = "perf_db_export_mode";
1000 const char *perf_db_export_calls = "perf_db_export_calls";1005 const char *perf_db_export_calls = "perf_db_export_calls";
1001 PyObject *db_export_mode, *db_export_calls;1006 const char *perf_db_export_callchains = "perf_db_export_callchains";
1007 PyObject *db_export_mode, *db_export_calls, *db_export_callchains;
1002 bool export_calls = false;1008 bool export_calls = false;
1009 bool export_callchains = false;
1003 int ret;1010 int ret;
1004 1011
1005 memset(tables, 0, sizeof(struct tables));1012 memset(tables, 0, sizeof(struct tables));
@@ -1016,6 +1023,7 @@ static void set_table_handlers(struct tables *tables) · 10 unmodified lines
1016 if (!ret)1023 if (!ret)
1017 return;1024 return;
1018 1025
1026 /* handle export calls */
1019 tables->dbe.crp = NULL;1027 tables->dbe.crp = NULL;
1020 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);1028 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
1021 if (db_export_calls) {1029 if (db_export_calls) {
@@ -1033,6 +1041,33 @@ static void set_table_handlers(struct tables *tables) · 11 unmodified lines
1033 Py_FatalError("failed to create calls processor");1041 Py_FatalError("failed to create calls processor");
1034 }1042 }
1035 1043
1044 /* handle export callchains */
1045 tables->dbe.cpr = NULL;
1046 db_export_callchains = PyDict_GetItemString(main_dict,
1047 perf_db_export_callchains);
1048 if (db_export_callchains) {
1049 ret = PyObject_IsTrue(db_export_callchains);
1050 if (ret == -1)
1051 handler_call_die(perf_db_export_callchains);
1052 export_callchains = !!ret;
1053 }
1054
1055 if (export_callchains) {
1056 /*
1057 * Attempt to use the call path root from the call return
1058 * processor, if the call return processor is in use. Otherwise,
1059 * we allocate a new call path root. This prevents exporting
1060 * duplicate call path ids when both are in use simultaniously.
1061 */
1062 if (tables->dbe.crp)
1063 tables->dbe.cpr = tables->dbe.crp->cpr;
1064 else
1065 tables->dbe.cpr = call_path_root__new();
1066
1067 if (!tables->dbe.cpr)
1068 Py_FatalError("failed to create call path root");
1069 }
1070
1036 tables->db_export_mode = true;1071 tables->db_export_mode = true;
1037 /*1072 /*
1038 * Reserve per symbol space for symbol->db_id via symbol__priv()1073 * Reserve per symbol space for symbol->db_id via symbol__priv()
tools/perf/util/session.c+13−102
@@ -409,6 +409,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool) · 408 unmodified lines
409 tool->stat = process_stat_stub;409 tool->stat = process_stat_stub;
410 if (tool->stat_round == NULL)410 if (tool->stat_round == NULL)
411 tool->stat_round = process_stat_round_stub;411 tool->stat_round = process_stat_round_stub;
412 if (tool->time_conv == NULL)
413 tool->time_conv = process_event_op2_stub;
412}414}
413 415
414static void swap_sample_id_all(union perf_event *event, void *data)416static void swap_sample_id_all(union perf_event *event, void *data)
@@ -794,6 +796,7 @@ static perf_event__swap_op perf_event__swap_ops[] = { · 379 unmodified lines
794 [PERF_RECORD_STAT] = perf_event__stat_swap,796 [PERF_RECORD_STAT] = perf_event__stat_swap,
795 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap,797 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap,
796 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap,798 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap,
799 [PERF_RECORD_TIME_CONV] = perf_event__all64_swap,
797 [PERF_RECORD_HEADER_MAX] = NULL,800 [PERF_RECORD_HEADER_MAX] = NULL,
798};801};
799 802
@@ -904,7 +907,7 @@ static void callchain__printf(struct perf_evsel *evsel, · 104 unmodified lines
904 unsigned int i;907 unsigned int i;
905 struct ip_callchain *callchain = sample->callchain;908 struct ip_callchain *callchain = sample->callchain;
906 909
907 if (has_branch_callstack(evsel))910 if (perf_evsel__has_branch_callstack(evsel))
908 callchain__lbr_callstack_printf(sample);911 callchain__lbr_callstack_printf(sample);
909 912
910 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);913 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
@@ -1078,7 +1081,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, · 167 unmodified lines
1078 if (sample_type & PERF_SAMPLE_CALLCHAIN)1081 if (sample_type & PERF_SAMPLE_CALLCHAIN)
1079 callchain__printf(evsel, sample);1082 callchain__printf(evsel, sample);
1080 1083
1081 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel))1084 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel))
1082 branch_stack__printf(sample);1085 branch_stack__printf(sample);
1083 1086
1084 if (sample_type & PERF_SAMPLE_REGS_USER)1087 if (sample_type & PERF_SAMPLE_REGS_USER)
@@ -1341,6 +1344,9 @@ static s64 perf_session__process_user_event(struct perf_session *session, · 256 unmodified lines
1341 return tool->stat(tool, event, session);1344 return tool->stat(tool, event, session);
1342 case PERF_RECORD_STAT_ROUND:1345 case PERF_RECORD_STAT_ROUND:
1343 return tool->stat_round(tool, event, session);1346 return tool->stat_round(tool, event, session);
1347 case PERF_RECORD_TIME_CONV:
1348 session->time_conv = event->time_conv;
1349 return tool->time_conv(tool, event, session);
1344 default:1350 default:
1345 return -EINVAL;1351 return -EINVAL;
1346 }1352 }
@@ -1830,7 +1836,11 @@ out: · 483 unmodified lines
1830out_err:1836out_err:
1831 ui_progress__finish();1837 ui_progress__finish();
1832 perf_session__warn_about_errors(session);1838 perf_session__warn_about_errors(session);
1833 ordered_events__free(&session->ordered_events);1839 /*
1840 * We may switching perf.data output, make ordered_events
1841 * reusable.
1842 */
1843 ordered_events__reinit(&session->ordered_events);
1834 auxtrace__free_events(session);1844 auxtrace__free_events(session);
1835 session->one_mmap = false;1845 session->one_mmap = false;
1836 return err;1846 return err;
@@ -1947,105 +1957,6 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session, · 110 unmodified lines
1947 return NULL;1957 return NULL;
1948}1958}
1949 1959
1950void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
1951 struct addr_location *al,
1952 unsigned int print_opts, unsigned int stack_depth)
1953{
1954 struct callchain_cursor_node *node;
1955 int print_ip = print_opts & PRINT_IP_OPT_IP;
1956 int print_sym = print_opts & PRINT_IP_OPT_SYM;
1957 int print_dso = print_opts & PRINT_IP_OPT_DSO;
1958 int print_symoffset = print_opts & PRINT_IP_OPT_SYMOFFSET;
1959 int print_oneline = print_opts & PRINT_IP_OPT_ONELINE;
1960 int print_srcline = print_opts & PRINT_IP_OPT_SRCLINE;
1961 char s = print_oneline ? ' ' : '\t';
1962
1963 if (symbol_conf.use_callchain && sample->callchain) {
1964 struct addr_location node_al;
1965
1966 if (thread__resolve_callchain(al->thread, evsel,
1967 sample, NULL, NULL,
1968 stack_depth) != 0) {
1969 if (verbose)
1970 error("Failed to resolve callchain. Skipping\n");
1971 return;
1972 }
1973 callchain_cursor_commit(&callchain_cursor);
1974
1975 if (print_symoffset)
1976 node_al = *al;
1977
1978 while (stack_depth) {
1979 u64 addr = 0;
1980
1981 node = callchain_cursor_current(&callchain_cursor);
1982 if (!node)
1983 break;
1984
1985 if (node->sym && node->sym->ignore)
1986 goto next;
1987
1988 if (print_ip)
1989 printf("%c%16" PRIx64, s, node->ip);
1990
1991 if (node->map)
1992 addr = node->map->map_ip(node->map, node->ip);
1993
1994 if (print_sym) {
1995 printf(" ");
1996 if (print_symoffset) {
1997 node_al.addr = addr;
1998 node_al.map = node->map;
1999 symbol__fprintf_symname_offs(node->sym, &node_al, stdout);
2000 } else
2001 symbol__fprintf_symname(node->sym, stdout);
2002 }
2003
2004 if (print_dso) {
2005 printf(" (");
2006 map__fprintf_dsoname(node->map, stdout);
2007 printf(")");
2008 }
2009
2010 if (print_srcline)
2011 map__fprintf_srcline(node->map, addr, "\n ",
2012 stdout);
2013
2014 if (!print_oneline)
2015 printf("\n");
2016
2017 stack_depth--;
2018next:
2019 callchain_cursor_advance(&callchain_cursor);
2020 }
2021
2022 } else {
2023 if (al->sym && al->sym->ignore)
2024 return;
2025
2026 if (print_ip)
2027 printf("%16" PRIx64, sample->ip);
2028
2029 if (print_sym) {
2030 printf(" ");
2031 if (print_symoffset)
2032 symbol__fprintf_symname_offs(al->sym, al,
2033 stdout);
2034 else
2035 symbol__fprintf_symname(al->sym, stdout);
2036 }
2037
2038 if (print_dso) {
2039 printf(" (");
2040 map__fprintf_dsoname(al->map, stdout);
2041 printf(")");
2042 }
2043
2044 if (print_srcline)
2045 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
2046 }
2047}
2048
2049int perf_session__cpu_bitmap(struct perf_session *session,1960int perf_session__cpu_bitmap(struct perf_session *session,
2050 const char *cpu_list, unsigned long *cpu_bitmap)1961 const char *cpu_list, unsigned long *cpu_bitmap)
2051{1962{
tools/perf/util/session.h+1−11
@@ -26,6 +26,7 @@ struct perf_session { · 25 unmodified lines
26 struct itrace_synth_opts *itrace_synth_opts;26 struct itrace_synth_opts *itrace_synth_opts;
27 struct list_head auxtrace_index;27 struct list_head auxtrace_index;
28 struct trace_event tevent;28 struct trace_event tevent;
29 struct time_conv_event time_conv;
29 bool repipe;30 bool repipe;
30 bool one_mmap;31 bool one_mmap;
31 void *one_mmap_addr;32 void *one_mmap_addr;
@@ -35,13 +36,6 @@ struct perf_session { · 3 unmodified lines
35 struct perf_tool *tool;36 struct perf_tool *tool;
36};37};
37 38
38#define PRINT_IP_OPT_IP (1<<0)
39#define PRINT_IP_OPT_SYM (1<<1)
40#define PRINT_IP_OPT_DSO (1<<2)
41#define PRINT_IP_OPT_SYMOFFSET (1<<3)
42#define PRINT_IP_OPT_ONELINE (1<<4)
43#define PRINT_IP_OPT_SRCLINE (1<<5)
44
45struct perf_tool;39struct perf_tool;
46 40
47struct perf_session *perf_session__new(struct perf_data_file *file,41struct perf_session *perf_session__new(struct perf_data_file *file,
@@ -103,10 +97,6 @@ size_t perf_session__fprintf_nr_events(struct perf_session *session, FILE *fp); · 55 unmodified lines
103struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,97struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
104 unsigned int type);98 unsigned int type);
105 99
106void perf_evsel__print_ip(struct perf_evsel *evsel, struct perf_sample *sample,
107 struct addr_location *al,
108 unsigned int print_opts, unsigned int stack_depth);
109
110int perf_session__cpu_bitmap(struct perf_session *session,100int perf_session__cpu_bitmap(struct perf_session *session,
111 const char *cpu_list, unsigned long *cpu_bitmap);101 const char *cpu_list, unsigned long *cpu_bitmap);
112 102
tools/perf/util/sort.c+14−21
@@ -21,13 +21,6 @@ const char *sort_order; · 20 unmodified lines
21const char *field_order;21const char *field_order;
22regex_t ignore_callees_regex;22regex_t ignore_callees_regex;
23int have_ignore_callees = 0;23int have_ignore_callees = 0;
24int sort__need_collapse = 0;
25int sort__has_parent = 0;
26int sort__has_sym = 0;
27int sort__has_dso = 0;
28int sort__has_socket = 0;
29int sort__has_thread = 0;
30int sort__has_comm = 0;
31enum sort_mode sort__mode = SORT_MODE__NORMAL;24enum sort_mode sort__mode = SORT_MODE__NORMAL;
32 25
33/*26/*
@@ -244,7 +237,7 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right) · 210 unmodified lines
244 * comparing symbol address alone is not enough since it's a237 * comparing symbol address alone is not enough since it's a
245 * relative address within a dso.238 * relative address within a dso.
246 */239 */
247 if (!sort__has_dso) {240 if (!hists__has(left->hists, dso) || hists__has(right->hists, dso)) {
248 ret = sort__dso_cmp(left, right);241 ret = sort__dso_cmp(left, right);
249 if (ret != 0)242 if (ret != 0)
250 return ret;243 return ret;
@@ -2163,7 +2156,7 @@ static int __sort_dimension__add(struct sort_dimension *sd, · 1912 unmodified lines
2163 return -1;2156 return -1;
2164 2157
2165 if (sd->entry->se_collapse)2158 if (sd->entry->se_collapse)
2166 sort__need_collapse = 1;2159 list->need_collapse = 1;
2167 2160
2168 sd->taken = 1;2161 sd->taken = 1;
2169 2162
@@ -2245,9 +2238,9 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, · 75 unmodified lines
2245 pr_err("Invalid regex: %s\n%s", parent_pattern, err);2238 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
2246 return -EINVAL;2239 return -EINVAL;
2247 }2240 }
2248 sort__has_parent = 1;2241 list->parent = 1;
2249 } else if (sd->entry == &sort_sym) {2242 } else if (sd->entry == &sort_sym) {
2250 sort__has_sym = 1;2243 list->sym = 1;
2251 /*2244 /*
2252 * perf diff displays the performance difference amongst2245 * perf diff displays the performance difference amongst
2253 * two or more perf.data files. Those files could come2246 * two or more perf.data files. Those files could come
@@ -2258,13 +2251,13 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, · 4 unmodified lines
2258 sd->entry->se_collapse = sort__sym_sort;2251 sd->entry->se_collapse = sort__sym_sort;
2259 2252
2260 } else if (sd->entry == &sort_dso) {2253 } else if (sd->entry == &sort_dso) {
2261 sort__has_dso = 1;2254 list->dso = 1;
2262 } else if (sd->entry == &sort_socket) {2255 } else if (sd->entry == &sort_socket) {
2263 sort__has_socket = 1;2256 list->socket = 1;
2264 } else if (sd->entry == &sort_thread) {2257 } else if (sd->entry == &sort_thread) {
2265 sort__has_thread = 1;2258 list->thread = 1;
2266 } else if (sd->entry == &sort_comm) {2259 } else if (sd->entry == &sort_comm) {
2267 sort__has_comm = 1;2260 list->comm = 1;
2268 }2261 }
2269 2262
2270 return __sort_dimension__add(sd, list, level);2263 return __sort_dimension__add(sd, list, level);
@@ -2289,7 +2282,7 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, · 18 unmodified lines
2289 return -EINVAL;2282 return -EINVAL;
2290 2283
2291 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)2284 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
2292 sort__has_sym = 1;2285 list->sym = 1;
2293 2286
2294 __sort_dimension__add(sd, list, level);2287 __sort_dimension__add(sd, list, level);
2295 return 0;2288 return 0;
@@ -2305,7 +2298,7 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, · 9 unmodified lines
2305 return -EINVAL;2298 return -EINVAL;
2306 2299
2307 if (sd->entry == &sort_mem_daddr_sym)2300 if (sd->entry == &sort_mem_daddr_sym)
2308 sort__has_sym = 1;2301 list->sym = 1;
2309 2302
2310 __sort_dimension__add(sd, list, level);2303 __sort_dimension__add(sd, list, level);
2311 return 0;2304 return 0;
@@ -2749,10 +2742,10 @@ int setup_sorting(struct perf_evlist *evlist) · 437 unmodified lines
2749 2742
2750void reset_output_field(void)2743void reset_output_field(void)
2751{2744{
2752 sort__need_collapse = 0;2745 perf_hpp_list.need_collapse = 0;
2753 sort__has_parent = 0;2746 perf_hpp_list.parent = 0;
2754 sort__has_sym = 0;2747 perf_hpp_list.sym = 0;
2755 sort__has_dso = 0;2748 perf_hpp_list.dso = 0;
2756 2749
2757 field_order = NULL;2750 field_order = NULL;
2758 sort_order = NULL;2751 sort_order = NULL;
tools/perf/util/sort.h+0−7
@@ -31,13 +31,6 @@ extern const char *parent_pattern; · 30 unmodified lines
31extern const char default_sort_order[];31extern const char default_sort_order[];
32extern regex_t ignore_callees_regex;32extern regex_t ignore_callees_regex;
33extern int have_ignore_callees;33extern int have_ignore_callees;
34extern int sort__need_collapse;
35extern int sort__has_dso;
36extern int sort__has_parent;
37extern int sort__has_sym;
38extern int sort__has_socket;
39extern int sort__has_thread;
40extern int sort__has_comm;
41extern enum sort_mode sort__mode;34extern enum sort_mode sort__mode;
42extern struct sort_entry sort_comm;35extern struct sort_entry sort_comm;
43extern struct sort_entry sort_dso;36extern struct sort_entry sort_dso;
tools/perf/util/stat.c+3−1
@@ -307,6 +307,7 @@ int perf_stat_process_counter(struct perf_stat_config *config, · 306 unmodified lines
307 struct perf_counts_values *aggr = &counter->counts->aggr;307 struct perf_counts_values *aggr = &counter->counts->aggr;
308 struct perf_stat_evsel *ps = counter->priv;308 struct perf_stat_evsel *ps = counter->priv;
309 u64 *count = counter->counts->aggr.values;309 u64 *count = counter->counts->aggr.values;
310 u64 val;
310 int i, ret;311 int i, ret;
311 312
312 aggr->val = aggr->ena = aggr->run = 0;313 aggr->val = aggr->ena = aggr->run = 0;
@@ -346,7 +347,8 @@ int perf_stat_process_counter(struct perf_stat_config *config, · 33 unmodified lines
346 /*347 /*
347 * Save the full runtime - to allow normalization during printout:348 * Save the full runtime - to allow normalization during printout:
348 */349 */
349 perf_stat__update_shadow_stats(counter, count, 0);350 val = counter->scale * *count;
351 perf_stat__update_shadow_stats(counter, &val, 0);
350 352
351 return 0;353 return 0;
352}354}
tools/perf/util/strbuf.c+67−26
@@ -1,3 +1,4 @@
1#include "debug.h"
1#include "cache.h"2#include "cache.h"
2#include <linux/kernel.h>3#include <linux/kernel.h>
3 4
@@ -17,12 +18,13 @@ int prefixcmp(const char *str, const char *prefix) · 13 unmodified lines
17 */18 */
18char strbuf_slopbuf[1];19char strbuf_slopbuf[1];
19 20
20void strbuf_init(struct strbuf *sb, ssize_t hint)21int strbuf_init(struct strbuf *sb, ssize_t hint)
21{22{
22 sb->alloc = sb->len = 0;23 sb->alloc = sb->len = 0;
23 sb->buf = strbuf_slopbuf;24 sb->buf = strbuf_slopbuf;
24 if (hint)25 if (hint)
25 strbuf_grow(sb, hint);26 return strbuf_grow(sb, hint);
27 return 0;
26}28}
27 29
28void strbuf_release(struct strbuf *sb)30void strbuf_release(struct strbuf *sb)
@@ -42,67 +44,104 @@ char *strbuf_detach(struct strbuf *sb, size_t *sz) · 13 unmodified lines
42 return res;44 return res;
43}45}
44 46
45void strbuf_grow(struct strbuf *sb, size_t extra)47int strbuf_grow(struct strbuf *sb, size_t extra)
46{48{
47 if (sb->len + extra + 1 <= sb->len)49 char *buf;
48 die("you want to use way too much memory");50 size_t nr = sb->len + extra + 1;
49 if (!sb->alloc)51
50 sb->buf = NULL;52 if (nr < sb->alloc)
51 ALLOC_GROW(sb->buf, sb->len + extra + 1, sb->alloc);53 return 0;
54
55 if (nr <= sb->len)
56 return -E2BIG;
57
58 if (alloc_nr(sb->alloc) > nr)
59 nr = alloc_nr(sb->alloc);
60
61 /*
62 * Note that sb->buf == strbuf_slopbuf if sb->alloc == 0, and it is
63 * a static variable. Thus we have to avoid passing it to realloc.
64 */
65 buf = realloc(sb->alloc ? sb->buf : NULL, nr * sizeof(*buf));
66 if (!buf)
67 return -ENOMEM;
68
69 sb->buf = buf;
70 sb->alloc = nr;
71 return 0;
52}72}
53 73
54void strbuf_addch(struct strbuf *sb, int c)74int strbuf_addch(struct strbuf *sb, int c)
55{75{
56 strbuf_grow(sb, 1);76 int ret = strbuf_grow(sb, 1);
77 if (ret)
78 return ret;
79
57 sb->buf[sb->len++] = c;80 sb->buf[sb->len++] = c;
58 sb->buf[sb->len] = '\0';81 sb->buf[sb->len] = '\0';
82 return 0;
59}83}
60 84
61void strbuf_add(struct strbuf *sb, const void *data, size_t len)85int strbuf_add(struct strbuf *sb, const void *data, size_t len)
62{86{
63 strbuf_grow(sb, len);87 int ret = strbuf_grow(sb, len);
88 if (ret)
89 return ret;
90
64 memcpy(sb->buf + sb->len, data, len);91 memcpy(sb->buf + sb->len, data, len);
65 strbuf_setlen(sb, sb->len + len);92 return strbuf_setlen(sb, sb->len + len);
66}93}
67 94
68static void strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)95static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
69{96{
70 int len;97 int len, ret;
71 va_list ap_saved;98 va_list ap_saved;
72 99
73 if (!strbuf_avail(sb))100 if (!strbuf_avail(sb)) {
74 strbuf_grow(sb, 64);101 ret = strbuf_grow(sb, 64);
102 if (ret)
103 return ret;
104 }
75 105
76 va_copy(ap_saved, ap);106 va_copy(ap_saved, ap);
77 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);107 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap);
78 if (len < 0)108 if (len < 0)
79 die("your vsnprintf is broken");109 return len;
80 if (len > strbuf_avail(sb)) {110 if (len > strbuf_avail(sb)) {
81 strbuf_grow(sb, len);111 ret = strbuf_grow(sb, len);
112 if (ret)
113 return ret;
82 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);114 len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
83 va_end(ap_saved);115 va_end(ap_saved);
84 if (len > strbuf_avail(sb)) {116 if (len > strbuf_avail(sb)) {
85 die("this should not happen, your vsnprintf is broken");117 pr_debug("this should not happen, your vsnprintf is broken");
118 return -EINVAL;
86 }119 }
87 }120 }
88 strbuf_setlen(sb, sb->len + len);121 return strbuf_setlen(sb, sb->len + len);
89}122}
90 123
91void strbuf_addf(struct strbuf *sb, const char *fmt, ...)124int strbuf_addf(struct strbuf *sb, const char *fmt, ...)
92{125{
93 va_list ap;126 va_list ap;
127 int ret;
94 128
95 va_start(ap, fmt);129 va_start(ap, fmt);
96 strbuf_addv(sb, fmt, ap);130 ret = strbuf_addv(sb, fmt, ap);
97 va_end(ap);131 va_end(ap);
132 return ret;
98}133}
99 134
100ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)135ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint)
101{136{
102 size_t oldlen = sb->len;137 size_t oldlen = sb->len;
103 size_t oldalloc = sb->alloc;138 size_t oldalloc = sb->alloc;
139 int ret;
140
141 ret = strbuf_grow(sb, hint ? hint : 8192);
142 if (ret)
143 return ret;
104 144
105 strbuf_grow(sb, hint ? hint : 8192);
106 for (;;) {145 for (;;) {
107 ssize_t cnt;146 ssize_t cnt;
108 147
@@ -112,12 +151,14 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, ssize_t hint) · 3 unmodified lines
112 strbuf_release(sb);151 strbuf_release(sb);
113 else152 else
114 strbuf_setlen(sb, oldlen);153 strbuf_setlen(sb, oldlen);
115 return -1;154 return cnt;
116 }155 }
117 if (!cnt)156 if (!cnt)
118 break;157 break;
119 sb->len += cnt;158 sb->len += cnt;
120 strbuf_grow(sb, 8192);159 ret = strbuf_grow(sb, 8192);
160 if (ret)
161 return ret;
121 }162 }
122 163
123 sb->buf[sb->len] = '\0';164 sb->buf[sb->len] = '\0';
tools/perf/util/strbuf.h+15−10
@@ -51,7 +51,7 @@ struct strbuf { · 50 unmodified lines
51#define STRBUF_INIT { 0, 0, strbuf_slopbuf }51#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
52 52
53/*----- strbuf life cycle -----*/53/*----- strbuf life cycle -----*/
54void strbuf_init(struct strbuf *buf, ssize_t hint);54int strbuf_init(struct strbuf *buf, ssize_t hint);
55void strbuf_release(struct strbuf *buf);55void strbuf_release(struct strbuf *buf);
56char *strbuf_detach(struct strbuf *buf, size_t *);56char *strbuf_detach(struct strbuf *buf, size_t *);
57 57
@@ -60,26 +60,31 @@ static inline ssize_t strbuf_avail(const struct strbuf *sb) { · 2 unmodified lines
60 return sb->alloc ? sb->alloc - sb->len - 1 : 0;60 return sb->alloc ? sb->alloc - sb->len - 1 : 0;
61}61}
62 62
63void strbuf_grow(struct strbuf *buf, size_t);63int strbuf_grow(struct strbuf *buf, size_t);
64 64
65static inline void strbuf_setlen(struct strbuf *sb, size_t len) {65static inline int strbuf_setlen(struct strbuf *sb, size_t len) {
66 if (!sb->alloc)66 int ret;
67 strbuf_grow(sb, 0);67 if (!sb->alloc) {
68 ret = strbuf_grow(sb, 0);
69 if (ret)
70 return ret;
71 }
68 assert(len < sb->alloc);72 assert(len < sb->alloc);
69 sb->len = len;73 sb->len = len;
70 sb->buf[len] = '\0';74 sb->buf[len] = '\0';
75 return 0;
71}76}
72 77
73/*----- add data in your buffer -----*/78/*----- add data in your buffer -----*/
74void strbuf_addch(struct strbuf *sb, int c);79int strbuf_addch(struct strbuf *sb, int c);
75 80
76void strbuf_add(struct strbuf *buf, const void *, size_t);81int strbuf_add(struct strbuf *buf, const void *, size_t);
77static inline void strbuf_addstr(struct strbuf *sb, const char *s) {82static inline int strbuf_addstr(struct strbuf *sb, const char *s) {
78 strbuf_add(sb, s, strlen(s));83 return strbuf_add(sb, s, strlen(s));
79}84}
80 85
81__attribute__((format(printf,2,3)))86__attribute__((format(printf,2,3)))
82void strbuf_addf(struct strbuf *sb, const char *fmt, ...);87int strbuf_addf(struct strbuf *sb, const char *fmt, ...);
83 88
84/* XXX: if read fails, any partial read is undone */89/* XXX: if read fails, any partial read is undone */
85ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);90ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
tools/perf/util/symbol-elf.c+7−13
@@ -709,17 +709,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name, · 708 unmodified lines
709 if (ss->opdshdr.sh_type != SHT_PROGBITS)709 if (ss->opdshdr.sh_type != SHT_PROGBITS)
710 ss->opdsec = NULL;710 ss->opdsec = NULL;
711 711
712 if (dso->kernel == DSO_TYPE_USER) {712 if (dso->kernel == DSO_TYPE_USER)
713 GElf_Shdr shdr;713 ss->adjust_symbols = true;
714 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||714 else
715 ehdr.e_type == ET_REL ||
716 dso__is_vdso(dso) ||
717 elf_section_by_name(elf, &ehdr, &shdr,
718 ".gnu.prelink_undo",
719 NULL) != NULL);
720 } else {
721 ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);715 ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);
722 }
723 716
724 ss->name = strdup(name);717 ss->name = strdup(name);
725 if (!ss->name) {718 if (!ss->name) {
@@ -777,7 +770,8 @@ static bool want_demangle(bool is_kernel_sym) · 51 unmodified lines
777 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;770 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
778}771}
779 772
780void __weak arch__elf_sym_adjust(GElf_Sym *sym __maybe_unused) { }773void __weak arch__sym_update(struct symbol *s __maybe_unused,
774 GElf_Sym *sym __maybe_unused) { }
781 775
782int dso__load_sym(struct dso *dso, struct map *map,776int dso__load_sym(struct dso *dso, struct map *map,
783 struct symsrc *syms_ss, struct symsrc *runtime_ss,777 struct symsrc *syms_ss, struct symsrc *runtime_ss,
@@ -954,8 +948,6 @@ int dso__load_sym(struct dso *dso, struct map *map, · 170 unmodified lines
954 (sym.st_value & 1))948 (sym.st_value & 1))
955 --sym.st_value;949 --sym.st_value;
956 950
957 arch__elf_sym_adjust(&sym);
958
959 if (dso->kernel || kmodule) {951 if (dso->kernel || kmodule) {
960 char dso_name[PATH_MAX];952 char dso_name[PATH_MAX];
961 953
@@ -1089,6 +1081,8 @@ new_symbol: · 127 unmodified lines
1089 if (!f)1081 if (!f)
1090 goto out_elf_end;1082 goto out_elf_end;
1091 1083
1084 arch__sym_update(f, &sym);
1085
1092 if (filter && filter(curr_map, f))1086 if (filter && filter(curr_map, f))
1093 symbol__delete(f);1087 symbol__delete(f);
1094 else {1088 else {
tools/perf/util/symbol.c+37−71
@@ -255,40 +255,6 @@ void symbol__delete(struct symbol *sym) · 254 unmodified lines
255 free(((void *)sym) - symbol_conf.priv_size);255 free(((void *)sym) - symbol_conf.priv_size);
256}256}
257 257
258size_t symbol__fprintf(struct symbol *sym, FILE *fp)
259{
260 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
261 sym->start, sym->end,
262 sym->binding == STB_GLOBAL ? 'g' :
263 sym->binding == STB_LOCAL ? 'l' : 'w',
264 sym->name);
265}
266
267size_t symbol__fprintf_symname_offs(const struct symbol *sym,
268 const struct addr_location *al, FILE *fp)
269{
270 unsigned long offset;
271 size_t length;
272
273 if (sym && sym->name) {
274 length = fprintf(fp, "%s", sym->name);
275 if (al) {
276 if (al->addr < sym->end)
277 offset = al->addr - sym->start;
278 else
279 offset = al->addr - al->map->start - sym->start;
280 length += fprintf(fp, "+0x%lx", offset);
281 }
282 return length;
283 } else
284 return fprintf(fp, "[unknown]");
285}
286
287size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
288{
289 return symbol__fprintf_symname_offs(sym, NULL, fp);
290}
291
292void symbols__delete(struct rb_root *symbols)258void symbols__delete(struct rb_root *symbols)
293{259{
294 struct symbol *pos;260 struct symbol *pos;
@@ -335,7 +301,7 @@ static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) · 40 unmodified lines
335 301
336 if (ip < s->start)302 if (ip < s->start)
337 n = n->rb_left;303 n = n->rb_left;
338 else if (ip >= s->end)304 else if (ip > s->end || (ip == s->end && ip != s->start))
339 n = n->rb_right;305 n = n->rb_right;
340 else306 else
341 return s;307 return s;
@@ -364,11 +330,6 @@ static struct symbol *symbols__next(struct symbol *sym) · 22 unmodified lines
364 return NULL;330 return NULL;
365}331}
366 332
367struct symbol_name_rb_node {
368 struct rb_node rb_node;
369 struct symbol sym;
370};
371
372static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym)333static void symbols__insert_by_name(struct rb_root *symbols, struct symbol *sym)
373{334{
374 struct rb_node **p = &symbols->rb_node;335 struct rb_node **p = &symbols->rb_node;
@@ -452,6 +413,18 @@ void dso__reset_find_symbol_cache(struct dso *dso) · 77 unmodified lines
452 }413 }
453}414}
454 415
416void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
417{
418 symbols__insert(&dso->symbols[type], sym);
419
420 /* update the symbol cache if necessary */
421 if (dso->last_find_result[type].addr >= sym->start &&
422 (dso->last_find_result[type].addr < sym->end ||
423 sym->start == sym->end)) {
424 dso->last_find_result[type].symbol = sym;
425 }
426}
427
455struct symbol *dso__find_symbol(struct dso *dso,428struct symbol *dso__find_symbol(struct dso *dso,
456 enum map_type type, u64 addr)429 enum map_type type, u64 addr)
457{430{
@@ -497,21 +470,6 @@ void dso__sort_by_name(struct dso *dso, enum map_type type) · 39 unmodified lines
497 &dso->symbols[type]);470 &dso->symbols[type]);
498}471}
499 472
500size_t dso__fprintf_symbols_by_name(struct dso *dso,
501 enum map_type type, FILE *fp)
502{
503 size_t ret = 0;
504 struct rb_node *nd;
505 struct symbol_name_rb_node *pos;
506
507 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) {
508 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
509 fprintf(fp, "%s\n", pos->sym.name);
510 }
511
512 return ret;
513}
514
515int modules__parse(const char *filename, void *arg,473int modules__parse(const char *filename, void *arg,
516 int (*process_module)(void *arg, const char *name,474 int (*process_module)(void *arg, const char *name,
517 u64 start))475 u64 start))
@@ -1262,8 +1220,8 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta) · 744 unmodified lines
1262 return 0;1220 return 0;
1263}1221}
1264 1222
1265int dso__load_kallsyms(struct dso *dso, const char *filename,1223int __dso__load_kallsyms(struct dso *dso, const char *filename,
1266 struct map *map, symbol_filter_t filter)1224 struct map *map, bool no_kcore, symbol_filter_t filter)
1267{1225{
1268 u64 delta = 0;1226 u64 delta = 0;
1269 1227
@@ -1284,12 +1242,18 @@ int dso__load_kallsyms(struct dso *dso, const char *filename, · 14 unmodified lines
1284 else1242 else
1285 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;1243 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
1286 1244
1287 if (!dso__load_kcore(dso, map, filename))1245 if (!no_kcore && !dso__load_kcore(dso, map, filename))
1288 return dso__split_kallsyms_for_kcore(dso, map, filter);1246 return dso__split_kallsyms_for_kcore(dso, map, filter);
1289 else1247 else
1290 return dso__split_kallsyms(dso, map, delta, filter);1248 return dso__split_kallsyms(dso, map, delta, filter);
1291}1249}
1292 1250
1251int dso__load_kallsyms(struct dso *dso, const char *filename,
1252 struct map *map, symbol_filter_t filter)
1253{
1254 return __dso__load_kallsyms(dso, filename, map, false, filter);
1255}
1256
1293static int dso__load_perf_map(struct dso *dso, struct map *map,1257static int dso__load_perf_map(struct dso *dso, struct map *map,
1294 symbol_filter_t filter)1258 symbol_filter_t filter)
1295{1259{
@@ -1644,25 +1608,27 @@ out: · 348 unmodified lines
1644 return err;1608 return err;
1645}1609}
1646 1610
1611static bool visible_dir_filter(const char *name, struct dirent *d)
1612{
1613 if (d->d_type != DT_DIR)
1614 return false;
1615 return lsdir_no_dot_filter(name, d);
1616}
1617
1647static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)1618static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1648{1619{
1649 char kallsyms_filename[PATH_MAX];1620 char kallsyms_filename[PATH_MAX];
1650 struct dirent *dent;
1651 int ret = -1;1621 int ret = -1;
1652 DIR *d;1622 struct strlist *dirs;
1623 struct str_node *nd;
1653 1624
1654 d = opendir(dir);1625 dirs = lsdir(dir, visible_dir_filter);
1655 if (!d)1626 if (!dirs)
1656 return -1;1627 return -1;
1657 1628
1658 while (1) {1629 strlist__for_each(nd, dirs) {
1659 dent = readdir(d);
1660 if (!dent)
1661 break;
1662 if (dent->d_type != DT_DIR)
1663 continue;
1664 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),1630 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1665 "%s/%s/kallsyms", dir, dent->d_name);1631 "%s/%s/kallsyms", dir, nd->s);
1666 if (!validate_kcore_addresses(kallsyms_filename, map)) {1632 if (!validate_kcore_addresses(kallsyms_filename, map)) {
1667 strlcpy(dir, kallsyms_filename, dir_sz);1633 strlcpy(dir, kallsyms_filename, dir_sz);
1668 ret = 0;1634 ret = 0;
@@ -1670,7 +1636,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz) · 1 unmodified line
1670 }1636 }
1671 }1637 }
1672 1638
1673 closedir(d);1639 strlist__delete(dirs);
1674 1640
1675 return ret;1641 return ret;
1676}1642}
@@ -1678,7 +1644,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz) · 1 unmodified line
1678static char *dso__find_kallsyms(struct dso *dso, struct map *map)1644static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1679{1645{
1680 u8 host_build_id[BUILD_ID_SIZE];1646 u8 host_build_id[BUILD_ID_SIZE];
1681 char sbuild_id[BUILD_ID_SIZE * 2 + 1];1647 char sbuild_id[SBUILD_ID_SIZE];
1682 bool is_host = false;1648 bool is_host = false;
1683 char path[PATH_MAX];1649 char path[PATH_MAX];
1684 1650
tools/perf/util/symbol.h+18−1
@@ -55,6 +55,7 @@ struct symbol { · 54 unmodified lines
55 u16 namelen;55 u16 namelen;
56 u8 binding;56 u8 binding;
57 bool ignore;57 bool ignore;
58 u8 arch_sym;
58 char name[0];59 char name[0];
59};60};
60 61
@@ -140,6 +141,11 @@ struct symbol_conf { · 79 unmodified lines
140 141
141extern struct symbol_conf symbol_conf;142extern struct symbol_conf symbol_conf;
142 143
144struct symbol_name_rb_node {
145 struct rb_node rb_node;
146 struct symbol sym;
147};
148
143static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)149static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
144{150{
145 return path__join(bf, size, symbol_conf.symfs, path);151 return path__join(bf, size, symbol_conf.symfs, path);
@@ -235,9 +241,14 @@ int dso__load_vmlinux(struct dso *dso, struct map *map, · 89 unmodified lines
235 symbol_filter_t filter);241 symbol_filter_t filter);
236int dso__load_vmlinux_path(struct dso *dso, struct map *map,242int dso__load_vmlinux_path(struct dso *dso, struct map *map,
237 symbol_filter_t filter);243 symbol_filter_t filter);
244int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
245 bool no_kcore, symbol_filter_t filter);
238int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,246int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
239 symbol_filter_t filter);247 symbol_filter_t filter);
240 248
249void dso__insert_symbol(struct dso *dso, enum map_type type,
250 struct symbol *sym);
251
241struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,252struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
242 u64 addr);253 u64 addr);
243struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,254struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
@@ -262,8 +273,14 @@ int symbol__init(struct perf_env *env); · 18 unmodified lines
262void symbol__exit(void);273void symbol__exit(void);
263void symbol__elf_init(void);274void symbol__elf_init(void);
264struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);275struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
276size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
277 const struct addr_location *al,
278 bool unknown_as_addr, FILE *fp);
265size_t symbol__fprintf_symname_offs(const struct symbol *sym,279size_t symbol__fprintf_symname_offs(const struct symbol *sym,
266 const struct addr_location *al, FILE *fp);280 const struct addr_location *al, FILE *fp);
281size_t __symbol__fprintf_symname(const struct symbol *sym,
282 const struct addr_location *al,
283 bool unknown_as_addr, FILE *fp);
267size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);284size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
268size_t symbol__fprintf(struct symbol *sym, FILE *fp);285size_t symbol__fprintf(struct symbol *sym, FILE *fp);
269bool symbol_type__is_a(char symbol_type, enum map_type map_type);286bool symbol_type__is_a(char symbol_type, enum map_type map_type);
@@ -310,7 +327,7 @@ int setup_intlist(struct intlist **list, const char *list_str, · 40 unmodified lines
310 327
311#ifdef HAVE_LIBELF_SUPPORT328#ifdef HAVE_LIBELF_SUPPORT
312bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);329bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
313void arch__elf_sym_adjust(GElf_Sym *sym);330void arch__sym_update(struct symbol *s, GElf_Sym *sym);
314#endif331#endif
315 332
316#define SYMBOL_A 0333#define SYMBOL_A 0
tools/perf/util/symbol_fprintf.c+71−0
@@ -0,0 +1,71 @@
1#include <elf.h>
2#include <inttypes.h>
3#include <stdio.h>
4
5#include "symbol.h"
6
7size_t symbol__fprintf(struct symbol *sym, FILE *fp)
8{
9 return fprintf(fp, " %" PRIx64 "-%" PRIx64 " %c %s\n",
10 sym->start, sym->end,
11 sym->binding == STB_GLOBAL ? 'g' :
12 sym->binding == STB_LOCAL ? 'l' : 'w',
13 sym->name);
14}
15
16size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
17 const struct addr_location *al,
18 bool unknown_as_addr, FILE *fp)
19{
20 unsigned long offset;
21 size_t length;
22
23 if (sym && sym->name) {
24 length = fprintf(fp, "%s", sym->name);
25 if (al) {
26 if (al->addr < sym->end)
27 offset = al->addr - sym->start;
28 else
29 offset = al->addr - al->map->start - sym->start;
30 length += fprintf(fp, "+0x%lx", offset);
31 }
32 return length;
33 } else if (al && unknown_as_addr)
34 return fprintf(fp, "[%#" PRIx64 "]", al->addr);
35 else
36 return fprintf(fp, "[unknown]");
37}
38
39size_t symbol__fprintf_symname_offs(const struct symbol *sym,
40 const struct addr_location *al,
41 FILE *fp)
42{
43 return __symbol__fprintf_symname_offs(sym, al, false, fp);
44}
45
46size_t __symbol__fprintf_symname(const struct symbol *sym,
47 const struct addr_location *al,
48 bool unknown_as_addr, FILE *fp)
49{
50 return __symbol__fprintf_symname_offs(sym, al, unknown_as_addr, fp);
51}
52
53size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp)
54{
55 return __symbol__fprintf_symname_offs(sym, NULL, false, fp);
56}
57
58size_t dso__fprintf_symbols_by_name(struct dso *dso,
59 enum map_type type, FILE *fp)
60{
61 size_t ret = 0;
62 struct rb_node *nd;
63 struct symbol_name_rb_node *pos;
64
65 for (nd = rb_first(&dso->symbol_names[type]); nd; nd = rb_next(nd)) {
66 pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
67 fprintf(fp, "%s\n", pos->sym.name);
68 }
69
70 return ret;
71}
tools/perf/util/syscalltbl.c+134−0
@@ -0,0 +1,134 @@
1/*
2 * System call table mapper
3 *
4 * (C) 2016 Arnaldo Carvalho de Melo <acme@redhat.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15
16#include "syscalltbl.h"
17#include <stdlib.h>
18
19#ifdef HAVE_SYSCALL_TABLE
20#include <linux/compiler.h>
21#include <string.h>
22#include "util.h"
23
24#if defined(__x86_64__)
25#include <asm/syscalls_64.c>
26const int syscalltbl_native_max_id = SYSCALLTBL_x86_64_MAX_ID;
27static const char **syscalltbl_native = syscalltbl_x86_64;
28#endif
29
30struct syscall {
31 int id;
32 const char *name;
33};
34
35static int syscallcmpname(const void *vkey, const void *ventry)
36{
37 const char *key = vkey;
38 const struct syscall *entry = ventry;
39
40 return strcmp(key, entry->name);
41}
42
43static int syscallcmp(const void *va, const void *vb)
44{
45 const struct syscall *a = va, *b = vb;
46
47 return strcmp(a->name, b->name);
48}
49
50static int syscalltbl__init_native(struct syscalltbl *tbl)
51{
52 int nr_entries = 0, i, j;
53 struct syscall *entries;
54
55 for (i = 0; i <= syscalltbl_native_max_id; ++i)
56 if (syscalltbl_native[i])
57 ++nr_entries;
58
59 entries = tbl->syscalls.entries = malloc(sizeof(struct syscall) * nr_entries);
60 if (tbl->syscalls.entries == NULL)
61 return -1;
62
63 for (i = 0, j = 0; i <= syscalltbl_native_max_id; ++i) {
64 if (syscalltbl_native[i]) {
65 entries[j].name = syscalltbl_native[i];
66 entries[j].id = i;
67 ++j;
68 }
69 }
70
71 qsort(tbl->syscalls.entries, nr_entries, sizeof(struct syscall), syscallcmp);
72 tbl->syscalls.nr_entries = nr_entries;
73 return 0;
74}
75
76struct syscalltbl *syscalltbl__new(void)
77{
78 struct syscalltbl *tbl = malloc(sizeof(*tbl));
79 if (tbl) {
80 if (syscalltbl__init_native(tbl)) {
81 free(tbl);
82 return NULL;
83 }
84 }
85 return tbl;
86}
87
88void syscalltbl__delete(struct syscalltbl *tbl)
89{
90 zfree(&tbl->syscalls.entries);
91 free(tbl);
92}
93
94const char *syscalltbl__name(const struct syscalltbl *tbl __maybe_unused, int id)
95{
96 return id <= syscalltbl_native_max_id ? syscalltbl_native[id]: NULL;
97}
98
99int syscalltbl__id(struct syscalltbl *tbl, const char *name)
100{
101 struct syscall *sc = bsearch(name, tbl->syscalls.entries,
102 tbl->syscalls.nr_entries, sizeof(*sc),
103 syscallcmpname);
104
105 return sc ? sc->id : -1;
106}
107
108#else /* HAVE_SYSCALL_TABLE */
109
110#include <libaudit.h>
111
112struct syscalltbl *syscalltbl__new(void)
113{
114 struct syscalltbl *tbl = malloc(sizeof(*tbl));
115 if (tbl)
116 tbl->audit_machine = audit_detect_machine();
117 return tbl;
118}
119
120void syscalltbl__delete(struct syscalltbl *tbl)
121{
122 free(tbl);
123}
124
125const char *syscalltbl__name(const struct syscalltbl *tbl, int id)
126{
127 return audit_syscall_to_name(id, tbl->audit_machine);
128}
129
130int syscalltbl__id(struct syscalltbl *tbl, const char *name)
131{
132 return audit_name_to_syscall(name, tbl->audit_machine);
133}
134#endif /* HAVE_SYSCALL_TABLE */
tools/perf/util/syscalltbl.h+20−0
@@ -0,0 +1,20 @@
1#ifndef __PERF_SYSCALLTBL_H
2#define __PERF_SYSCALLTBL_H
3
4struct syscalltbl {
5 union {
6 int audit_machine;
7 struct {
8 int nr_entries;
9 void *entries;
10 } syscalls;
11 };
12};
13
14struct syscalltbl *syscalltbl__new(void);
15void syscalltbl__delete(struct syscalltbl *tbl);
16
17const char *syscalltbl__name(const struct syscalltbl *tbl, int id);
18int syscalltbl__id(struct syscalltbl *tbl, const char *name);
19
20#endif /* __PERF_SYSCALLTBL_H */
tools/perf/util/thread-stack.c+1−138
@@ -22,44 +22,9 @@ · 21 unmodified lines
22#include "debug.h"22#include "debug.h"
23#include "symbol.h"23#include "symbol.h"
24#include "comm.h"24#include "comm.h"
25#include "call-path.h"
25#include "thread-stack.h"26#include "thread-stack.h"
26 27
27#define CALL_PATH_BLOCK_SHIFT 8
28#define CALL_PATH_BLOCK_SIZE (1 << CALL_PATH_BLOCK_SHIFT)
29#define CALL_PATH_BLOCK_MASK (CALL_PATH_BLOCK_SIZE - 1)
30
31struct call_path_block {
32 struct call_path cp[CALL_PATH_BLOCK_SIZE];
33 struct list_head node;
34};
35
36/**
37 * struct call_path_root - root of all call paths.
38 * @call_path: root call path
39 * @blocks: list of blocks to store call paths
40 * @next: next free space
41 * @sz: number of spaces
42 */
43struct call_path_root {
44 struct call_path call_path;
45 struct list_head blocks;
46 size_t next;
47 size_t sz;
48};
49
50/**
51 * struct call_return_processor - provides a call-back to consume call-return
52 * information.
53 * @cpr: call path root
54 * @process: call-back that accepts call/return information
55 * @data: anonymous data for call-back
56 */
57struct call_return_processor {
58 struct call_path_root *cpr;
59 int (*process)(struct call_return *cr, void *data);
60 void *data;
61};
62
63#define STACK_GROWTH 204828#define STACK_GROWTH 2048
64 29
65/**30/**
@@ -335,108 +300,6 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain, · 269 unmodified lines
335 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;300 chain->ips[i] = thread->ts->stack[thread->ts->cnt - i].ret_addr;
336}301}
337 302
338static void call_path__init(struct call_path *cp, struct call_path *parent,
339 struct symbol *sym, u64 ip, bool in_kernel)
340{
341 cp->parent = parent;
342 cp->sym = sym;
343 cp->ip = sym ? 0 : ip;
344 cp->db_id = 0;
345 cp->in_kernel = in_kernel;
346 RB_CLEAR_NODE(&cp->rb_node);
347 cp->children = RB_ROOT;
348}
349
350static struct call_path_root *call_path_root__new(void)
351{
352 struct call_path_root *cpr;
353
354 cpr = zalloc(sizeof(struct call_path_root));
355 if (!cpr)
356 return NULL;
357 call_path__init(&cpr->call_path, NULL, NULL, 0, false);
358 INIT_LIST_HEAD(&cpr->blocks);
359 return cpr;
360}
361
362static void call_path_root__free(struct call_path_root *cpr)
363{
364 struct call_path_block *pos, *n;
365
366 list_for_each_entry_safe(pos, n, &cpr->blocks, node) {
367 list_del(&pos->node);
368 free(pos);
369 }
370 free(cpr);
371}
372
373static struct call_path *call_path__new(struct call_path_root *cpr,
374 struct call_path *parent,
375 struct symbol *sym, u64 ip,
376 bool in_kernel)
377{
378 struct call_path_block *cpb;
379 struct call_path *cp;
380 size_t n;
381
382 if (cpr->next < cpr->sz) {
383 cpb = list_last_entry(&cpr->blocks, struct call_path_block,
384 node);
385 } else {
386 cpb = zalloc(sizeof(struct call_path_block));
387 if (!cpb)
388 return NULL;
389 list_add_tail(&cpb->node, &cpr->blocks);
390 cpr->sz += CALL_PATH_BLOCK_SIZE;
391 }
392
393 n = cpr->next++ & CALL_PATH_BLOCK_MASK;
394 cp = &cpb->cp[n];
395
396 call_path__init(cp, parent, sym, ip, in_kernel);
397
398 return cp;
399}
400
401static struct call_path *call_path__findnew(struct call_path_root *cpr,
402 struct call_path *parent,
403 struct symbol *sym, u64 ip, u64 ks)
404{
405 struct rb_node **p;
406 struct rb_node *node_parent = NULL;
407 struct call_path *cp;
408 bool in_kernel = ip >= ks;
409
410 if (sym)
411 ip = 0;
412
413 if (!parent)
414 return call_path__new(cpr, parent, sym, ip, in_kernel);
415
416 p = &parent->children.rb_node;
417 while (*p != NULL) {
418 node_parent = *p;
419 cp = rb_entry(node_parent, struct call_path, rb_node);
420
421 if (cp->sym == sym && cp->ip == ip)
422 return cp;
423
424 if (sym < cp->sym || (sym == cp->sym && ip < cp->ip))
425 p = &(*p)->rb_left;
426 else
427 p = &(*p)->rb_right;
428 }
429
430 cp = call_path__new(cpr, parent, sym, ip, in_kernel);
431 if (!cp)
432 return NULL;
433
434 rb_link_node(&cp->rb_node, node_parent, p);
435 rb_insert_color(&cp->rb_node, &parent->children);
436
437 return cp;
438}
439
440struct call_return_processor *303struct call_return_processor *
441call_return_processor__new(int (*process)(struct call_return *cr, void *data),304call_return_processor__new(int (*process)(struct call_return *cr, void *data),
442 void *data)305 void *data)
tools/perf/util/thread-stack.h+10−21
@@ -19,17 +19,16 @@ · 18 unmodified lines
19#include <sys/types.h>19#include <sys/types.h>
20 20
21#include <linux/types.h>21#include <linux/types.h>
22#include <linux/rbtree.h>
23 22
24struct thread;23struct thread;
25struct comm;24struct comm;
26struct ip_callchain;25struct ip_callchain;
27struct symbol;26struct symbol;
28struct dso;27struct dso;
29struct call_return_processor;
30struct comm;28struct comm;
31struct perf_sample;29struct perf_sample;
32struct addr_location;30struct addr_location;
31struct call_path;
33 32
34/*33/*
35 * Call/Return flags.34 * Call/Return flags.
@@ -69,26 +68,16 @@ struct call_return { · 33 unmodified lines
69};68};
70 69
71/**70/**
72 * struct call_path - node in list of calls leading to a function call.71 * struct call_return_processor - provides a call-back to consume call-return
73 * @parent: call path to the parent function call72 * information.
74 * @sym: symbol of function called73 * @cpr: call path root
75 * @ip: only if sym is null, the ip of the function74 * @process: call-back that accepts call/return information
76 * @db_id: id used for db-export75 * @data: anonymous data for call-back
77 * @in_kernel: whether function is a in the kernel
78 * @rb_node: node in parent's tree of called functions
79 * @children: tree of call paths of functions called
80 *
81 * In combination with the call_return structure, the call_path structure
82 * defines a context-sensitve call-graph.
83 */76 */
84struct call_path {77struct call_return_processor {
85 struct call_path *parent;78 struct call_path_root *cpr;
86 struct symbol *sym;79 int (*process)(struct call_return *cr, void *data);
87 u64 ip;80 void *data;
88 u64 db_id;
89 bool in_kernel;
90 struct rb_node rb_node;
91 struct rb_root children;
92};81};
93 82
94int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,83int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
tools/perf/util/thread.c+20−1
@@ -10,6 +10,8 @@ · 9 unmodified lines
10#include "comm.h"10#include "comm.h"
11#include "unwind.h"11#include "unwind.h"
12 12
13#include <api/fs/fs.h>
14
13int thread__init_map_groups(struct thread *thread, struct machine *machine)15int thread__init_map_groups(struct thread *thread, struct machine *machine)
14{16{
15 struct thread *leader;17 struct thread *leader;
@@ -153,6 +155,23 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp, · 137 unmodified lines
153 return 0;155 return 0;
154}156}
155 157
158int thread__set_comm_from_proc(struct thread *thread)
159{
160 char path[64];
161 char *comm = NULL;
162 size_t sz;
163 int err = -1;
164
165 if (!(snprintf(path, sizeof(path), "%d/task/%d/comm",
166 thread->pid_, thread->tid) >= (int)sizeof(path)) &&
167 procfs__read_str(path, &comm, &sz) == 0) {
168 comm[sz - 1] = '\0';
169 err = thread__set_comm(thread, comm, 0);
170 }
171
172 return err;
173}
174
156const char *thread__comm_str(const struct thread *thread)175const char *thread__comm_str(const struct thread *thread)
157{176{
158 const struct comm *comm = thread__comm(thread);177 const struct comm *comm = thread__comm(thread);
@@ -233,7 +252,7 @@ void thread__find_cpumode_addr_location(struct thread *thread, · 74 unmodified lines
233 struct addr_location *al)252 struct addr_location *al)
234{253{
235 size_t i;254 size_t i;
236 const u8 const cpumodes[] = {255 const u8 cpumodes[] = {
237 PERF_RECORD_MISC_USER,256 PERF_RECORD_MISC_USER,
238 PERF_RECORD_MISC_KERNEL,257 PERF_RECORD_MISC_KERNEL,
239 PERF_RECORD_MISC_GUEST_USER,258 PERF_RECORD_MISC_GUEST_USER,
tools/perf/util/thread.h+8−0
@@ -9,6 +9,9 @@ · 8 unmodified lines
9#include "symbol.h"9#include "symbol.h"
10#include <strlist.h>10#include <strlist.h>
11#include <intlist.h>11#include <intlist.h>
12#ifdef HAVE_LIBUNWIND_SUPPORT
13#include <libunwind.h>
14#endif
12 15
13struct thread_stack;16struct thread_stack;
14 17
@@ -32,6 +35,9 @@ struct thread { · 17 unmodified lines
32 35
33 void *priv;36 void *priv;
34 struct thread_stack *ts;37 struct thread_stack *ts;
38#ifdef HAVE_LIBUNWIND_SUPPORT
39 unw_addr_space_t addr_space;
40#endif
35};41};
36 42
37struct machine;43struct machine;
@@ -65,6 +71,8 @@ static inline int thread__set_comm(struct thread *thread, const char *comm, · 27 unmodified lines
65 return __thread__set_comm(thread, comm, timestamp, false);71 return __thread__set_comm(thread, comm, timestamp, false);
66}72}
67 73
74int thread__set_comm_from_proc(struct thread *thread);
75
68int thread__comm_len(struct thread *thread);76int thread__comm_len(struct thread *thread);
69struct comm *thread__comm(const struct thread *thread);77struct comm *thread__comm(const struct thread *thread);
70struct comm *thread__exec_comm(const struct thread *thread);78struct comm *thread__exec_comm(const struct thread *thread);
tools/perf/util/thread_map.c+13−1
@@ -260,7 +260,7 @@ struct thread_map *thread_map__new_dummy(void) · 259 unmodified lines
260 return threads;260 return threads;
261}261}
262 262
263static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)263struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
264{264{
265 struct thread_map *threads = NULL, *nt;265 struct thread_map *threads = NULL, *nt;
266 int ntasks = 0;266 int ntasks = 0;
@@ -436,3 +436,15 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event) · 169 unmodified lines
436 436
437 return threads;437 return threads;
438}438}
439
440bool thread_map__has(struct thread_map *threads, pid_t pid)
441{
442 int i;
443
444 for (i = 0; i < threads->nr; ++i) {
445 if (threads->map[i].pid == pid)
446 return true;
447 }
448
449 return false;
450}
tools/perf/util/thread_map.h+3−0
@@ -31,6 +31,8 @@ void thread_map__put(struct thread_map *map); · 30 unmodified lines
31struct thread_map *thread_map__new_str(const char *pid,31struct thread_map *thread_map__new_str(const char *pid,
32 const char *tid, uid_t uid);32 const char *tid, uid_t uid);
33 33
34struct thread_map *thread_map__new_by_tid_str(const char *tid_str);
35
34size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);36size_t thread_map__fprintf(struct thread_map *threads, FILE *fp);
35 37
36static inline int thread_map__nr(struct thread_map *threads)38static inline int thread_map__nr(struct thread_map *threads)
@@ -55,4 +57,5 @@ static inline char *thread_map__comm(struct thread_map *map, int thread) · 18 unmodified lines
55}57}
56 58
57void thread_map__read_comms(struct thread_map *threads);59void thread_map__read_comms(struct thread_map *threads);
60bool thread_map__has(struct thread_map *threads, pid_t pid);
58#endif /* __PERF_THREAD_MAP_H */61#endif /* __PERF_THREAD_MAP_H */
tools/perf/util/tool.h+1−0
@@ -57,6 +57,7 @@ struct perf_tool { · 56 unmodified lines
57 id_index,57 id_index,
58 auxtrace_info,58 auxtrace_info,
59 auxtrace_error,59 auxtrace_error,
60 time_conv,
60 thread_map,61 thread_map,
61 cpu_map,62 cpu_map,
62 stat_config,63 stat_config,
tools/perf/util/trigger.h+94−0
@@ -0,0 +1,94 @@
1#ifndef __TRIGGER_H_
2#define __TRIGGER_H_ 1
3
4#include "util/debug.h"
5#include "asm/bug.h"
6
7/*
8 * Use trigger to model operations which need to be executed when
9 * an event (a signal, for example) is observed.
10 *
11 * States and transits:
12 *
13 *
14 * OFF--(on)--> READY --(hit)--> HIT
15 * ^ |
16 * | (ready)
17 * | |
18 * \_____________/
19 *
20 * is_hit and is_ready are two key functions to query the state of
21 * a trigger. is_hit means the event already happen; is_ready means the
22 * trigger is waiting for the event.
23 */
24
25struct trigger {
26 volatile enum {
27 TRIGGER_ERROR = -2,
28 TRIGGER_OFF = -1,
29 TRIGGER_READY = 0,
30 TRIGGER_HIT = 1,
31 } state;
32 const char *name;
33};
34
35#define TRIGGER_WARN_ONCE(t, exp) \
36 WARN_ONCE(t->state != exp, "trigger '%s' state transist error: %d in %s()\n", \
37 t->name, t->state, __func__)
38
39static inline bool trigger_is_available(struct trigger *t)
40{
41 return t->state >= 0;
42}
43
44static inline bool trigger_is_error(struct trigger *t)
45{
46 return t->state <= TRIGGER_ERROR;
47}
48
49static inline void trigger_on(struct trigger *t)
50{
51 TRIGGER_WARN_ONCE(t, TRIGGER_OFF);
52 t->state = TRIGGER_READY;
53}
54
55static inline void trigger_ready(struct trigger *t)
56{
57 if (!trigger_is_available(t))
58 return;
59 t->state = TRIGGER_READY;
60}
61
62static inline void trigger_hit(struct trigger *t)
63{
64 if (!trigger_is_available(t))
65 return;
66 TRIGGER_WARN_ONCE(t, TRIGGER_READY);
67 t->state = TRIGGER_HIT;
68}
69
70static inline void trigger_off(struct trigger *t)
71{
72 if (!trigger_is_available(t))
73 return;
74 t->state = TRIGGER_OFF;
75}
76
77static inline void trigger_error(struct trigger *t)
78{
79 t->state = TRIGGER_ERROR;
80}
81
82static inline bool trigger_is_ready(struct trigger *t)
83{
84 return t->state == TRIGGER_READY;
85}
86
87static inline bool trigger_is_hit(struct trigger *t)
88{
89 return t->state == TRIGGER_HIT;
90}
91
92#define DEFINE_TRIGGER(n) \
93struct trigger n = {.state = TRIGGER_OFF, .name = #n}
94#endif
tools/perf/util/tsc.h+20−1
@@ -3,10 +3,29 @@ · 2 unmodified lines
3 3
4#include <linux/types.h>4#include <linux/types.h>
5 5
6#include "../arch/x86/util/tsc.h"6#include "event.h"
7
8struct perf_tsc_conversion {
9 u16 time_shift;
10 u32 time_mult;
11 u64 time_zero;
12};
13struct perf_event_mmap_page;
14
15int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
16 struct perf_tsc_conversion *tc);
7 17
8u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);18u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
9u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);19u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);
10u64 rdtsc(void);20u64 rdtsc(void);
11 21
22struct perf_event_mmap_page;
23struct perf_tool;
24struct machine;
25
26int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc,
27 struct perf_tool *tool,
28 perf_event__handler_t process,
29 struct machine *machine);
30
12#endif31#endif
tools/perf/util/unwind-libunwind.c+9−16
@@ -32,6 +32,7 @@ · 31 unmodified lines
32#include "symbol.h"32#include "symbol.h"
33#include "util.h"33#include "util.h"
34#include "debug.h"34#include "debug.h"
35#include "asm/bug.h"
35 36
36extern int37extern int
37UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,38UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
@@ -580,43 +581,33 @@ static unw_accessors_t accessors = { · 542 unmodified lines
580 581
581int unwind__prepare_access(struct thread *thread)582int unwind__prepare_access(struct thread *thread)
582{583{
583 unw_addr_space_t addr_space;
584
585 if (callchain_param.record_mode != CALLCHAIN_DWARF)584 if (callchain_param.record_mode != CALLCHAIN_DWARF)
586 return 0;585 return 0;
587 586
588 addr_space = unw_create_addr_space(&accessors, 0);587 thread->addr_space = unw_create_addr_space(&accessors, 0);
589 if (!addr_space) {588 if (!thread->addr_space) {
590 pr_err("unwind: Can't create unwind address space.\n");589 pr_err("unwind: Can't create unwind address space.\n");
591 return -ENOMEM;590 return -ENOMEM;
592 }591 }
593 592
594 unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);593 unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
595 thread__set_priv(thread, addr_space);
596
597 return 0;594 return 0;
598}595}
599 596
600void unwind__flush_access(struct thread *thread)597void unwind__flush_access(struct thread *thread)
601{598{
602 unw_addr_space_t addr_space;
603
604 if (callchain_param.record_mode != CALLCHAIN_DWARF)599 if (callchain_param.record_mode != CALLCHAIN_DWARF)
605 return;600 return;
606 601
607 addr_space = thread__priv(thread);602 unw_flush_cache(thread->addr_space, 0, 0);
608 unw_flush_cache(addr_space, 0, 0);
609}603}
610 604
611void unwind__finish_access(struct thread *thread)605void unwind__finish_access(struct thread *thread)
612{606{
613 unw_addr_space_t addr_space;
614
615 if (callchain_param.record_mode != CALLCHAIN_DWARF)607 if (callchain_param.record_mode != CALLCHAIN_DWARF)
616 return;608 return;
617 609
618 addr_space = thread__priv(thread);610 unw_destroy_addr_space(thread->addr_space);
619 unw_destroy_addr_space(addr_space);
620}611}
621 612
622static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,613static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
@@ -639,7 +630,9 @@ static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb, · 16 unmodified lines
639 * unwind itself.630 * unwind itself.
640 */631 */
641 if (max_stack - 1 > 0) {632 if (max_stack - 1 > 0) {
642 addr_space = thread__priv(ui->thread);633 WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
634 addr_space = ui->thread->addr_space;
635
643 if (addr_space == NULL)636 if (addr_space == NULL)
644 return -1;637 return -1;
645 638
tools/perf/util/util.c+36−2
@@ -33,6 +33,8 @@ struct callchain_param callchain_param = { · 32 unmodified lines
33unsigned int page_size;33unsigned int page_size;
34int cacheline_size;34int cacheline_size;
35 35
36unsigned int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
37
36bool test_attr__enabled;38bool test_attr__enabled;
37 39
38bool perf_host = true;40bool perf_host = true;
@@ -117,6 +119,40 @@ int rm_rf(char *path) · 78 unmodified lines
117 return rmdir(path);119 return rmdir(path);
118}120}
119 121
122/* A filter which removes dot files */
123bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
124{
125 return d->d_name[0] != '.';
126}
127
128/* lsdir reads a directory and store it in strlist */
129struct strlist *lsdir(const char *name,
130 bool (*filter)(const char *, struct dirent *))
131{
132 struct strlist *list = NULL;
133 DIR *dir;
134 struct dirent *d;
135
136 dir = opendir(name);
137 if (!dir)
138 return NULL;
139
140 list = strlist__new(NULL, NULL);
141 if (!list) {
142 errno = ENOMEM;
143 goto out;
144 }
145
146 while ((d = readdir(dir)) != NULL) {
147 if (!filter || filter(name, d))
148 strlist__add(list, d->d_name);
149 }
150
151out:
152 closedir(dir);
153 return list;
154}
155
120static int slow_copyfile(const char *from, const char *to)156static int slow_copyfile(const char *from, const char *to)
121{157{
122 int err = -1;158 int err = -1;
@@ -471,7 +507,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) · 348 unmodified lines
471 "needed for --call-graph fp\n");507 "needed for --call-graph fp\n");
472 break;508 break;
473 509
474#ifdef HAVE_DWARF_UNWIND_SUPPORT
475 /* Dwarf style */510 /* Dwarf style */
476 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {511 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
477 const unsigned long default_stack_dump_size = 8192;512 const unsigned long default_stack_dump_size = 8192;
@@ -487,7 +522,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param) · 9 unmodified lines
487 ret = get_stack_size(tok, &size);522 ret = get_stack_size(tok, &size);
488 param->dump_size = size;523 param->dump_size = size;
489 }524 }
490#endif /* HAVE_DWARF_UNWIND_SUPPORT */
491 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {525 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
492 if (!strtok_r(NULL, ",", &saveptr)) {526 if (!strtok_r(NULL, ",", &saveptr)) {
493 param->record_mode = CALLCHAIN_LBR;527 param->record_mode = CALLCHAIN_LBR;
tools/perf/util/util.h+9−6
@@ -79,6 +79,7 @@ · 78 unmodified lines
79#include <termios.h>79#include <termios.h>
80#include <linux/bitops.h>80#include <linux/bitops.h>
81#include <termios.h>81#include <termios.h>
82#include "strlist.h"
82 83
83extern const char *graph_line;84extern const char *graph_line;
84extern const char *graph_dotted_line;85extern const char *graph_dotted_line;
@@ -159,12 +160,6 @@ static inline char *gitstrchrnul(const char *s, int c) · 74 unmodified lines
159}160}
160#endif161#endif
161 162
162/*
163 * Wrappers:
164 */
165void *xrealloc(void *ptr, size_t size) __attribute__((weak));
166
167
168static inline void *zalloc(size_t size)163static inline void *zalloc(size_t size)
169{164{
170 return calloc(1, size);165 return calloc(1, size);
@@ -222,6 +217,8 @@ static inline int sane_case(int x, int high) · 51 unmodified lines
222 217
223int mkdir_p(char *path, mode_t mode);218int mkdir_p(char *path, mode_t mode);
224int rm_rf(char *path);219int rm_rf(char *path);
220struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *));
221bool lsdir_no_dot_filter(const char *name, struct dirent *d);
225int copyfile(const char *from, const char *to);222int copyfile(const char *from, const char *to);
226int copyfile_mode(const char *from, const char *to, mode_t mode);223int copyfile_mode(const char *from, const char *to, mode_t mode);
227int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);224int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
@@ -254,11 +251,17 @@ int hex2u64(const char *ptr, u64 *val); · 26 unmodified lines
254char *ltrim(char *s);251char *ltrim(char *s);
255char *rtrim(char *s);252char *rtrim(char *s);
256 253
254static inline char *trim(char *s)
255{
256 return ltrim(rtrim(s));
257}
258
257void dump_stack(void);259void dump_stack(void);
258void sighandler_dump_stack(int sig);260void sighandler_dump_stack(int sig);
259 261
260extern unsigned int page_size;262extern unsigned int page_size;
261extern int cacheline_size;263extern int cacheline_size;
264extern unsigned int sysctl_perf_event_max_stack;
262 265
263struct parse_tag {266struct parse_tag {
264 char tag;267 char tag;
tools/perf/util/wrapper.c+0−29
@@ -1,29 +0,0 @@
1/*
2 * Various trivial helper wrappers around standard functions
3 */
4#include "cache.h"
5
6/*
7 * There's no pack memory to release - but stay close to the Git
8 * version so wrap this away:
9 */
10static inline void release_pack_memory(size_t size __maybe_unused,
11 int flag __maybe_unused)
12{
13}
14
15void *xrealloc(void *ptr, size_t size)
16{
17 void *ret = realloc(ptr, size);
18 if (!ret && !size)
19 ret = realloc(ptr, 1);
20 if (!ret) {
21 release_pack_memory(size, -1);
22 ret = realloc(ptr, size);
23 if (!ret && !size)
24 ret = realloc(ptr, 1);
25 if (!ret)
26 die("Out of memory, realloc failed");
27 }
28 return ret;
29}