aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/.gitignore1
-rw-r--r--tools/perf/Documentation/android.txt16
-rw-r--r--tools/perf/Documentation/intel-pt.txt7
-rw-r--r--tools/perf/Documentation/itrace.txt8
-rw-r--r--tools/perf/Documentation/perf-annotate.txt9
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt3
-rw-r--r--tools/perf/Documentation/perf-data.txt4
-rw-r--r--tools/perf/Documentation/perf-diff.txt2
-rw-r--r--tools/perf/Documentation/perf-list.txt107
-rw-r--r--tools/perf/Documentation/perf-mem.txt11
-rw-r--r--tools/perf/Documentation/perf-probe.txt42
-rw-r--r--tools/perf/Documentation/perf-record.txt45
-rw-r--r--tools/perf/Documentation/perf-report.txt12
-rw-r--r--tools/perf/Documentation/perf-sched.txt16
-rw-r--r--tools/perf/Documentation/perf-script.txt49
-rw-r--r--tools/perf/Documentation/perf-stat.txt32
-rw-r--r--tools/perf/Documentation/perf-test.txt4
-rw-r--r--tools/perf/Documentation/perf-top.txt2
-rw-r--r--tools/perf/Documentation/perf-trace.txt33
-rw-r--r--tools/perf/Documentation/perf.data-file-format.txt442
-rw-r--r--tools/perf/MANIFEST54
-rw-r--r--tools/perf/Makefile.config (renamed from tools/perf/config/Makefile)98
-rw-r--r--tools/perf/Makefile.perf108
-rw-r--r--tools/perf/arch/arm/util/Build2
-rw-r--r--tools/perf/arch/arm64/util/Build2
-rw-r--r--tools/perf/arch/arm64/util/unwind-libunwind.c4
-rw-r--r--tools/perf/arch/common.c20
-rw-r--r--tools/perf/arch/common.h1
-rw-r--r--tools/perf/arch/powerpc/Makefile1
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h69
-rw-r--r--tools/perf/arch/powerpc/util/Build2
-rw-r--r--tools/perf/arch/powerpc/util/dwarf-regs.c40
-rw-r--r--tools/perf/arch/powerpc/util/perf_regs.c49
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c68
-rw-r--r--tools/perf/arch/powerpc/util/unwind-libunwind.c96
-rw-r--r--tools/perf/arch/s390/util/Build2
-rw-r--r--tools/perf/arch/s390/util/machine.c19
-rw-r--r--tools/perf/arch/x86/Makefile23
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl378
-rwxr-xr-xtools/perf/arch/x86/entry/syscalls/syscalltbl.sh39
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-32.c1020
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-64.c942
-rw-r--r--tools/perf/arch/x86/tests/insn-x86-dat-src.c1793
-rw-r--r--tools/perf/arch/x86/tests/perf-time-to-tsc.c8
-rw-r--r--tools/perf/arch/x86/tests/rdpmc.c8
-rw-r--r--tools/perf/arch/x86/util/Build3
-rw-r--r--tools/perf/arch/x86/util/auxtrace.c2
-rw-r--r--tools/perf/arch/x86/util/group.c27
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c13
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c21
-rw-r--r--tools/perf/arch/x86/util/tsc.c34
-rw-r--r--tools/perf/arch/x86/util/tsc.h17
-rw-r--r--tools/perf/arch/x86/util/unwind-libunwind.c6
-rw-r--r--tools/perf/bench/futex-hash.c15
-rw-r--r--tools/perf/bench/futex-lock-pi.c13
-rw-r--r--tools/perf/bench/futex-requeue.c11
-rw-r--r--tools/perf/bench/futex-wake-parallel.c11
-rw-r--r--tools/perf/bench/futex-wake.c11
-rw-r--r--tools/perf/bench/futex.h6
-rw-r--r--tools/perf/bench/mem-functions.c22
-rw-r--r--tools/perf/bench/mem-memcpy-x86-64-asm.S2
-rw-r--r--tools/perf/bench/mem-memset-x86-64-asm.S2
-rw-r--r--tools/perf/bench/numa.c4
-rw-r--r--tools/perf/builtin-annotate.c12
-rw-r--r--tools/perf/builtin-buildid-cache.c29
-rw-r--r--tools/perf/builtin-config.c36
-rw-r--r--tools/perf/builtin-data.c11
-rw-r--r--tools/perf/builtin-diff.c38
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c28
-rw-r--r--tools/perf/builtin-inject.c9
-rw-r--r--tools/perf/builtin-kmem.c7
-rw-r--r--tools/perf/builtin-kvm.c14
-rw-r--r--tools/perf/builtin-list.c6
-rw-r--r--tools/perf/builtin-mem.c15
-rw-r--r--tools/perf/builtin-probe.c38
-rw-r--r--tools/perf/builtin-record.c536
-rw-r--r--tools/perf/builtin-report.c40
-rw-r--r--tools/perf/builtin-sched.c200
-rw-r--r--tools/perf/builtin-script.c208
-rw-r--r--tools/perf/builtin-stat.c260
-rw-r--r--tools/perf/builtin-timechart.c5
-rw-r--r--tools/perf/builtin-top.c69
-rw-r--r--tools/perf/builtin-trace.c1368
-rw-r--r--tools/perf/jvmti/jvmti_agent.c53
-rw-r--r--tools/perf/perf-sys.h19
-rw-r--r--tools/perf/perf.c77
-rw-r--r--tools/perf/perf.h4
-rwxr-xr-xtools/perf/python/tracepoint.py47
-rw-r--r--tools/perf/scripts/perl/Perf-Trace-Util/Build4
-rwxr-xr-xtools/perf/scripts/python/bin/stackcollapse-record8
-rwxr-xr-xtools/perf/scripts/python/bin/stackcollapse-report3
-rw-r--r--tools/perf/scripts/python/export-to-postgresql.py52
-rw-r--r--tools/perf/scripts/python/netdev-times.py11
-rwxr-xr-xtools/perf/scripts/python/stackcollapse.py125
-rw-r--r--tools/perf/tests/Build5
-rw-r--r--tools/perf/tests/backward-ring-buffer.c151
-rw-r--r--tools/perf/tests/bitmap.c53
-rw-r--r--tools/perf/tests/bpf-script-example.c4
-rw-r--r--tools/perf/tests/bpf.c12
-rw-r--r--tools/perf/tests/builtin-test.c81
-rw-r--r--tools/perf/tests/code-reading.c102
-rw-r--r--tools/perf/tests/cpumap.c31
-rw-r--r--tools/perf/tests/dso-data.c8
-rw-r--r--tools/perf/tests/event-times.c235
-rw-r--r--tools/perf/tests/event_update.c2
-rw-r--r--tools/perf/tests/evsel-roundtrip-name.c2
-rw-r--r--tools/perf/tests/fdarray.c9
-rw-r--r--tools/perf/tests/hists_common.c2
-rw-r--r--tools/perf/tests/hists_cumulate.c8
-rw-r--r--tools/perf/tests/hists_filter.c6
-rw-r--r--tools/perf/tests/hists_link.c12
-rw-r--r--tools/perf/tests/hists_output.c4
-rw-r--r--tools/perf/tests/is_printable_array.c36
-rw-r--r--tools/perf/tests/keep-tracking.c2
-rw-r--r--tools/perf/tests/kmod-path.c1
-rw-r--r--tools/perf/tests/llvm.c1
-rw-r--r--tools/perf/tests/make5
-rw-r--r--tools/perf/tests/mmap-basic.c11
-rw-r--r--tools/perf/tests/openat-syscall-all-cpus.c9
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c13
-rw-r--r--tools/perf/tests/openat-syscall.c2
-rw-r--r--tools/perf/tests/parse-events.c8
-rw-r--r--tools/perf/tests/parse-no-sample-id-all.c3
-rw-r--r--tools/perf/tests/perf-record.c13
-rw-r--r--tools/perf/tests/sdt.c115
-rw-r--r--tools/perf/tests/sw-clock.c4
-rw-r--r--tools/perf/tests/switch-tracking.c4
-rw-r--r--tools/perf/tests/task-exit.c4
-rw-r--r--tools/perf/tests/tests.h6
-rw-r--r--tools/perf/tests/thread-map.c16
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c11
-rw-r--r--tools/perf/trace/beauty/eventfd.c36
-rw-r--r--tools/perf/trace/beauty/flock.c48
-rw-r--r--tools/perf/trace/beauty/futex_op.c60
-rw-r--r--tools/perf/trace/beauty/mmap.c191
-rw-r--r--tools/perf/trace/beauty/mode_t.c68
-rw-r--r--tools/perf/trace/beauty/msg_flags.c61
-rw-r--r--tools/perf/trace/beauty/open_flags.c71
-rw-r--r--tools/perf/trace/beauty/perf_event_open.c43
-rw-r--r--tools/perf/trace/beauty/pid.c21
-rw-r--r--tools/perf/trace/beauty/sched_policy.c47
-rw-r--r--tools/perf/trace/beauty/seccomp.c50
-rw-r--r--tools/perf/trace/beauty/signum.c53
-rw-r--r--tools/perf/trace/beauty/socket_type.c60
-rw-r--r--tools/perf/trace/beauty/waitid_options.c26
-rw-r--r--tools/perf/ui/browser.c2
-rw-r--r--tools/perf/ui/browsers/annotate.c30
-rw-r--r--tools/perf/ui/browsers/hists.c190
-rw-r--r--tools/perf/ui/browsers/hists.h32
-rw-r--r--tools/perf/ui/gtk/annotate.c8
-rw-r--r--tools/perf/ui/gtk/hists.c6
-rw-r--r--tools/perf/ui/gtk/util.c1
-rw-r--r--tools/perf/ui/helpline.c1
-rw-r--r--tools/perf/ui/hist.c15
-rw-r--r--tools/perf/ui/setup.c7
-rw-r--r--tools/perf/ui/stdio/hist.c136
-rw-r--r--tools/perf/ui/tui/setup.c2
-rw-r--r--tools/perf/ui/ui.h4
-rw-r--r--tools/perf/util/Build17
-rw-r--r--tools/perf/util/alias.c2
-rw-r--r--tools/perf/util/annotate.c177
-rw-r--r--tools/perf/util/annotate.h23
-rw-r--r--tools/perf/util/auxtrace.c7
-rw-r--r--tools/perf/util/auxtrace.h4
-rw-r--r--tools/perf/util/bpf-loader.c328
-rw-r--r--tools/perf/util/bpf-loader.h31
-rw-r--r--tools/perf/util/build-id.c356
-rw-r--r--tools/perf/util/build-id.h8
-rw-r--r--tools/perf/util/cache.h42
-rw-r--r--tools/perf/util/call-path.c122
-rw-r--r--tools/perf/util/call-path.h77
-rw-r--r--tools/perf/util/callchain.c9
-rw-r--r--tools/perf/util/callchain.h11
-rw-r--r--tools/perf/util/cgroup.c4
-rw-r--r--tools/perf/util/cloexec.c18
-rw-r--r--tools/perf/util/color.c4
-rw-r--r--tools/perf/util/config.c300
-rw-r--r--tools/perf/util/config.h66
-rw-r--r--tools/perf/util/cpumap.c76
-rw-r--r--tools/perf/util/cpumap.h5
-rw-r--r--tools/perf/util/data-convert-bt.c241
-rw-r--r--tools/perf/util/data-convert-bt.h4
-rw-r--r--tools/perf/util/data-convert.h9
-rw-r--r--tools/perf/util/data.c45
-rw-r--r--tools/perf/util/data.h11
-rw-r--r--tools/perf/util/db-export.c101
-rw-r--r--tools/perf/util/db-export.h3
-rw-r--r--tools/perf/util/debug.h2
-rw-r--r--tools/perf/util/demangle-rust.c269
-rw-r--r--tools/perf/util/demangle-rust.h7
-rw-r--r--tools/perf/util/dso.c39
-rw-r--r--tools/perf/util/dso.h8
-rw-r--r--tools/perf/util/dwarf-aux.c52
-rw-r--r--tools/perf/util/env.c5
-rw-r--r--tools/perf/util/env.h10
-rw-r--r--tools/perf/util/event.c5
-rw-r--r--tools/perf/util/event.h9
-rw-r--r--tools/perf/util/evlist.c552
-rw-r--r--tools/perf/util/evlist.h112
-rw-r--r--tools/perf/util/evsel.c254
-rw-r--r--tools/perf/util/evsel.h56
-rw-r--r--tools/perf/util/evsel_fprintf.c212
-rw-r--r--tools/perf/util/group.h7
-rw-r--r--tools/perf/util/header.c115
-rw-r--r--tools/perf/util/help-unknown-cmd.c32
-rw-r--r--tools/perf/util/hist.c275
-rw-r--r--tools/perf/util/hist.h50
-rw-r--r--tools/perf/util/include/asm/alternative-asm.h9
-rw-r--r--tools/perf/util/include/asm/byteorder.h2
-rw-r--r--tools/perf/util/include/asm/unistd_32.h1
-rw-r--r--tools/perf/util/include/asm/unistd_64.h1
-rw-r--r--tools/perf/util/include/linux/const.h1
-rw-r--r--tools/perf/util/intel-bts.c29
-rw-r--r--tools/perf/util/intel-pt-decoder/Build5
-rw-r--r--tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk11
-rw-r--r--tools/perf/util/intel-pt-decoder/inat.h17
-rw-r--r--tools/perf/util/intel-pt-decoder/insn.c18
-rw-r--r--tools/perf/util/intel-pt-decoder/insn.h12
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.c46
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c24
-rw-r--r--tools/perf/util/intel-pt-decoder/x86-opcode-map.txt265
-rw-r--r--tools/perf/util/intel-pt.c48
-rw-r--r--tools/perf/util/intlist.h8
-rw-r--r--tools/perf/util/jitdump.c44
-rw-r--r--tools/perf/util/jitdump.h3
-rw-r--r--tools/perf/util/levenshtein.c4
-rw-r--r--tools/perf/util/libunwind/arm64.c40
-rw-r--r--tools/perf/util/libunwind/x86_32.c43
-rw-r--r--tools/perf/util/llvm-utils.c53
-rw-r--r--tools/perf/util/llvm-utils.h5
-rw-r--r--tools/perf/util/machine.c164
-rw-r--r--tools/perf/util/machine.h9
-rw-r--r--tools/perf/util/map.c28
-rw-r--r--tools/perf/util/map.h2
-rw-r--r--tools/perf/util/mem-events.c17
-rw-r--r--tools/perf/util/mem-events.h1
-rw-r--r--tools/perf/util/ordered-events.c9
-rw-r--r--tools/perf/util/ordered-events.h1
-rw-r--r--tools/perf/util/parse-events.c144
-rw-r--r--tools/perf/util/parse-events.h7
-rw-r--r--tools/perf/util/parse-events.l4
-rw-r--r--tools/perf/util/path.c67
-rw-r--r--tools/perf/util/perf_regs.c8
-rw-r--r--tools/perf/util/pmu.c23
-rw-r--r--tools/perf/util/probe-event.c986
-rw-r--r--tools/perf/util/probe-event.h17
-rw-r--r--tools/perf/util/probe-file.c580
-rw-r--r--tools/perf/util/probe-file.h42
-rw-r--r--tools/perf/util/probe-finder.c55
-rw-r--r--tools/perf/util/python-ext-sources2
-rw-r--r--tools/perf/util/python.c152
-rw-r--r--tools/perf/util/quote.c40
-rw-r--r--tools/perf/util/quote.h5
-rw-r--r--tools/perf/util/rb_resort.h149
-rw-r--r--tools/perf/util/record.c13
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c125
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c76
-rw-r--r--tools/perf/util/session.c153
-rw-r--r--tools/perf/util/session.h12
-rw-r--r--tools/perf/util/sort.c161
-rw-r--r--tools/perf/util/sort.h15
-rw-r--r--tools/perf/util/stat-shadow.c170
-rw-r--r--tools/perf/util/stat.c15
-rw-r--r--tools/perf/util/stat.h5
-rw-r--r--tools/perf/util/strbuf.c95
-rw-r--r--tools/perf/util/strbuf.h28
-rw-r--r--tools/perf/util/strlist.h4
-rw-r--r--tools/perf/util/symbol-elf.c294
-rw-r--r--tools/perf/util/symbol.c222
-rw-r--r--tools/perf/util/symbol.h48
-rw-r--r--tools/perf/util/symbol_fprintf.c71
-rw-r--r--tools/perf/util/syscalltbl.c134
-rw-r--r--tools/perf/util/syscalltbl.h20
-rw-r--r--tools/perf/util/target.c7
-rw-r--r--tools/perf/util/thread-stack.c146
-rw-r--r--tools/perf/util/thread-stack.h32
-rw-r--r--tools/perf/util/thread.c82
-rw-r--r--tools/perf/util/thread.h11
-rw-r--r--tools/perf/util/thread_map.c18
-rw-r--r--tools/perf/util/thread_map.h3
-rw-r--r--tools/perf/util/tool.h1
-rw-r--r--tools/perf/util/top.h1
-rw-r--r--tools/perf/util/trace-event.c8
-rw-r--r--tools/perf/util/trace-event.h2
-rw-r--r--tools/perf/util/trigger.h94
-rw-r--r--tools/perf/util/tsc.h21
-rw-r--r--tools/perf/util/unwind-libdw.c2
-rw-r--r--tools/perf/util/unwind-libunwind-local.c699
-rw-r--r--tools/perf/util/unwind-libunwind.c702
-rw-r--r--tools/perf/util/unwind.h34
-rw-r--r--tools/perf/util/util.c87
-rw-r--r--tools/perf/util/util.h23
-rw-r--r--tools/perf/util/vdso.c40
-rw-r--r--tools/perf/util/wrapper.c29
295 files changed, 18016 insertions, 4565 deletions
diff --git a/tools/perf/.gitignore b/tools/perf/.gitignore
index 3d1bb802dbf4..3db3db9278be 100644
--- a/tools/perf/.gitignore
+++ b/tools/perf/.gitignore
@@ -30,3 +30,4 @@ config.mak.autogen
30*.pyo 30*.pyo
31.config-detected 31.config-detected
32util/intel-pt-decoder/inat-tables.c 32util/intel-pt-decoder/inat-tables.c
33arch/*/include/generated/
diff --git a/tools/perf/Documentation/android.txt b/tools/perf/Documentation/android.txt
index 8484c3a04a6a..24a59998fc91 100644
--- a/tools/perf/Documentation/android.txt
+++ b/tools/perf/Documentation/android.txt
@@ -12,14 +12,14 @@ Set the NDK variable to point to the path where you installed the NDK:
12 12
132. Set cross-compiling environment variables for NDK toolchain and sysroot. 132. Set cross-compiling environment variables for NDK toolchain and sysroot.
14For arm: 14For arm:
15 export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi- 15 export NDK_TOOLCHAIN=${NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-
16 export NDK_SYSROOT=${NDK}/platforms/android-9/arch-arm 16 export NDK_SYSROOT=${NDK}/platforms/android-24/arch-arm
17For x86: 17For x86:
18 export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.6/prebuilt/linux-x86/bin/i686-linux-android- 18 export NDK_TOOLCHAIN=${NDK}/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/i686-linux-android-
19 export NDK_SYSROOT=${NDK}/platforms/android-9/arch-x86 19 export NDK_SYSROOT=${NDK}/platforms/android-24/arch-x86
20 20
21This method is not working for Android NDK versions up to Revision 8b. 21This method is only tested for Android NDK versions Revision 11b and later.
22perf uses some bionic enhancements that are not included in these NDK versions. 22perf uses some bionic enhancements that are not included in prior NDK versions.
23You can use method (b) described below instead. 23You can use method (b) described below instead.
24 24
25(b). Use the Android source tree 25(b). Use the Android source tree
@@ -49,9 +49,9 @@ II. Compile perf for Android
49------------------------------------------------ 49------------------------------------------------
50You need to run make with the NDK toolchain and sysroot defined above: 50You need to run make with the NDK toolchain and sysroot defined above:
51For arm: 51For arm:
52 make ARCH=arm CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" 52 make WERROR=0 ARCH=arm CROSS_COMPILE=${NDK_TOOLCHAIN} EXTRA_CFLAGS="-pie --sysroot=${NDK_SYSROOT}"
53For x86: 53For x86:
54 make ARCH=x86 CROSS_COMPILE=${NDK_TOOLCHAIN} CFLAGS="--sysroot=${NDK_SYSROOT}" 54 make WERROR=0 ARCH=x86 CROSS_COMPILE=${NDK_TOOLCHAIN} EXTRA_CFLAGS="-pie --sysroot=${NDK_SYSROOT}"
55 55
56III. Install perf 56III. Install perf
57----------------------------------------------- 57-----------------------------------------------
diff --git a/tools/perf/Documentation/intel-pt.txt b/tools/perf/Documentation/intel-pt.txt
index be764f9ec769..c6c8318e38a2 100644
--- a/tools/perf/Documentation/intel-pt.txt
+++ b/tools/perf/Documentation/intel-pt.txt
@@ -672,6 +672,7 @@ The letters are:
672 d create a debug log 672 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 -e 677"Instructions" events look like they were recorded by "perf record -e
677instructions". 678instructions".
@@ -730,6 +731,12 @@ from one sample to the next.
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 option 741dump option
735----------- 742-----------
diff --git a/tools/perf/Documentation/itrace.txt b/tools/perf/Documentation/itrace.txt
index 65453f4c7006..e2a4c5e0dbe5 100644
--- a/tools/perf/Documentation/itrace.txt
+++ b/tools/perf/Documentation/itrace.txt
@@ -7,6 +7,7 @@
7 d create a debug log 7 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=ibxe 12 The default is all events i.e. the same as --itrace=ibxe
12 13
@@ -24,3 +25,10 @@
24 25
25 Also the number of last branch entries (default 64, max. 1024) for 26 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.
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index e9cd39a92dc2..8ffbd272952d 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -33,7 +33,7 @@ OPTIONS
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::
@@ -61,6 +61,13 @@ OPTIONS
61 61
62--stdio:: Use the stdio interface. 62--stdio:: Use the stdio interface.
63 63
64--stdio-color::
65 'always', 'never' or 'auto', allowing configuring color output
66 via the command line, in addition to via "color.ui" .perfconfig.
67 Use '--stdio-color always' to generate color even when redirecting
68 to a pipe or file. Using just '--stdio-color' is equivalent to
69 using 'always'.
70
64--tui:: Use the TUI interface. Use of --tui requires a tty, if one is not 71--tui:: Use the TUI interface. Use of --tui requires a tty, if one is not
65 present, as when piping to other commands, the stdio interface is 72 present, as when piping to other commands, the stdio interface is
66 used. This interfaces starts by centering on the line with more 73 used. This interfaces starts by centering on the line with more
diff --git a/tools/perf/Documentation/perf-buildid-cache.txt b/tools/perf/Documentation/perf-buildid-cache.txt
index dd07b55f58d8..058064db39d2 100644
--- a/tools/perf/Documentation/perf-buildid-cache.txt
+++ b/tools/perf/Documentation/perf-buildid-cache.txt
@@ -15,6 +15,9 @@ DESCRIPTION
15This command manages the build-id cache. It can add, remove, update and purge 15This command manages the build-id cache. It can add, remove, update and purge
16files to/from the cache. In the future it should as well set upper limits for 16files to/from the cache. In the future it should as well set upper limits for
17the space used by the cache, etc. 17the space used by the cache, etc.
18This also scans the target binary for SDT (Statically Defined Tracing) and
19record it along with the buildid-cache, which will be used by perf-probe.
20For more details, see linkperf:perf-probe[1].
18 21
19OPTIONS 22OPTIONS
20------- 23-------
diff --git a/tools/perf/Documentation/perf-data.txt b/tools/perf/Documentation/perf-data.txt
index be8fa1a0a97e..f0796a47dfa3 100644
--- a/tools/perf/Documentation/perf-data.txt
+++ b/tools/perf/Documentation/perf-data.txt
@@ -34,6 +34,10 @@ OPTIONS for 'convert'
34--verbose:: 34--verbose::
35 Be more verbose (show counter open errors, etc). 35 Be more verbose (show counter open errors, etc).
36 36
37--all::
38 Convert all events, including non-sample events (comm, fork, ...), to output.
39 Default is off, only convert samples.
40
37SEE ALSO 41SEE ALSO
38-------- 42--------
39linkperf:perf[1] 43linkperf:perf[1]
diff --git a/tools/perf/Documentation/perf-diff.txt b/tools/perf/Documentation/perf-diff.txt
index d1deb573877f..3e9490b9c533 100644
--- a/tools/perf/Documentation/perf-diff.txt
+++ b/tools/perf/Documentation/perf-diff.txt
@@ -75,7 +75,7 @@ OPTIONS
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.
diff --git a/tools/perf/Documentation/perf-list.txt b/tools/perf/Documentation/perf-list.txt
index ec723d0a5bb3..a126e97a8114 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -93,6 +93,67 @@ raw encoding of 0x1A8 can be used:
93You should refer to the processor specific documentation for getting these 93You 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 EVENTS 157PARAMETERIZED EVENTS
97-------------------- 158--------------------
98 159
@@ -106,6 +167,50 @@ also be supplied. For example:
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
109OPTIONS 214OPTIONS
110------- 215-------
111 216
@@ -143,5 +248,5 @@ SEE ALSO
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]
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 43310d8661fe..73496320fca3 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -48,6 +48,17 @@ OPTIONS
48 option can be passed in record mode. It will be interpreted the same way as perf 48 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
59--ldload::
60 Specify desired latency for loads event.
61
51SEE ALSO 62SEE ALSO
52-------- 63--------
53linkperf:perf-record[1], linkperf:perf-report[1] 64linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/Documentation/perf-probe.txt b/tools/perf/Documentation/perf-probe.txt
index 3a8a9ba2b041..b303bcdd8ed1 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -67,7 +67,10 @@ OPTIONS
67 67
68-l:: 68-l::
69--list[=[GROUP:]EVENT]:: 69--list[=[GROUP:]EVENT]::
70 List up current probe events. This can also accept filtering patterns of event names. 70 List up current probe events. This can also accept filtering patterns of
71 event names.
72 When this is used with --cache, perf shows all cached probes instead of
73 the live probes.
71 74
72-L:: 75-L::
73--line=:: 76--line=::
@@ -109,6 +112,12 @@ OPTIONS
109 Dry run. With this option, --add and --del doesn't execute actual 112 Dry run. With this option, --add and --del doesn't execute actual
110 adding and removal operations. 113 adding and removal operations.
111 114
115--cache::
116 (With --add) Cache the probes. Any events which successfully added
117 are also stored in the cache file.
118 (With --list) Show cached probes.
119 (With --del) Remove cached probes.
120
112--max-probes=NUM:: 121--max-probes=NUM::
113 Set the maximum number of probe points for an event. Default is 128. 122 Set the maximum number of probe points for an event. Default is 128.
114 123
@@ -134,19 +143,30 @@ PROBE SYNTAX
134Probe points are defined by following syntax. 143Probe points are defined by following syntax.
135 144
136 1) Define event based on function name 145 1) Define event based on function name
137 [EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...] 146 [[GROUP:]EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...]
138 147
139 2) Define event based on source file with line number 148 2) Define event based on source file with line number
140 [EVENT=]SRC:ALN [ARG ...] 149 [[GROUP:]EVENT=]SRC:ALN [ARG ...]
141 150
142 3) Define event based on source file with lazy pattern 151 3) Define event based on source file with lazy pattern
143 [EVENT=]SRC;PTN [ARG ...] 152 [[GROUP:]EVENT=]SRC;PTN [ARG ...]
144 153
154 4) Pre-defined SDT events or cached event with name
155 %[sdt_PROVIDER:]SDTEVENT
156 or,
157 sdt_PROVIDER:SDTEVENT
145 158
146'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. Currently, event group name is set as 'probe'. 159'EVENT' specifies the name of new event, if omitted, it will be set the name of the probed function. You can also specify a group name by 'GROUP', if omitted, set 'probe' is used for kprobe and 'probe_<bin>' is used for uprobe.
160Note that using existing group name can conflict with other events. Especially, using the group name reserved for kernel modules can hide embedded events in the
161modules.
147'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function. 162'FUNC' specifies a probed function name, and it may have one of the following options; '+OFFS' is the offset from function entry address in bytes, ':RLN' is the relative-line number from function entry line, and '%return' means that it probes function return. And ';PTN' means lazy matching pattern (see LAZY MATCHING). Note that ';PTN' must be the end of the probe point definition. In addition, '@SRC' specifies a source file which has that function.
148It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern. 163It is also possible to specify a probe point by the source line number or lazy matching by using 'SRC:ALN' or 'SRC;PTN' syntax, where 'SRC' is the source file path, ':ALN' is the line number and ';PTN' is the lazy matching pattern.
149'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT). 164'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT).
165'SDTEVENT' and 'PROVIDER' is the pre-defined event name which is defined by user SDT (Statically Defined Tracing) or the pre-cached probes with event name.
166Note that before using the SDT event, the target binary (on which SDT events are defined) must be scanned by linkperf:perf-buildid-cache[1] to make SDT events as cached events.
167
168For details of the SDT, see below.
169https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html
150 170
151PROBE ARGUMENT 171PROBE ARGUMENT
152-------------- 172--------------
@@ -156,10 +176,18 @@ Each probe argument follows below syntax.
156 176
157'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.) 177'NAME' specifies the name of this argument (optional). You can use the name of local variable, local data structure member (e.g. var->field, var.field2), local array with fixed index (e.g. array[1], var->array[0], var->pointer[2]), or kprobe-tracer argument format (e.g. $retval, %ax, etc). Note that the name of this argument will be set as the last member name if you specify a local data structure member (e.g. field2 for 'var->field1.field2'.)
158'$vars' and '$params' special arguments are also available for NAME, '$vars' is expanded to the local variables (including function parameters) which can access at given probe point. '$params' is expanded to only the function parameters. 178'$vars' and '$params' special arguments are also available for NAME, '$vars' is expanded to the local variables (including function parameters) which can access at given probe point. '$params' is expanded to only the function parameters.
159'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type. 179'TYPE' casts the type of this argument (optional). If omitted, perf probe automatically set the type based on debuginfo. Currently, basic types (u8/u16/u32/u64/s8/s16/s32/s64), signedness casting (u/s), "string" and bitfield are supported. (see TYPES for detail)
160 180
161On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid. 181On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
162 182
183TYPES
184-----
185Basic types (u8/u16/u32/u64/s8/s16/s32/s64) are integer types. Prefix 's' and 'u' means those types are signed and unsigned respectively. Traced arguments are shown in decimal (signed) or hex (unsigned). You can also use 's' or 'u' to specify only signedness and leave its size auto-detected by perf probe.
186String type is a special type, which fetches a "null-terminated" string from kernel space. This means it will fail and store NULL if the string container has been paged out. You can specify 'string' type only for the local variable or structure member which is an array of or a pointer to 'char' or 'unsigned char' type.
187Bitfield is another special type, which takes 3 parameters, bit-width, bit-offset, and container-size (usually 32). The syntax is;
188
189 b<bit-width>@<bit-offset>/<container-size>
190
163LINE SYNTAX 191LINE SYNTAX
164----------- 192-----------
165Line range is described by following syntax. 193Line range is described by following syntax.
@@ -226,4 +254,4 @@ Add probes at malloc() function on libc
226 254
227SEE ALSO 255SEE ALSO
228-------- 256--------
229linkperf:perf-trace[1], linkperf:perf-record[1] 257linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 19aa17532a16..379a2bed07c0 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -192,6 +192,9 @@ OPTIONS
192--period:: 192--period::
193 Record the sample period. 193 Record the sample period.
194 194
195--sample-cpu::
196 Record the sample cpu.
197
195-n:: 198-n::
196--no-samples:: 199--no-samples::
197 Don't sample. 200 Don't sample.
@@ -347,6 +350,48 @@ Configure all used events to run in kernel space.
347--all-user:: 350--all-user::
348Configure all used events to run in user space. 351Configure all used events to run in user space.
349 352
353--timestamp-filename
354Append timestamp to output file name.
355
356--switch-output::
357Generate multiple perf.data files, timestamp prefixed, switching to a new one
358when receiving a SIGUSR2.
359
360A possible use case is to, given an external event, slice the perf.data file
361that gets then processed, possibly via a perf script, to decide if that
362particular perf.data snapshot should be kept or not.
363
364Implies --timestamp-filename, --no-buildid and --no-buildid-cache.
365
366--dry-run::
367Parse options then exit. --dry-run can be used to detect errors in cmdline
368options.
369
370'perf record --dry-run -e' can act as a BPF script compiler if llvm.dump-obj
371in config file is set to true.
372
373--tail-synthesize::
374Instead of collecting non-sample events (for example, fork, comm, mmap) at
375the beginning of record, collect them during finalizing an output file.
376The collected non-sample events reflects the status of the system when
377record is finished.
378
379--overwrite::
380Makes all events use an overwritable ring buffer. An overwritable ring
381buffer works like a flight recorder: when it gets full, the kernel will
382overwrite the oldest records, that thus will never make it to the
383perf.data file.
384
385When '--overwrite' and '--switch-output' are used perf records and drops
386events until it receives a signal, meaning that something unusual was
387detected that warrants taking a snapshot of the most current events,
388those fitting in the ring buffer at that moment.
389
390'overwrite' attribute can also be set or canceled for an event using
391config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'.
392
393Implies --tail-synthesize.
394
350SEE ALSO 395SEE ALSO
351-------- 396--------
352linkperf:perf-stat[1], linkperf:perf-list[1] 397linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 12113992ac9d..2d1746295abf 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -103,12 +103,13 @@ OPTIONS
103 103
104 If --branch-stack option is used, following sort keys are also 104 If --branch-stack option is used, following sort keys are also
105 available: 105 available:
106 dso_from, dso_to, symbol_from, symbol_to, mispredict.
107 106
108 - dso_from: name of library or module branched from 107 - dso_from: name of library or module branched from
109 - dso_to: name of library or module branched to 108 - dso_to: name of library or module branched to
110 - symbol_from: name of function branched from 109 - symbol_from: name of function branched from
111 - symbol_to: name of function branched to 110 - symbol_to: name of function branched to
111 - srcline_from: source file and line branched from
112 - srcline_to: source file and line branched to
112 - mispredict: "N" for predicted branch, "Y" for mispredicted branch 113 - mispredict: "N" for predicted branch, "Y" for mispredicted branch
113 - in_tx: branch in TSX transaction 114 - in_tx: branch in TSX transaction
114 - abort: TSX transaction abort. 115 - abort: TSX transaction abort.
@@ -264,6 +265,13 @@ OPTIONS
264 265
265--stdio:: Use the stdio interface. 266--stdio:: Use the stdio interface.
266 267
268--stdio-color::
269 'always', 'never' or 'auto', allowing configuring color output
270 via the command line, in addition to via "color.ui" .perfconfig.
271 Use '--stdio-color always' to generate color even when redirecting
272 to a pipe or file. Using just '--stdio-color' is equivalent to
273 using 'always'.
274
267--tui:: Use the TUI interface, that is integrated with annotate and allows 275--tui:: Use the TUI interface, that is integrated with annotate and allows
268 zooming into DSOs or threads, among other features. Use of --tui 276 zooming into DSOs or threads, among other features. Use of --tui
269 requires a tty, if one is not present, as when piping to other 277 requires a tty, if one is not present, as when piping to other
@@ -285,7 +293,7 @@ OPTIONS
285 293
286-f:: 294-f::
287--force:: 295--force::
288 Don't complain, do it. 296 Don't do ownership validation.
289 297
290--symfs=<directory>:: 298--symfs=<directory>::
291 Look for files with symbols relative to this directory. 299 Look for files with symbols relative to this directory.
diff --git a/tools/perf/Documentation/perf-sched.txt b/tools/perf/Documentation/perf-sched.txt
index 8ff4df956951..1cc08cc47ac5 100644
--- a/tools/perf/Documentation/perf-sched.txt
+++ b/tools/perf/Documentation/perf-sched.txt
@@ -50,6 +50,22 @@ OPTIONS
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 ALSO 69SEE ALSO
54-------- 70--------
55linkperf:perf-record[1] 71linkperf:perf-record[1]
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 382ddfb45d1d..053bbbd84ece 100644
--- a/tools/perf/Documentation/perf-script.txt
+++ b/tools/perf/Documentation/perf-script.txt
@@ -116,16 +116,16 @@ OPTIONS
116--fields:: 116--fields::
117 Comma separated list of fields to print. Options are: 117 Comma separated list of fields to print. Options are:
118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff, 118 comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr, symoff,
119 srcline, period, iregs, brstack, brstacksym, flags. 119 srcline, period, iregs, brstack, brstacksym, flags, bpf-output,
120 Field list can be prepended with the type, trace, sw or hw, 120 callindent. Field list can be prepended with the type, trace, sw or hw,
121 to indicate to which event type the field list applies. 121 to indicate to which event type the field list applies.
122 e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace 122 e.g., -F sw:comm,tid,time,ip,sym and -F trace:time,cpu,trace
123 123
124 perf script -f <fields> 124 perf script -F <fields>
125 125
126 is equivalent to: 126 is equivalent to:
127 127
128 perf script -f trace:<fields> -f sw:<fields> -f hw:<fields> 128 perf script -F trace:<fields> -F sw:<fields> -F hw:<fields>
129 129
130 i.e., the specified fields apply to all event types if the type string 130 i.e., the specified fields apply to all event types if the type string
131 is not given. 131 is not given.
@@ -133,9 +133,9 @@ OPTIONS
133 The arguments are processed in the order received. A later usage can 133 The arguments are processed in the order received. A later usage can
134 reset a prior request. e.g.: 134 reset a prior request. e.g.:
135 135
136 -f trace: -f comm,tid,time,ip,sym 136 -F trace: -F comm,tid,time,ip,sym
137 137
138 The first -f suppresses trace events (field list is ""), but then the 138 The first -F suppresses trace events (field list is ""), but then the
139 second invocation sets the fields to comm,tid,time,ip,sym. In this case a 139 second invocation sets the fields to comm,tid,time,ip,sym. In this case a
140 warning is given to the user: 140 warning is given to the user:
141 141
@@ -143,9 +143,9 @@ OPTIONS
143 143
144 Alternatively, consider the order: 144 Alternatively, consider the order:
145 145
146 -f comm,tid,time,ip,sym -f trace: 146 -F comm,tid,time,ip,sym -F trace:
147 147
148 The first -f sets the fields for all events and the second -f 148 The first -F sets the fields for all events and the second -F
149 suppresses trace events. The user is given a warning message about 149 suppresses trace events. The user is given a warning message about
150 the override, and the result of the above is that only S/W and H/W 150 the override, and the result of the above is that only S/W and H/W
151 events are displayed with the given fields. 151 events are displayed with the given fields.
@@ -154,14 +154,14 @@ OPTIONS
154 event type, a message is displayed to the user that the option is 154 event type, a message is displayed to the user that the option is
155 ignored for that type. For example: 155 ignored for that type. For example:
156 156
157 $ perf script -f comm,tid,trace 157 $ perf script -F comm,tid,trace
158 'trace' not valid for hardware events. Ignoring. 158 'trace' not valid for hardware events. Ignoring.
159 'trace' not valid for software events. Ignoring. 159 'trace' not valid for software events. Ignoring.
160 160
161 Alternatively, if the type is given an invalid field is specified it 161 Alternatively, if the type is given an invalid field is specified it
162 is an error. For example: 162 is an error. For example:
163 163
164 perf script -v -f sw:comm,tid,trace 164 perf script -v -F sw:comm,tid,trace
165 'trace' not valid for software events. 165 'trace' not valid for software events.
166 166
167 At this point usage is displayed, and perf-script exits. 167 At this point usage is displayed, and perf-script exits.
@@ -170,10 +170,19 @@ OPTIONS
170 Trace decoding. The flags are "bcrosyiABEx" which stand for branch, 170 Trace decoding. The flags are "bcrosyiABEx" which stand for branch,
171 call, return, conditional, system, asynchronous, interrupt, 171 call, return, conditional, system, asynchronous, interrupt,
172 transaction abort, trace begin, trace end, and in transaction, 172 transaction abort, trace begin, trace end, and in transaction,
173 respectively. 173 respectively. Known combinations of flags are printed more nicely e.g.
174 "call" for "bc", "return" for "br", "jcc" for "bo", "jmp" for "b",
175 "int" for "bci", "iret" for "bri", "syscall" for "bcs", "sysret" for "brs",
176 "async" for "by", "hw int" for "bcyi", "tx abrt" for "bA", "tr strt" for "bB",
177 "tr end" for "bE". However the "x" flag will be display separately in those
178 cases e.g. "jcc (x)" for a condition branch within a transaction.
179
180 The callindent field is synthesized and may have a value when
181 Instruction Trace decoding. For calls and returns, it will display the
182 name of the symbol indented with spaces to reflect the stack depth.
174 183
175 Finally, a user may not set fields to none for all event types. 184 Finally, a user may not set fields to none for all event types.
176 i.e., -f "" is not allowed. 185 i.e., -F "" is not allowed.
177 186
178 The brstack output includes branch related information with raw addresses using the 187 The brstack output includes branch related information with raw addresses using the
179 /v/v/v/v/ syntax in the following order: 188 /v/v/v/v/ syntax in the following order:
@@ -259,9 +268,23 @@ include::itrace.txt[]
259--full-source-path:: 268--full-source-path::
260 Show the full path for source files for srcline output. 269 Show the full path for source files for srcline output.
261 270
271--max-stack::
272 Set the stack depth limit when parsing the callchain, anything
273 beyond the specified depth will be ignored. This is a trade-off
274 between information loss and faster processing especially for
275 workloads that can have a very long callchain stack.
276 Note that when using the --itrace option the synthesized callchain size
277 will override this value if the synthesized callchain size is bigger.
278
279 Default: 127
280
262--ns:: 281--ns::
263 Use 9 decimal places when displaying time (i.e. show the nanoseconds) 282 Use 9 decimal places when displaying time (i.e. show the nanoseconds)
264 283
284-f::
285--force::
286 Don't do ownership validation.
287
265SEE ALSO 288SEE ALSO
266-------- 289--------
267linkperf:perf-record[1], linkperf:perf-script-perl[1], 290linkperf:perf-record[1], linkperf:perf-script-perl[1],
diff --git a/tools/perf/Documentation/perf-stat.txt b/tools/perf/Documentation/perf-stat.txt
index 04f23b404bbc..d96ccd4844df 100644
--- a/tools/perf/Documentation/perf-stat.txt
+++ b/tools/perf/Documentation/perf-stat.txt
@@ -204,6 +204,38 @@ Aggregate counts per physical processor for system-wide mode measurements.
204--no-aggr:: 204--no-aggr::
205Do not aggregate counts across all monitored CPUs. 205Do not aggregate counts across all monitored CPUs.
206 206
207--topdown::
208Print top down level 1 metrics if supported by the CPU. This allows to
209determine bottle necks in the CPU pipeline for CPU bound workloads,
210by breaking the cycles consumed down into frontend bound, backend bound,
211bad speculation and retiring.
212
213Frontend bound means that the CPU cannot fetch and decode instructions fast
214enough. Backend bound means that computation or memory access is the bottle
215neck. Bad Speculation means that the CPU wasted cycles due to branch
216mispredictions and similar issues. Retiring means that the CPU computed without
217an apparently bottleneck. The bottleneck is only the real bottleneck
218if the workload is actually bound by the CPU and not by something else.
219
220For best results it is usually a good idea to use it with interval
221mode like -I 1000, as the bottleneck of workloads can change often.
222
223The top down metrics are collected per core instead of per
224CPU thread. Per core mode is automatically enabled
225and -a (global monitoring) is needed, requiring root rights or
226perf.perf_event_paranoid=-1.
227
228Topdown uses the full Performance Monitoring Unit, and needs
229disabling of the NMI watchdog (as root):
230echo 0 > /proc/sys/kernel/nmi_watchdog
231for best results. Otherwise the bottlenecks may be inconsistent
232on workload with changing phases.
233
234This enables --metric-only, unless overriden with --no-metric-only.
235
236To interpret the results it is usually needed to know on which
237CPUs the workload runs on. If needed the CPUs can be forced using
238taskset.
207 239
208EXAMPLES 240EXAMPLES
209-------- 241--------
diff --git a/tools/perf/Documentation/perf-test.txt b/tools/perf/Documentation/perf-test.txt
index 31a5c3ea7f74..b329c65d7f40 100644
--- a/tools/perf/Documentation/perf-test.txt
+++ b/tools/perf/Documentation/perf-test.txt
@@ -30,3 +30,7 @@ OPTIONS
30-v:: 30-v::
31--verbose:: 31--verbose::
32 Be more verbose. 32 Be more verbose.
33
34-F::
35--dont-fork::
36 Do not fork child for each test, run all tests within single process.
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index 19f046f027cd..91d638df3a6b 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -177,7 +177,7 @@ Default is to monitor all CPUS.
177 between information loss and faster processing especially for 177 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: 127 180 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.
diff --git a/tools/perf/Documentation/perf-trace.txt b/tools/perf/Documentation/perf-trace.txt
index 13293de8869f..1ab0782369b1 100644
--- a/tools/perf/Documentation/perf-trace.txt
+++ b/tools/perf/Documentation/perf-trace.txt
@@ -117,9 +117,42 @@ the thread executes on the designated CPUs. Default is to monitor all CPUs.
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 for
147 live sessions (without --input/-i), 127 otherwise.
148
149--min-stack::
150 Set the stack depth limit when parsing the callchain, anything
151 below the specified depth will be ignored. Disabled by default.
152
153 Implies '--call-graph dwarf' when --call-graph not present on the
154 command line, on systems where DWARF unwinding was built in.
155
123--proc-map-timeout:: 156--proc-map-timeout::
124 When processing pre-existing threads /proc/XXX/mmap, it may take a long time, 157 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. 158 because the file may be huge. A time out is needed in such cases.
diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
new file mode 100644
index 000000000000..fdc99fe6bbc3
--- /dev/null
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -0,0 +1,442 @@
1perf.data format
2
3Uptodate as of v4.7
4
5This document describes the on-disk perf.data format, generated by perf record
6or perf inject and consumed by the other perf tools.
7
8On a high level perf.data contains the events generated by the PMUs, plus metadata.
9
10All fields are in native-endian of the machine that generated the perf.data.
11
12When perf is writing to a pipe it uses a special version of the file
13format that does not rely on seeking to adjust data offsets. This
14format is not described here. The pipe version can be converted to
15normal perf.data with perf inject.
16
17The file starts with a perf_header:
18
19struct perf_header {
20 char magic[8]; /* PERFILE2 */
21 uint64_t size; /* size of the header */
22 uint64_t attr_size; /* size of an attribute in attrs */
23 struct perf_file_section attrs;
24 struct perf_file_section data;
25 struct perf_file_section event_types;
26 uint64_t flags;
27 uint64_t flags1[3];
28};
29
30The magic number identifies the perf file and the version. Current perf versions
31use PERFILE2. Old perf versions generated a version 1 format (PERFFILE). Version 1
32is not described here. The magic number also identifies the endian. When the
33magic value is 64bit byte swapped compared the file is in non-native
34endian.
35
36A perf_file_section contains a pointer to another section of the perf file.
37The header contains three such pointers: for attributes, data and event types.
38
39struct perf_file_section {
40 uint64_t offset; /* offset from start of file */
41 uint64_t size; /* size of the section */
42};
43
44Flags section:
45
46The header is followed by different optional headers, described by the bits set
47in flags. Only headers for which the bit is set are included. Each header
48consists of a perf_file_section located after the initial header.
49The respective perf_file_section points to the data of the additional
50header and defines its size.
51
52Some headers consist of strings, which are defined like this:
53
54struct perf_header_string {
55 uint32_t len;
56 char string[len]; /* zero terminated */
57};
58
59Some headers consist of a sequence of strings, which start with a
60
61struct perf_header_string_list {
62 uint32_t nr;
63 struct perf_header_string strings[nr]; /* variable length records */
64};
65
66The bits are the flags bits in a 256 bit bitmap starting with
67flags. These define the valid bits:
68
69 HEADER_RESERVED = 0, /* always cleared */
70 HEADER_FIRST_FEATURE = 1,
71 HEADER_TRACING_DATA = 1,
72
73Describe me.
74
75 HEADER_BUILD_ID = 2,
76
77The header consists of an sequence of build_id_event. The size of each record
78is defined by header.size (see perf_event.h). Each event defines a ELF build id
79for a executable file name for a pid. An ELF build id is a unique identifier
80assigned by the linker to an executable.
81
82struct build_id_event {
83 struct perf_event_header header;
84 pid_t pid;
85 uint8_t build_id[24];
86 char filename[header.size - offsetof(struct build_id_event, filename)];
87};
88
89 HEADER_HOSTNAME = 3,
90
91A perf_header_string with the hostname where the data was collected
92(uname -n)
93
94 HEADER_OSRELEASE = 4,
95
96A perf_header_string with the os release where the data was collected
97(uname -r)
98
99 HEADER_VERSION = 5,
100
101A perf_header_string with the perf user tool version where the
102data was collected. This is the same as the version of the source tree
103the perf tool was built from.
104
105 HEADER_ARCH = 6,
106
107A perf_header_string with the CPU architecture (uname -m)
108
109 HEADER_NRCPUS = 7,
110
111A structure defining the number of CPUs.
112
113struct nr_cpus {
114 uint32_t nr_cpus_online;
115 uint32_t nr_cpus_available; /* CPUs not yet onlined */
116};
117
118 HEADER_CPUDESC = 8,
119
120A perf_header_string with description of the CPU. On x86 this is the model name
121in /proc/cpuinfo
122
123 HEADER_CPUID = 9,
124
125A perf_header_string with the exact CPU type. On x86 this is
126vendor,family,model,stepping. For example: GenuineIntel,6,69,1
127
128 HEADER_TOTAL_MEM = 10,
129
130An uint64_t with the total memory in bytes.
131
132 HEADER_CMDLINE = 11,
133
134A perf_header_string with the perf command line used to collect the data.
135
136 HEADER_EVENT_DESC = 12,
137
138Another description of the perf_event_attrs, more detailed than header.attrs
139including IDs and names. See perf_event.h or the man page for a description
140of a struct perf_event_attr.
141
142struct {
143 uint32_t nr; /* number of events */
144 uint32_t attr_size; /* size of each perf_event_attr */
145 struct {
146 struct perf_event_attr attr; /* size of attr_size */
147 uint32_t nr_ids;
148 struct perf_header_string event_string;
149 uint64_t ids[nr_ids];
150 } events[nr]; /* Variable length records */
151};
152
153 HEADER_CPU_TOPOLOGY = 13,
154
155String lists defining the core and CPU threads topology.
156
157struct {
158 struct perf_header_string_list cores; /* Variable length */
159 struct perf_header_string_list threads; /* Variable length */
160};
161
162Example:
163 sibling cores : 0-3
164 sibling threads : 0-1
165 sibling threads : 2-3
166
167 HEADER_NUMA_TOPOLOGY = 14,
168
169 A list of NUMA node descriptions
170
171struct {
172 uint32_t nr;
173 struct {
174 uint32_t nodenr;
175 uint64_t mem_total;
176 uint64_t mem_free;
177 struct perf_header_string cpus;
178 } nodes[nr]; /* Variable length records */
179};
180
181 HEADER_BRANCH_STACK = 15,
182
183Not implemented in perf.
184
185 HEADER_PMU_MAPPINGS = 16,
186
187 A list of PMU structures, defining the different PMUs supported by perf.
188
189struct {
190 uint32_t nr;
191 struct pmu {
192 uint32_t pmu_type;
193 struct perf_header_string pmu_name;
194 } [nr]; /* Variable length records */
195};
196
197 HEADER_GROUP_DESC = 17,
198
199 Description of counter groups ({...} in perf syntax)
200
201struct {
202 uint32_t nr;
203 struct {
204 struct perf_header_string string;
205 uint32_t leader_idx;
206 uint32_t nr_members;
207 } [nr]; /* Variable length records */
208};
209
210 HEADER_AUXTRACE = 18,
211
212Define additional auxtrace areas in the perf.data. auxtrace is used to store
213undecoded hardware tracing information, such as Intel Processor Trace data.
214
215/**
216 * struct auxtrace_index_entry - indexes a AUX area tracing event within a
217 * perf.data file.
218 * @file_offset: offset within the perf.data file
219 * @sz: size of the event
220 */
221struct auxtrace_index_entry {
222 u64 file_offset;
223 u64 sz;
224};
225
226#define PERF_AUXTRACE_INDEX_ENTRY_COUNT 256
227
228/**
229 * struct auxtrace_index - index of AUX area tracing events within a perf.data
230 * file.
231 * @list: linking a number of arrays of entries
232 * @nr: number of entries
233 * @entries: array of entries
234 */
235struct auxtrace_index {
236 struct list_head list;
237 size_t nr;
238 struct auxtrace_index_entry entries[PERF_AUXTRACE_INDEX_ENTRY_COUNT];
239};
240
241 other bits are reserved and should ignored for now
242 HEADER_FEAT_BITS = 256,
243
244Attributes
245
246This is an array of perf_event_attrs, each attr_size bytes long, which defines
247each event collected. See perf_event.h or the man page for a detailed
248description.
249
250Data
251
252This section is the bulk of the file. It consist of a stream of perf_events
253describing events. This matches the format generated by the kernel.
254See perf_event.h or the manpage for a detailed description.
255
256Some notes on parsing:
257
258Ordering
259
260The events are not necessarily in time stamp order, as they can be
261collected in parallel on different CPUs. If the events should be
262processed in time order they need to be sorted first. It is possible
263to only do a partial sort using the FINISHED_ROUND event header (see
264below). perf record guarantees that there is no reordering over a
265FINISHED_ROUND.
266
267ID vs IDENTIFIER
268
269When the event stream contains multiple events each event is identified
270by an ID. This can be either through the PERF_SAMPLE_ID or the
271PERF_SAMPLE_IDENTIFIER header. The PERF_SAMPLE_IDENTIFIER header is
272at a fixed offset from the event header, which allows reliable
273parsing of the header. Relying on ID may be ambigious.
274IDENTIFIER is only supported by newer Linux kernels.
275
276Perf record specific events:
277
278In addition to the kernel generated event types perf record adds its
279own event types (in addition it also synthesizes some kernel events,
280for example MMAP events)
281
282 PERF_RECORD_USER_TYPE_START = 64,
283 PERF_RECORD_HEADER_ATTR = 64,
284
285struct attr_event {
286 struct perf_event_header header;
287 struct perf_event_attr attr;
288 uint64_t id[];
289};
290
291 PERF_RECORD_HEADER_EVENT_TYPE = 65, /* depreceated */
292
293#define MAX_EVENT_NAME 64
294
295struct perf_trace_event_type {
296 uint64_t event_id;
297 char name[MAX_EVENT_NAME];
298};
299
300struct event_type_event {
301 struct perf_event_header header;
302 struct perf_trace_event_type event_type;
303};
304
305
306 PERF_RECORD_HEADER_TRACING_DATA = 66,
307
308Describe me
309
310struct tracing_data_event {
311 struct perf_event_header header;
312 uint32_t size;
313};
314
315 PERF_RECORD_HEADER_BUILD_ID = 67,
316
317Define a ELF build ID for a referenced executable.
318
319 struct build_id_event; /* See above */
320
321 PERF_RECORD_FINISHED_ROUND = 68,
322
323No event reordering over this header. No payload.
324
325 PERF_RECORD_ID_INDEX = 69,
326
327Map event ids to CPUs and TIDs.
328
329struct id_index_entry {
330 uint64_t id;
331 uint64_t idx;
332 uint64_t cpu;
333 uint64_t tid;
334};
335
336struct id_index_event {
337 struct perf_event_header header;
338 uint64_t nr;
339 struct id_index_entry entries[nr];
340};
341
342 PERF_RECORD_AUXTRACE_INFO = 70,
343
344Auxtrace type specific information. Describe me
345
346struct auxtrace_info_event {
347 struct perf_event_header header;
348 uint32_t type;
349 uint32_t reserved__; /* For alignment */
350 uint64_t priv[];
351};
352
353 PERF_RECORD_AUXTRACE = 71,
354
355Defines auxtrace data. Followed by the actual data. The contents of
356the auxtrace data is dependent on the event and the CPU. For example
357for Intel Processor Trace it contains Processor Trace data generated
358by the CPU.
359
360struct auxtrace_event {
361 struct perf_event_header header;
362 uint64_t size;
363 uint64_t offset;
364 uint64_t reference;
365 uint32_t idx;
366 uint32_t tid;
367 uint32_t cpu;
368 uint32_t reserved__; /* For alignment */
369};
370
371struct aux_event {
372 struct perf_event_header header;
373 uint64_t aux_offset;
374 uint64_t aux_size;
375 uint64_t flags;
376};
377
378 PERF_RECORD_AUXTRACE_ERROR = 72,
379
380Describes an error in hardware tracing
381
382enum auxtrace_error_type {
383 PERF_AUXTRACE_ERROR_ITRACE = 1,
384 PERF_AUXTRACE_ERROR_MAX
385};
386
387#define MAX_AUXTRACE_ERROR_MSG 64
388
389struct auxtrace_error_event {
390 struct perf_event_header header;
391 uint32_t type;
392 uint32_t code;
393 uint32_t cpu;
394 uint32_t pid;
395 uint32_t tid;
396 uint32_t reserved__; /* For alignment */
397 uint64_t ip;
398 char msg[MAX_AUXTRACE_ERROR_MSG];
399};
400
401Event types
402
403Define the event attributes with their IDs.
404
405An array bound by the perf_file_section size.
406
407 struct {
408 struct perf_event_attr attr; /* Size defined by header.attr_size */
409 struct perf_file_section ids;
410 }
411
412ids points to a array of uint64_t defining the ids for event attr attr.
413
414References:
415
416include/uapi/linux/perf_event.h
417
418This is the canonical description of the kernel generated perf_events
419and the perf_event_attrs.
420
421perf_events manpage
422
423A manpage describing perf_event and perf_event_attr is here:
424http://web.eece.maine.edu/~vweaver/projects/perf_events/programming.html
425This tends to be slightly behind the kernel include, but has better
426descriptions. An (typically older) version of the man page may be
427included with the standard Linux man pages, available with "man
428perf_events"
429
430pmu-tools
431
432https://github.com/andikleen/pmu-tools/tree/master/parser
433
434A definition of the perf.data format in python "construct" format is available
435in pmu-tools parser. This allows to read perf.data from python and dump it.
436
437quipper
438
439The quipper C++ parser is available at
440https://chromium.googlesource.com/chromiumos/platform/chromiumos-wide-profiling/
441Unfortunately this parser tends to be many versions behind and may not be able
442to parse data files generated by recent perf.
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8c8c6b9ce915..ad2534df4ba6 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -12,13 +12,23 @@ tools/arch/sparc/include/asm/barrier_32.h
12tools/arch/sparc/include/asm/barrier_64.h 12tools/arch/sparc/include/asm/barrier_64.h
13tools/arch/tile/include/asm/barrier.h 13tools/arch/tile/include/asm/barrier.h
14tools/arch/x86/include/asm/barrier.h 14tools/arch/x86/include/asm/barrier.h
15tools/arch/x86/include/asm/cpufeatures.h
16tools/arch/x86/include/asm/disabled-features.h
17tools/arch/x86/include/asm/required-features.h
18tools/arch/x86/include/uapi/asm/svm.h
19tools/arch/x86/include/uapi/asm/vmx.h
20tools/arch/x86/include/uapi/asm/kvm.h
21tools/arch/x86/include/uapi/asm/kvm_perf.h
22tools/arch/x86/lib/memcpy_64.S
23tools/arch/x86/lib/memset_64.S
24tools/arch/s390/include/uapi/asm/kvm_perf.h
25tools/arch/s390/include/uapi/asm/sie.h
15tools/arch/xtensa/include/asm/barrier.h 26tools/arch/xtensa/include/asm/barrier.h
16tools/scripts 27tools/scripts
17tools/build 28tools/build
18tools/arch/x86/include/asm/atomic.h 29tools/arch/x86/include/asm/atomic.h
19tools/arch/x86/include/asm/rmwcc.h 30tools/arch/x86/include/asm/rmwcc.h
20tools/lib/traceevent 31tools/lib/traceevent
21tools/lib/bpf
22tools/lib/api 32tools/lib/api
23tools/lib/bpf 33tools/lib/bpf
24tools/lib/subcmd 34tools/lib/subcmd
@@ -29,6 +39,9 @@ tools/lib/symbol/kallsyms.c
29tools/lib/symbol/kallsyms.h 39tools/lib/symbol/kallsyms.h
30tools/lib/find_bit.c 40tools/lib/find_bit.c
31tools/lib/bitmap.c 41tools/lib/bitmap.c
42tools/lib/str_error_r.c
43tools/lib/vsprintf.c
44tools/include/asm/alternative-asm.h
32tools/include/asm/atomic.h 45tools/include/asm/atomic.h
33tools/include/asm/barrier.h 46tools/include/asm/barrier.h
34tools/include/asm/bug.h 47tools/include/asm/bug.h
@@ -52,43 +65,16 @@ tools/include/linux/hash.h
52tools/include/linux/kernel.h 65tools/include/linux/kernel.h
53tools/include/linux/list.h 66tools/include/linux/list.h
54tools/include/linux/log2.h 67tools/include/linux/log2.h
68tools/include/uapi/linux/bpf.h
69tools/include/uapi/linux/bpf_common.h
70tools/include/uapi/linux/hw_breakpoint.h
71tools/include/uapi/linux/perf_event.h
55tools/include/linux/poison.h 72tools/include/linux/poison.h
56tools/include/linux/rbtree.h 73tools/include/linux/rbtree.h
57tools/include/linux/rbtree_augmented.h 74tools/include/linux/rbtree_augmented.h
58tools/include/linux/string.h 75tools/include/linux/string.h
76tools/include/linux/stringify.h
59tools/include/linux/types.h 77tools/include/linux/types.h
60tools/include/linux/err.h 78tools/include/linux/err.h
61tools/include/linux/bitmap.h 79tools/include/linux/bitmap.h
62include/asm-generic/bitops/arch_hweight.h 80tools/arch/*/include/uapi/asm/perf_regs.h
63include/asm-generic/bitops/const_hweight.h
64include/asm-generic/bitops/fls64.h
65include/asm-generic/bitops/__fls.h
66include/asm-generic/bitops/fls.h
67include/linux/perf_event.h
68include/linux/list.h
69include/linux/hash.h
70include/linux/stringify.h
71include/linux/swab.h
72arch/*/include/asm/unistd*.h
73arch/*/include/uapi/asm/unistd*.h
74arch/*/include/uapi/asm/perf_regs.h
75arch/*/lib/memcpy*.S
76arch/*/lib/memset*.S
77arch/*/include/asm/*features.h
78include/linux/poison.h
79include/linux/hw_breakpoint.h
80include/uapi/linux/perf_event.h
81include/uapi/linux/bpf.h
82include/uapi/linux/bpf_common.h
83include/uapi/linux/const.h
84include/uapi/linux/swab.h
85include/uapi/linux/hw_breakpoint.h
86arch/x86/include/asm/svm.h
87arch/x86/include/asm/vmx.h
88arch/x86/include/asm/kvm_host.h
89arch/x86/include/uapi/asm/svm.h
90arch/x86/include/uapi/asm/vmx.h
91arch/x86/include/uapi/asm/kvm.h
92arch/x86/include/uapi/asm/kvm_perf.h
93arch/s390/include/uapi/asm/sie.h
94arch/s390/include/uapi/asm/kvm_perf.h
diff --git a/tools/perf/config/Makefile b/tools/perf/Makefile.config
index 6f8f6430f2bf..24803c58049a 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/Makefile.config
@@ -23,11 +23,17 @@ $(call detected_var,ARCH)
23 23
24NO_PERF_REGS := 1 24NO_PERF_REGS := 1
25 25
26# Additional ARCH settings for ppc
27ifeq ($(ARCH),powerpc)
28 NO_PERF_REGS := 0
29 LIBUNWIND_LIBS := -lunwind -lunwind-ppc64
30endif
31
26# Additional ARCH settings for x86 32# Additional ARCH settings for x86
27ifeq ($(ARCH),x86) 33ifeq ($(ARCH),x86)
28 $(call detected,CONFIG_X86) 34 $(call detected,CONFIG_X86)
29 ifeq (${IS_64_BIT}, 1) 35 ifeq (${IS_64_BIT}, 1)
30 CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT 36 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.S 37 ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
32 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64 38 LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
33 $(call detected,CONFIG_X86_64) 39 $(call detected,CONFIG_X86_64)
@@ -67,17 +73,25 @@ endif
67# 73#
68# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ 74# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
69# 75#
76
77libunwind_arch_set_flags = $(eval $(libunwind_arch_set_flags_code))
78define libunwind_arch_set_flags_code
79 FEATURE_CHECK_CFLAGS-libunwind-$(1) = -I$(LIBUNWIND_DIR)/include
80 FEATURE_CHECK_LDFLAGS-libunwind-$(1) = -L$(LIBUNWIND_DIR)/lib
81endef
82
70ifdef LIBUNWIND_DIR 83ifdef LIBUNWIND_DIR
71 LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include 84 LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include
72 LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib 85 LIBUNWIND_LDFLAGS = -L$(LIBUNWIND_DIR)/lib
86 LIBUNWIND_ARCHS = x86 x86_64 arm aarch64 debug-frame-arm debug-frame-aarch64
87 $(foreach libunwind_arch,$(LIBUNWIND_ARCHS),$(call libunwind_arch_set_flags,$(libunwind_arch)))
73endif 88endif
74LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
75 89
76# Set per-feature check compilation flags 90# Set per-feature check compilation flags
77FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) 91FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
78FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) 92FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
79FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) 93FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
80FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) 94FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
81 95
82ifeq ($(NO_PERF_REGS),0) 96ifeq ($(NO_PERF_REGS),0)
83 CFLAGS += -DHAVE_PERF_REGS_SUPPORT 97 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
@@ -101,7 +115,7 @@ endif
101FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) 115FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
102FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf 116FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
103 117
104FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi 118FEATURE_CHECK_CFLAGS-bpf = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
105# include ARCH specific config 119# include ARCH specific config
106-include $(src-perf)/arch/$(ARCH)/Makefile 120-include $(src-perf)/arch/$(ARCH)/Makefile
107 121
@@ -192,11 +206,11 @@ endif
192 206
193CFLAGS += -I$(src-perf)/util/include 207CFLAGS += -I$(src-perf)/util/include
194CFLAGS += -I$(src-perf)/arch/$(ARCH)/include 208CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
209CFLAGS += -I$(srctree)/tools/include/uapi
195CFLAGS += -I$(srctree)/tools/include/ 210CFLAGS += -I$(srctree)/tools/include/
196CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi 211CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
197CFLAGS += -I$(srctree)/arch/$(ARCH)/include 212CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
198CFLAGS += -I$(srctree)/include/uapi 213CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/
199CFLAGS += -I$(srctree)/include
200 214
201# $(obj-perf) for generated common-cmds.h 215# $(obj-perf) for generated common-cmds.h
202# $(obj-perf)/util for generated bison/flex headers 216# $(obj-perf)/util for generated bison/flex headers
@@ -243,7 +257,7 @@ else
243 LIBC_SUPPORT := 1 257 LIBC_SUPPORT := 1
244 endif 258 endif
245 ifeq ($(LIBC_SUPPORT),1) 259 ifeq ($(LIBC_SUPPORT),1)
246 msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install elfutils-libelf-devel/libelf-dev); 260 msg := $(warning No libelf found, disables 'probe' tool and BPF support in 'perf record', please install libelf-dev, libelf-devel or elfutils-libelf-devel);
247 261
248 NO_LIBELF := 1 262 NO_LIBELF := 1
249 NO_DWARF := 1 263 NO_DWARF := 1
@@ -295,8 +309,15 @@ ifndef NO_LIBELF
295 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT 309 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
296 endif 310 endif
297 311
298 # include ARCH specific config 312 ifeq ($(feature-libelf-gelf_getnote), 1)
299 -include $(src-perf)/arch/$(ARCH)/Makefile 313 CFLAGS += -DHAVE_GELF_GETNOTE_SUPPORT
314 else
315 msg := $(warning gelf_getnote() not found on libelf, SDT support disabled);
316 endif
317
318 ifeq ($(feature-libelf-getshdrstrndx), 1)
319 CFLAGS += -DHAVE_ELF_GETSHDRSTRNDX_SUPPORT
320 endif
300 321
301 ifndef NO_DWARF 322 ifndef NO_DWARF
302 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 323 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
@@ -334,6 +355,16 @@ ifndef NO_LIBELF
334 endif # NO_LIBBPF 355 endif # NO_LIBBPF
335endif # NO_LIBELF 356endif # NO_LIBELF
336 357
358ifndef NO_SDT
359 ifneq ($(feature-sdt), 1)
360 msg := $(warning No sys/sdt.h found, no SDT events are defined, please install systemtap-sdt-devel or systemtap-sdt-dev);
361 NO_SDT := 1;
362 else
363 CFLAGS += -DHAVE_SDT_EVENT
364 $(call detected,CONFIG_SDT_EVENT)
365 endif
366endif
367
337ifdef PERF_HAVE_JITDUMP 368ifdef PERF_HAVE_JITDUMP
338 ifndef NO_DWARF 369 ifndef NO_DWARF
339 $(call detected,CONFIG_JITDUMP) 370 $(call detected,CONFIG_JITDUMP)
@@ -348,10 +379,42 @@ ifeq ($(ARCH),powerpc)
348endif 379endif
349 380
350ifndef NO_LIBUNWIND 381ifndef NO_LIBUNWIND
382 have_libunwind :=
383
384 ifeq ($(feature-libunwind-x86), 1)
385 $(call detected,CONFIG_LIBUNWIND_X86)
386 CFLAGS += -DHAVE_LIBUNWIND_X86_SUPPORT
387 LDFLAGS += -lunwind-x86
388 EXTLIBS_LIBUNWIND += -lunwind-x86
389 have_libunwind = 1
390 endif
391
392 ifeq ($(feature-libunwind-aarch64), 1)
393 $(call detected,CONFIG_LIBUNWIND_AARCH64)
394 CFLAGS += -DHAVE_LIBUNWIND_AARCH64_SUPPORT
395 LDFLAGS += -lunwind-aarch64
396 EXTLIBS_LIBUNWIND += -lunwind-aarch64
397 have_libunwind = 1
398 $(call feature_check,libunwind-debug-frame-aarch64)
399 ifneq ($(feature-libunwind-debug-frame-aarch64), 1)
400 msg := $(warning No debug_frame support found in libunwind-aarch64);
401 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME_AARCH64
402 endif
403 endif
404
351 ifneq ($(feature-libunwind), 1) 405 ifneq ($(feature-libunwind), 1)
352 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR); 406 msg := $(warning No libunwind found. Please install libunwind-dev[el] >= 1.1 and/or set LIBUNWIND_DIR);
407 NO_LOCAL_LIBUNWIND := 1
408 else
409 have_libunwind := 1
410 $(call detected,CONFIG_LOCAL_LIBUNWIND)
411 endif
412
413 ifneq ($(have_libunwind), 1)
353 NO_LIBUNWIND := 1 414 NO_LIBUNWIND := 1
354 endif 415 endif
416else
417 NO_LOCAL_LIBUNWIND := 1
355endif 418endif
356 419
357ifndef NO_LIBBPF 420ifndef NO_LIBBPF
@@ -389,7 +452,7 @@ else
389 NO_DWARF_UNWIND := 1 452 NO_DWARF_UNWIND := 1
390endif 453endif
391 454
392ifndef NO_LIBUNWIND 455ifndef NO_LOCAL_LIBUNWIND
393 ifeq ($(ARCH),$(filter $(ARCH),arm arm64)) 456 ifeq ($(ARCH),$(filter $(ARCH),arm arm64))
394 $(call feature_check,libunwind-debug-frame) 457 $(call feature_check,libunwind-debug-frame)
395 ifneq ($(feature-libunwind-debug-frame), 1) 458 ifneq ($(feature-libunwind-debug-frame), 1)
@@ -400,10 +463,15 @@ ifndef NO_LIBUNWIND
400 # non-ARM has no dwarf_find_debug_frame() function: 463 # non-ARM has no dwarf_find_debug_frame() function:
401 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 464 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
402 endif 465 endif
403 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
404 EXTLIBS += $(LIBUNWIND_LIBS) 466 EXTLIBS += $(LIBUNWIND_LIBS)
467 LDFLAGS += $(LIBUNWIND_LIBS)
468endif
469
470ifndef NO_LIBUNWIND
471 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
405 CFLAGS += $(LIBUNWIND_CFLAGS) 472 CFLAGS += $(LIBUNWIND_CFLAGS)
406 LDFLAGS += $(LIBUNWIND_LDFLAGS) 473 LDFLAGS += $(LIBUNWIND_LDFLAGS)
474 EXTLIBS += $(EXTLIBS_LIBUNWIND)
407endif 475endif
408 476
409ifndef NO_LIBAUDIT 477ifndef NO_LIBAUDIT
@@ -434,7 +502,7 @@ endif
434 502
435ifndef NO_SLANG 503ifndef NO_SLANG
436 ifneq ($(feature-libslang), 1) 504 ifneq ($(feature-libslang), 1)
437 msg := $(warning slang not found, disables TUI support. Please install slang-devel or libslang-dev); 505 msg := $(warning slang not found, disables TUI support. Please install slang-devel, libslang-dev or libslang2-dev);
438 NO_SLANG := 1 506 NO_SLANG := 1
439 else 507 else
440 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h 508 # Fedora has /usr/include/slang/slang.h, but ubuntu /usr/include/slang.h
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 000ea210389d..2d9087501633 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -81,6 +81,9 @@ include ../scripts/utilities.mak
81# 81#
82# Define NO_LIBBPF if you do not want BPF support 82# Define NO_LIBBPF if you do not want BPF support
83# 83#
84# Define NO_SDT if you do not want to define SDT event in perf tools,
85# note that it doesn't disable SDT scanning support.
86#
84# Define FEATURES_DUMP to provide features detection dump file 87# Define FEATURES_DUMP to provide features detection dump file
85# and bypass the feature detection 88# and bypass the feature detection
86 89
@@ -158,7 +161,7 @@ TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
158BPF_DIR = $(srctree)/tools/lib/bpf/ 161BPF_DIR = $(srctree)/tools/lib/bpf/
159SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ 162SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
160 163
161# include config/Makefile by default and rule out 164# include Makefile.config by default and rule out
162# non-config cases 165# non-config cases
163config := 1 166config := 1
164 167
@@ -180,7 +183,12 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
180FEATURE_TESTS := all 183FEATURE_TESTS := all
181endif 184endif
182endif 185endif
183include config/Makefile 186include Makefile.config
187endif
188
189ifeq ($(config),0)
190include $(srctree)/tools/scripts/Makefile.arch
191-include arch/$(ARCH)/Makefile
184endif 192endif
185 193
186# The FEATURE_DUMP_EXPORT holds location of the actual 194# The FEATURE_DUMP_EXPORT holds location of the actual
@@ -249,7 +257,8 @@ PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
249PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 257PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
250 258
251$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) 259$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
252 $(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ 260 $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
261 CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
253 $(PYTHON_WORD) util/setup.py \ 262 $(PYTHON_WORD) util/setup.py \
254 --quiet build_ext; \ 263 --quiet build_ext; \
255 mkdir -p $(OUTPUT)python && \ 264 mkdir -p $(OUTPUT)python && \
@@ -297,8 +306,6 @@ endif
297# because maintaining the nesting to match is a pain. If 306# because maintaining the nesting to match is a pain. If
298# we had "elif" things would have been much nicer... 307# we had "elif" things would have been much nicer...
299 308
300-include arch/$(ARCH)/Makefile
301
302ifneq ($(OUTPUT),) 309ifneq ($(OUTPUT),)
303 CFLAGS += -I$(OUTPUT) 310 CFLAGS += -I$(OUTPUT)
304endif 311endif
@@ -341,6 +348,87 @@ export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
341include $(srctree)/tools/build/Makefile.include 348include $(srctree)/tools/build/Makefile.include
342 349
343$(PERF_IN): prepare FORCE 350$(PERF_IN): prepare FORCE
351 @(test -f ../../include/uapi/linux/perf_event.h && ( \
352 (diff -B ../include/uapi/linux/perf_event.h ../../include/uapi/linux/perf_event.h >/dev/null) \
353 || echo "Warning: tools/include/uapi/linux/perf_event.h differs from kernel" >&2 )) || true
354 @(test -f ../../include/linux/hash.h && ( \
355 (diff -B ../include/linux/hash.h ../../include/linux/hash.h >/dev/null) \
356 || echo "Warning: tools/include/linux/hash.h differs from kernel" >&2 )) || true
357 @(test -f ../../include/uapi/linux/hw_breakpoint.h && ( \
358 (diff -B ../include/uapi/linux/hw_breakpoint.h ../../include/uapi/linux/hw_breakpoint.h >/dev/null) \
359 || echo "Warning: tools/include/uapi/linux/hw_breakpoint.h differs from kernel" >&2 )) || true
360 @(test -f ../../arch/x86/include/asm/disabled-features.h && ( \
361 (diff -B ../arch/x86/include/asm/disabled-features.h ../../arch/x86/include/asm/disabled-features.h >/dev/null) \
362 || echo "Warning: tools/arch/x86/include/asm/disabled-features.h differs from kernel" >&2 )) || true
363 @(test -f ../../arch/x86/include/asm/required-features.h && ( \
364 (diff -B ../arch/x86/include/asm/required-features.h ../../arch/x86/include/asm/required-features.h >/dev/null) \
365 || echo "Warning: tools/arch/x86/include/asm/required-features.h differs from kernel" >&2 )) || true
366 @(test -f ../../arch/x86/include/asm/cpufeatures.h && ( \
367 (diff -B ../arch/x86/include/asm/cpufeatures.h ../../arch/x86/include/asm/cpufeatures.h >/dev/null) \
368 || echo "Warning: tools/arch/x86/include/asm/cpufeatures.h differs from kernel" >&2 )) || true
369 @(test -f ../../arch/x86/lib/memcpy_64.S && ( \
370 (diff -B ../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memcpy_64.S >/dev/null) \
371 || echo "Warning: tools/arch/x86/lib/memcpy_64.S differs from kernel" >&2 )) || true
372 @(test -f ../../arch/x86/lib/memset_64.S && ( \
373 (diff -B ../arch/x86/lib/memset_64.S ../../arch/x86/lib/memset_64.S >/dev/null) \
374 || echo "Warning: tools/arch/x86/lib/memset_64.S differs from kernel" >&2 )) || true
375 @(test -f ../../arch/arm/include/uapi/asm/perf_regs.h && ( \
376 (diff -B ../arch/arm/include/uapi/asm/perf_regs.h ../../arch/arm/include/uapi/asm/perf_regs.h >/dev/null) \
377 || echo "Warning: tools/arch/arm/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
378 @(test -f ../../arch/arm64/include/uapi/asm/perf_regs.h && ( \
379 (diff -B ../arch/arm64/include/uapi/asm/perf_regs.h ../../arch/arm64/include/uapi/asm/perf_regs.h >/dev/null) \
380 || echo "Warning: tools/arch/arm64/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
381 @(test -f ../../arch/powerpc/include/uapi/asm/perf_regs.h && ( \
382 (diff -B ../arch/powerpc/include/uapi/asm/perf_regs.h ../../arch/powerpc/include/uapi/asm/perf_regs.h >/dev/null) \
383 || echo "Warning: tools/arch/powerpc/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
384 @(test -f ../../arch/x86/include/uapi/asm/perf_regs.h && ( \
385 (diff -B ../arch/x86/include/uapi/asm/perf_regs.h ../../arch/x86/include/uapi/asm/perf_regs.h >/dev/null) \
386 || echo "Warning: tools/arch/x86/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
387 @(test -f ../../arch/x86/include/uapi/asm/kvm.h && ( \
388 (diff -B ../arch/x86/include/uapi/asm/kvm.h ../../arch/x86/include/uapi/asm/kvm.h >/dev/null) \
389 || echo "Warning: tools/arch/x86/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
390 @(test -f ../../arch/x86/include/uapi/asm/kvm_perf.h && ( \
391 (diff -B ../arch/x86/include/uapi/asm/kvm_perf.h ../../arch/x86/include/uapi/asm/kvm_perf.h >/dev/null) \
392 || echo "Warning: tools/arch/x86/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true
393 @(test -f ../../arch/x86/include/uapi/asm/svm.h && ( \
394 (diff -B ../arch/x86/include/uapi/asm/svm.h ../../arch/x86/include/uapi/asm/svm.h >/dev/null) \
395 || echo "Warning: tools/arch/x86/include/uapi/asm/svm.h differs from kernel" >&2 )) || true
396 @(test -f ../../arch/x86/include/uapi/asm/vmx.h && ( \
397 (diff -B ../arch/x86/include/uapi/asm/vmx.h ../../arch/x86/include/uapi/asm/vmx.h >/dev/null) \
398 || echo "Warning: tools/arch/x86/include/uapi/asm/vmx.h differs from kernel" >&2 )) || true
399 @(test -f ../../arch/powerpc/include/uapi/asm/kvm.h && ( \
400 (diff -B ../arch/powerpc/include/uapi/asm/kvm.h ../../arch/powerpc/include/uapi/asm/kvm.h >/dev/null) \
401 || echo "Warning: tools/arch/powerpc/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
402 @(test -f ../../arch/s390/include/uapi/asm/kvm.h && ( \
403 (diff -B ../arch/s390/include/uapi/asm/kvm.h ../../arch/s390/include/uapi/asm/kvm.h >/dev/null) \
404 || echo "Warning: tools/arch/s390/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
405 @(test -f ../../arch/s390/include/uapi/asm/kvm_perf.h && ( \
406 (diff -B ../arch/s390/include/uapi/asm/kvm_perf.h ../../arch/s390/include/uapi/asm/kvm_perf.h >/dev/null) \
407 || echo "Warning: tools/arch/s390/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true
408 @(test -f ../../arch/s390/include/uapi/asm/sie.h && ( \
409 (diff -B ../arch/s390/include/uapi/asm/sie.h ../../arch/s390/include/uapi/asm/sie.h >/dev/null) \
410 || echo "Warning: tools/arch/s390/include/uapi/asm/sie.h differs from kernel" >&2 )) || true
411 @(test -f ../../arch/arm/include/uapi/asm/kvm.h && ( \
412 (diff -B ../arch/arm/include/uapi/asm/kvm.h ../../arch/arm/include/uapi/asm/kvm.h >/dev/null) \
413 || echo "Warning: tools/arch/arm/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
414 @(test -f ../../arch/arm64/include/uapi/asm/kvm.h && ( \
415 (diff -B ../arch/arm64/include/uapi/asm/kvm.h ../../arch/arm64/include/uapi/asm/kvm.h >/dev/null) \
416 || echo "Warning: tools/arch/arm64/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
417 @(test -f ../../include/asm-generic/bitops/arch_hweight.h && ( \
418 (diff -B ../include/asm-generic/bitops/arch_hweight.h ../../include/asm-generic/bitops/arch_hweight.h >/dev/null) \
419 || echo "Warning: tools/include/asm-generic/bitops/arch_hweight.h differs from kernel" >&2 )) || true
420 @(test -f ../../include/asm-generic/bitops/const_hweight.h && ( \
421 (diff -B ../include/asm-generic/bitops/const_hweight.h ../../include/asm-generic/bitops/const_hweight.h >/dev/null) \
422 || echo "Warning: tools/include/asm-generic/bitops/const_hweight.h differs from kernel" >&2 )) || true
423 @(test -f ../../include/asm-generic/bitops/__fls.h && ( \
424 (diff -B ../include/asm-generic/bitops/__fls.h ../../include/asm-generic/bitops/__fls.h >/dev/null) \
425 || echo "Warning: tools/include/asm-generic/bitops/__fls.h differs from kernel" >&2 )) || true
426 @(test -f ../../include/asm-generic/bitops/fls.h && ( \
427 (diff -B ../include/asm-generic/bitops/fls.h ../../include/asm-generic/bitops/fls.h >/dev/null) \
428 || echo "Warning: tools/include/asm-generic/bitops/fls.h differs from kernel" >&2 )) || true
429 @(test -f ../../include/asm-generic/bitops/fls64.h && ( \
430 (diff -B ../include/asm-generic/bitops/fls64.h ../../include/asm-generic/bitops/fls64.h >/dev/null) \
431 || echo "Warning: tools/include/asm-generic/bitops/fls64.h differs from kernel" >&2 )) || true
344 $(Q)$(MAKE) $(build)=perf 432 $(Q)$(MAKE) $(build)=perf
345 433
346$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) 434$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
@@ -390,7 +478,7 @@ endif
390__build-dir = $(subst $(OUTPUT),,$(dir $@)) 478__build-dir = $(subst $(OUTPUT),,$(dir $@))
391build-dir = $(if $(__build-dir),$(__build-dir),.) 479build-dir = $(if $(__build-dir),$(__build-dir),.)
392 480
393prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep 481prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h fixdep archheaders
394 482
395$(OUTPUT)%.o: %.c prepare FORCE 483$(OUTPUT)%.o: %.c prepare FORCE
396 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@ 484 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
@@ -430,7 +518,7 @@ $(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
430 518
431LIBPERF_IN := $(OUTPUT)libperf-in.o 519LIBPERF_IN := $(OUTPUT)libperf-in.o
432 520
433$(LIBPERF_IN): fixdep FORCE 521$(LIBPERF_IN): prepare fixdep FORCE
434 $(Q)$(MAKE) $(build)=libperf 522 $(Q)$(MAKE) $(build)=libperf
435 523
436$(LIB_FILE): $(LIBPERF_IN) 524$(LIB_FILE): $(LIBPERF_IN)
@@ -618,14 +706,14 @@ $(INSTALL_DOC_TARGETS):
618### Cleaning rules 706### Cleaning rules
619 707
620# 708#
621# This is here, not in config/Makefile, because config/Makefile does 709# This is here, not in Makefile.config, because Makefile.config does
622# not get included for the clean target: 710# not get included for the clean target:
623# 711#
624config-clean: 712config-clean:
625 $(call QUIET_CLEAN, config) 713 $(call QUIET_CLEAN, config)
626 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null 714 $(Q)$(MAKE) -C $(srctree)/tools/build/feature/ $(if $(OUTPUT),OUTPUT=$(OUTPUT)feature/,) clean >/dev/null
627 715
628clean: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clean config-clean 716clean:: $(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) 717 $(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' -delete 718 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
631 $(Q)$(RM) $(OUTPUT).config-detected 719 $(Q)$(RM) $(OUTPUT).config-detected
@@ -662,5 +750,5 @@ FORCE:
662.PHONY: all install clean config-clean strip install-gtk 750.PHONY: all install clean config-clean strip install-gtk
663.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell 751.PHONY: shell_compatibility_test please_set_SHELL_PATH_to_a_more_modern_shell
664.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare 752.PHONY: $(GIT-HEAD-PHONY) TAGS tags cscope FORCE prepare
665.PHONY: libtraceevent_plugins 753.PHONY: libtraceevent_plugins archheaders
666 754
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
index d22e3d07de3d..f98da17357c0 100644
--- a/tools/perf/arch/arm/util/Build
+++ b/tools/perf/arch/arm/util/Build
@@ -1,4 +1,4 @@
1libperf-$(CONFIG_DWARF) += dwarf-regs.o 1libperf-$(CONFIG_DWARF) += dwarf-regs.o
2 2
3libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 3libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
4libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 4libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index e58123a8912b..02f41dba4f4f 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -1,2 +1,2 @@
1libperf-$(CONFIG_DWARF) += dwarf-regs.o 1libperf-$(CONFIG_DWARF) += dwarf-regs.o
2libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 2libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/arm64/util/unwind-libunwind.c b/tools/perf/arch/arm64/util/unwind-libunwind.c
index a87afa91a99e..c116b713f7f7 100644
--- a/tools/perf/arch/arm64/util/unwind-libunwind.c
+++ b/tools/perf/arch/arm64/util/unwind-libunwind.c
@@ -1,11 +1,13 @@
1 1
2#ifndef REMOTE_UNWIND_LIBUNWIND
2#include <errno.h> 3#include <errno.h>
3#include <libunwind.h> 4#include <libunwind.h>
4#include "perf_regs.h" 5#include "perf_regs.h"
5#include "../../util/unwind.h" 6#include "../../util/unwind.h"
6#include "../../util/debug.h" 7#include "../../util/debug.h"
8#endif
7 9
8int libunwind__arch_reg_id(int regnum) 10int LIBUNWIND__ARCH_REG_ID(int regnum)
9{ 11{
10 switch (regnum) { 12 switch (regnum) {
11 case UNW_AARCH64_X0: 13 case UNW_AARCH64_X0:
diff --git a/tools/perf/arch/common.c b/tools/perf/arch/common.c
index e83c8ce24303..886dd2aaff0d 100644
--- a/tools/perf/arch/common.c
+++ b/tools/perf/arch/common.c
@@ -1,6 +1,7 @@
1#include <stdio.h> 1#include <stdio.h>
2#include <sys/utsname.h> 2#include <sys/utsname.h>
3#include "common.h" 3#include "common.h"
4#include "../util/util.h"
4#include "../util/debug.h" 5#include "../util/debug.h"
5 6
6const char *const arm_triplets[] = { 7const char *const arm_triplets[] = {
@@ -9,34 +10,44 @@ const char *const arm_triplets[] = {
9 "arm-unknown-linux-", 10 "arm-unknown-linux-",
10 "arm-unknown-linux-gnu-", 11 "arm-unknown-linux-gnu-",
11 "arm-unknown-linux-gnueabi-", 12 "arm-unknown-linux-gnueabi-",
13 "arm-linux-gnu-",
14 "arm-linux-gnueabihf-",
15 "arm-none-eabi-",
12 NULL 16 NULL
13}; 17};
14 18
15const char *const arm64_triplets[] = { 19const char *const arm64_triplets[] = {
16 "aarch64-linux-android-", 20 "aarch64-linux-android-",
21 "aarch64-linux-gnu-",
17 NULL 22 NULL
18}; 23};
19 24
20const char *const powerpc_triplets[] = { 25const char *const powerpc_triplets[] = {
21 "powerpc-unknown-linux-gnu-", 26 "powerpc-unknown-linux-gnu-",
22 "powerpc64-unknown-linux-gnu-", 27 "powerpc64-unknown-linux-gnu-",
28 "powerpc64-linux-gnu-",
29 "powerpc64le-linux-gnu-",
23 NULL 30 NULL
24}; 31};
25 32
26const char *const s390_triplets[] = { 33const char *const s390_triplets[] = {
27 "s390-ibm-linux-", 34 "s390-ibm-linux-",
35 "s390x-linux-gnu-",
28 NULL 36 NULL
29}; 37};
30 38
31const char *const sh_triplets[] = { 39const char *const sh_triplets[] = {
32 "sh-unknown-linux-gnu-", 40 "sh-unknown-linux-gnu-",
33 "sh64-unknown-linux-gnu-", 41 "sh64-unknown-linux-gnu-",
42 "sh-linux-gnu-",
43 "sh64-linux-gnu-",
34 NULL 44 NULL
35}; 45};
36 46
37const char *const sparc_triplets[] = { 47const char *const sparc_triplets[] = {
38 "sparc-unknown-linux-gnu-", 48 "sparc-unknown-linux-gnu-",
39 "sparc64-unknown-linux-gnu-", 49 "sparc64-unknown-linux-gnu-",
50 "sparc64-linux-gnu-",
40 NULL 51 NULL
41}; 52};
42 53
@@ -49,12 +60,19 @@ const char *const x86_triplets[] = {
49 "i386-pc-linux-gnu-", 60 "i386-pc-linux-gnu-",
50 "i686-linux-android-", 61 "i686-linux-android-",
51 "i686-android-linux-", 62 "i686-android-linux-",
63 "x86_64-linux-gnu-",
64 "i586-linux-gnu-",
52 NULL 65 NULL
53}; 66};
54 67
55const char *const mips_triplets[] = { 68const char *const mips_triplets[] = {
56 "mips-unknown-linux-gnu-", 69 "mips-unknown-linux-gnu-",
57 "mipsel-linux-android-", 70 "mipsel-linux-android-",
71 "mips-linux-gnu-",
72 "mips64-linux-gnu-",
73 "mips64el-linux-gnuabi64-",
74 "mips64-linux-gnuabi64-",
75 "mipsel-linux-gnu-",
58 NULL 76 NULL
59}; 77};
60 78
@@ -102,7 +120,7 @@ static int lookup_triplets(const char *const *triplets, const char *name)
102 * Return architecture name in a normalized form. 120 * Return architecture name in a normalized form.
103 * The conversion logic comes from the Makefile. 121 * The conversion logic comes from the Makefile.
104 */ 122 */
105static const char *normalize_arch(char *arch) 123const char *normalize_arch(char *arch)
106{ 124{
107 if (!strcmp(arch, "x86_64")) 125 if (!strcmp(arch, "x86_64"))
108 return "x86"; 126 return "x86";
diff --git a/tools/perf/arch/common.h b/tools/perf/arch/common.h
index 7529cfb143ce..6b01c736b7d9 100644
--- a/tools/perf/arch/common.h
+++ b/tools/perf/arch/common.h
@@ -6,5 +6,6 @@
6extern const char *objdump_path; 6extern const char *objdump_path;
7 7
8int perf_env__lookup_objdump(struct perf_env *env); 8int perf_env__lookup_objdump(struct perf_env *env);
9const char *normalize_arch(char *arch);
9 10
10#endif /* ARCH_PERF_COMMON_H */ 11#endif /* ARCH_PERF_COMMON_H */
diff --git a/tools/perf/arch/powerpc/Makefile b/tools/perf/arch/powerpc/Makefile
index 56e05f126ad8..cc3930904d68 100644
--- a/tools/perf/arch/powerpc/Makefile
+++ b/tools/perf/arch/powerpc/Makefile
@@ -3,4 +3,5 @@ PERF_HAVE_DWARF_REGS := 1
3endif 3endif
4 4
5HAVE_KVM_STAT_SUPPORT := 1 5HAVE_KVM_STAT_SUPPORT := 1
6PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
6PERF_HAVE_JITDUMP := 1 7PERF_HAVE_JITDUMP := 1
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
new file mode 100644
index 000000000000..75de0e92e71e
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -0,0 +1,69 @@
1#ifndef ARCH_PERF_REGS_H
2#define ARCH_PERF_REGS_H
3
4#include <stdlib.h>
5#include <linux/types.h>
6#include <asm/perf_regs.h>
7
8#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_POWERPC_MAX
10#ifdef __powerpc64__
11 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
12#else
13 #define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_32
14#endif
15
16#define PERF_REG_IP PERF_REG_POWERPC_NIP
17#define PERF_REG_SP PERF_REG_POWERPC_R1
18
19static const char *reg_names[] = {
20 [PERF_REG_POWERPC_R0] = "r0",
21 [PERF_REG_POWERPC_R1] = "r1",
22 [PERF_REG_POWERPC_R2] = "r2",
23 [PERF_REG_POWERPC_R3] = "r3",
24 [PERF_REG_POWERPC_R4] = "r4",
25 [PERF_REG_POWERPC_R5] = "r5",
26 [PERF_REG_POWERPC_R6] = "r6",
27 [PERF_REG_POWERPC_R7] = "r7",
28 [PERF_REG_POWERPC_R8] = "r8",
29 [PERF_REG_POWERPC_R9] = "r9",
30 [PERF_REG_POWERPC_R10] = "r10",
31 [PERF_REG_POWERPC_R11] = "r11",
32 [PERF_REG_POWERPC_R12] = "r12",
33 [PERF_REG_POWERPC_R13] = "r13",
34 [PERF_REG_POWERPC_R14] = "r14",
35 [PERF_REG_POWERPC_R15] = "r15",
36 [PERF_REG_POWERPC_R16] = "r16",
37 [PERF_REG_POWERPC_R17] = "r17",
38 [PERF_REG_POWERPC_R18] = "r18",
39 [PERF_REG_POWERPC_R19] = "r19",
40 [PERF_REG_POWERPC_R20] = "r20",
41 [PERF_REG_POWERPC_R21] = "r21",
42 [PERF_REG_POWERPC_R22] = "r22",
43 [PERF_REG_POWERPC_R23] = "r23",
44 [PERF_REG_POWERPC_R24] = "r24",
45 [PERF_REG_POWERPC_R25] = "r25",
46 [PERF_REG_POWERPC_R26] = "r26",
47 [PERF_REG_POWERPC_R27] = "r27",
48 [PERF_REG_POWERPC_R28] = "r28",
49 [PERF_REG_POWERPC_R29] = "r29",
50 [PERF_REG_POWERPC_R30] = "r30",
51 [PERF_REG_POWERPC_R31] = "r31",
52 [PERF_REG_POWERPC_NIP] = "nip",
53 [PERF_REG_POWERPC_MSR] = "msr",
54 [PERF_REG_POWERPC_ORIG_R3] = "orig_r3",
55 [PERF_REG_POWERPC_CTR] = "ctr",
56 [PERF_REG_POWERPC_LINK] = "link",
57 [PERF_REG_POWERPC_XER] = "xer",
58 [PERF_REG_POWERPC_CCR] = "ccr",
59 [PERF_REG_POWERPC_SOFTE] = "softe",
60 [PERF_REG_POWERPC_TRAP] = "trap",
61 [PERF_REG_POWERPC_DAR] = "dar",
62 [PERF_REG_POWERPC_DSISR] = "dsisr"
63};
64
65static inline const char *perf_reg_name(int id)
66{
67 return reg_names[id];
68}
69#endif /* ARCH_PERF_REGS_H */
diff --git a/tools/perf/arch/powerpc/util/Build b/tools/perf/arch/powerpc/util/Build
index c8fe2074d217..90ad64b231cd 100644
--- a/tools/perf/arch/powerpc/util/Build
+++ b/tools/perf/arch/powerpc/util/Build
@@ -1,6 +1,8 @@
1libperf-y += header.o 1libperf-y += header.o
2libperf-y += sym-handling.o 2libperf-y += sym-handling.o
3libperf-y += kvm-stat.o 3libperf-y += kvm-stat.o
4libperf-y += perf_regs.o
4 5
5libperf-$(CONFIG_DWARF) += dwarf-regs.o 6libperf-$(CONFIG_DWARF) += dwarf-regs.o
6libperf-$(CONFIG_DWARF) += skip-callchain-idx.o 7libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
8libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
diff --git a/tools/perf/arch/powerpc/util/dwarf-regs.c b/tools/perf/arch/powerpc/util/dwarf-regs.c
index 733151cdf46e..41bdf9530d82 100644
--- a/tools/perf/arch/powerpc/util/dwarf-regs.c
+++ b/tools/perf/arch/powerpc/util/dwarf-regs.c
@@ -10,19 +10,26 @@
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) #s 26#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[] = {
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)
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}
diff --git a/tools/perf/arch/powerpc/util/perf_regs.c b/tools/perf/arch/powerpc/util/perf_regs.c
new file mode 100644
index 000000000000..a3c3e1ce6807
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/perf_regs.c
@@ -0,0 +1,49 @@
1#include "../../perf.h"
2#include "../../util/perf_regs.h"
3
4const struct sample_reg sample_reg_masks[] = {
5 SMPL_REG(r0, PERF_REG_POWERPC_R0),
6 SMPL_REG(r1, PERF_REG_POWERPC_R1),
7 SMPL_REG(r2, PERF_REG_POWERPC_R2),
8 SMPL_REG(r3, PERF_REG_POWERPC_R3),
9 SMPL_REG(r4, PERF_REG_POWERPC_R4),
10 SMPL_REG(r5, PERF_REG_POWERPC_R5),
11 SMPL_REG(r6, PERF_REG_POWERPC_R6),
12 SMPL_REG(r7, PERF_REG_POWERPC_R7),
13 SMPL_REG(r8, PERF_REG_POWERPC_R8),
14 SMPL_REG(r9, PERF_REG_POWERPC_R9),
15 SMPL_REG(r10, PERF_REG_POWERPC_R10),
16 SMPL_REG(r11, PERF_REG_POWERPC_R11),
17 SMPL_REG(r12, PERF_REG_POWERPC_R12),
18 SMPL_REG(r13, PERF_REG_POWERPC_R13),
19 SMPL_REG(r14, PERF_REG_POWERPC_R14),
20 SMPL_REG(r15, PERF_REG_POWERPC_R15),
21 SMPL_REG(r16, PERF_REG_POWERPC_R16),
22 SMPL_REG(r17, PERF_REG_POWERPC_R17),
23 SMPL_REG(r18, PERF_REG_POWERPC_R18),
24 SMPL_REG(r19, PERF_REG_POWERPC_R19),
25 SMPL_REG(r20, PERF_REG_POWERPC_R20),
26 SMPL_REG(r21, PERF_REG_POWERPC_R21),
27 SMPL_REG(r22, PERF_REG_POWERPC_R22),
28 SMPL_REG(r23, PERF_REG_POWERPC_R23),
29 SMPL_REG(r24, PERF_REG_POWERPC_R24),
30 SMPL_REG(r25, PERF_REG_POWERPC_R25),
31 SMPL_REG(r26, PERF_REG_POWERPC_R26),
32 SMPL_REG(r27, PERF_REG_POWERPC_R27),
33 SMPL_REG(r28, PERF_REG_POWERPC_R28),
34 SMPL_REG(r29, PERF_REG_POWERPC_R29),
35 SMPL_REG(r30, PERF_REG_POWERPC_R30),
36 SMPL_REG(r31, PERF_REG_POWERPC_R31),
37 SMPL_REG(nip, PERF_REG_POWERPC_NIP),
38 SMPL_REG(msr, PERF_REG_POWERPC_MSR),
39 SMPL_REG(orig_r3, PERF_REG_POWERPC_ORIG_R3),
40 SMPL_REG(ctr, PERF_REG_POWERPC_CTR),
41 SMPL_REG(link, PERF_REG_POWERPC_LINK),
42 SMPL_REG(xer, PERF_REG_POWERPC_XER),
43 SMPL_REG(ccr, PERF_REG_POWERPC_CCR),
44 SMPL_REG(softe, PERF_REG_POWERPC_SOFTE),
45 SMPL_REG(trap, PERF_REG_POWERPC_TRAP),
46 SMPL_REG(dar, PERF_REG_POWERPC_DAR),
47 SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
48 SMPL_REG_END
49};
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index bbc1a50768dd..35745a733100 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -19,12 +19,6 @@ bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
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#endif 22#endif
29 23
30#if !defined(_CALL_ELF) || _CALL_ELF != 2 24#if !defined(_CALL_ELF) || _CALL_ELF != 2
@@ -60,23 +54,71 @@ int arch__compare_symbol_names(const char *namea, const char *nameb)
60#endif 54#endif
61 55
62#if defined(_CALL_ELF) && _CALL_ELF == 2 56#if defined(_CALL_ELF) && _CALL_ELF == 2
63bool arch__prefers_symtab(void) 57
58#ifdef HAVE_LIBELF_SUPPORT
59void arch__sym_update(struct symbol *s, GElf_Sym *sym)
64{ 60{
65 return true; 61 s->arch_sym = sym->st_other;
66} 62}
63#endif
67 64
68#define PPC64LE_LEP_OFFSET 8 65#define PPC64LE_LEP_OFFSET 8
69 66
70void arch__fix_tev_from_maps(struct perf_probe_event *pev, 67void arch__fix_tev_from_maps(struct perf_probe_event *pev,
71 struct probe_trace_event *tev, struct map *map) 68 struct probe_trace_event *tev, struct map *map,
69 struct symbol *sym)
72{ 70{
71 int lep_offset;
72
73 /* 73 /*
74 * ppc64 ABIv2 local entry point is currently always 2 instructions 74 * When probing at a function entry point, we normally always want the
75 * (8 bytes) after the global entry point. 75 * LEP since that catches calls to the function through both the GEP and
76 * the LEP. Hence, we would like to probe at an offset of 8 bytes if
77 * the user only specified the function entry.
78 *
79 * However, if the user specifies an offset, we fall back to using the
80 * GEP since all userspace applications (objdump/readelf) show function
81 * disassembly with offsets from the GEP.
82 *
83 * In addition, we shouldn't specify an offset for kretprobes.
76 */ 84 */
77 if (!pev->uprobes && map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) { 85 if (pev->point.offset || pev->point.retprobe || !map || !sym)
78 tev->point.address += PPC64LE_LEP_OFFSET; 86 return;
87
88 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym);
89
90 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS)
79 tev->point.offset += PPC64LE_LEP_OFFSET; 91 tev->point.offset += PPC64LE_LEP_OFFSET;
92 else if (lep_offset) {
93 if (pev->uprobes)
94 tev->point.address += lep_offset;
95 else
96 tev->point.offset += lep_offset;
80 } 97 }
81} 98}
99
100#ifdef HAVE_LIBELF_SUPPORT
101void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
102 int ntevs)
103{
104 struct probe_trace_event *tev;
105 struct map *map;
106 struct symbol *sym = NULL;
107 struct rb_node *tmp;
108 int i = 0;
109
110 map = get_target_map(pev->target, pev->uprobes);
111 if (!map || map__load(map, NULL) < 0)
112 return;
113
114 for (i = 0; i < ntevs; i++) {
115 tev = &pev->tevs[i];
116 map__for_each_symbol(map, sym, tmp) {
117 if (map->unmap_ip(map, sym->start) == tev->point.address)
118 arch__fix_tev_from_maps(pev, tev, map, sym);
119 }
120 }
121}
122#endif /* HAVE_LIBELF_SUPPORT */
123
82#endif 124#endif
diff --git a/tools/perf/arch/powerpc/util/unwind-libunwind.c b/tools/perf/arch/powerpc/util/unwind-libunwind.c
new file mode 100644
index 000000000000..9e15f92ae49f
--- /dev/null
+++ b/tools/perf/arch/powerpc/util/unwind-libunwind.c
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2016 Chandan Kumar, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <errno.h>
11#include <libunwind.h>
12#include <asm/perf_regs.h>
13#include "../../util/unwind.h"
14#include "../../util/debug.h"
15
16int libunwind__arch_reg_id(int regnum)
17{
18 switch (regnum) {
19 case UNW_PPC64_R0:
20 return PERF_REG_POWERPC_R0;
21 case UNW_PPC64_R1:
22 return PERF_REG_POWERPC_R1;
23 case UNW_PPC64_R2:
24 return PERF_REG_POWERPC_R2;
25 case UNW_PPC64_R3:
26 return PERF_REG_POWERPC_R3;
27 case UNW_PPC64_R4:
28 return PERF_REG_POWERPC_R4;
29 case UNW_PPC64_R5:
30 return PERF_REG_POWERPC_R5;
31 case UNW_PPC64_R6:
32 return PERF_REG_POWERPC_R6;
33 case UNW_PPC64_R7:
34 return PERF_REG_POWERPC_R7;
35 case UNW_PPC64_R8:
36 return PERF_REG_POWERPC_R8;
37 case UNW_PPC64_R9:
38 return PERF_REG_POWERPC_R9;
39 case UNW_PPC64_R10:
40 return PERF_REG_POWERPC_R10;
41 case UNW_PPC64_R11:
42 return PERF_REG_POWERPC_R11;
43 case UNW_PPC64_R12:
44 return PERF_REG_POWERPC_R12;
45 case UNW_PPC64_R13:
46 return PERF_REG_POWERPC_R13;
47 case UNW_PPC64_R14:
48 return PERF_REG_POWERPC_R14;
49 case UNW_PPC64_R15:
50 return PERF_REG_POWERPC_R15;
51 case UNW_PPC64_R16:
52 return PERF_REG_POWERPC_R16;
53 case UNW_PPC64_R17:
54 return PERF_REG_POWERPC_R17;
55 case UNW_PPC64_R18:
56 return PERF_REG_POWERPC_R18;
57 case UNW_PPC64_R19:
58 return PERF_REG_POWERPC_R19;
59 case UNW_PPC64_R20:
60 return PERF_REG_POWERPC_R20;
61 case UNW_PPC64_R21:
62 return PERF_REG_POWERPC_R21;
63 case UNW_PPC64_R22:
64 return PERF_REG_POWERPC_R22;
65 case UNW_PPC64_R23:
66 return PERF_REG_POWERPC_R23;
67 case UNW_PPC64_R24:
68 return PERF_REG_POWERPC_R24;
69 case UNW_PPC64_R25:
70 return PERF_REG_POWERPC_R25;
71 case UNW_PPC64_R26:
72 return PERF_REG_POWERPC_R26;
73 case UNW_PPC64_R27:
74 return PERF_REG_POWERPC_R27;
75 case UNW_PPC64_R28:
76 return PERF_REG_POWERPC_R28;
77 case UNW_PPC64_R29:
78 return PERF_REG_POWERPC_R29;
79 case UNW_PPC64_R30:
80 return PERF_REG_POWERPC_R30;
81 case UNW_PPC64_R31:
82 return PERF_REG_POWERPC_R31;
83 case UNW_PPC64_LR:
84 return PERF_REG_POWERPC_LINK;
85 case UNW_PPC64_CTR:
86 return PERF_REG_POWERPC_CTR;
87 case UNW_PPC64_XER:
88 return PERF_REG_POWERPC_XER;
89 case UNW_PPC64_NIP:
90 return PERF_REG_POWERPC_NIP;
91 default:
92 pr_err("unwind: invalid reg id %d\n", regnum);
93 return -EINVAL;
94 }
95 return -EINVAL;
96}
diff --git a/tools/perf/arch/s390/util/Build b/tools/perf/arch/s390/util/Build
index 8a61372bb47a..5bd7b9260cc0 100644
--- a/tools/perf/arch/s390/util/Build
+++ b/tools/perf/arch/s390/util/Build
@@ -2,3 +2,5 @@ libperf-y += header.o
2libperf-y += kvm-stat.o 2libperf-y += kvm-stat.o
3 3
4libperf-$(CONFIG_DWARF) += dwarf-regs.o 4libperf-$(CONFIG_DWARF) += dwarf-regs.o
5
6libperf-y += machine.o
diff --git a/tools/perf/arch/s390/util/machine.c b/tools/perf/arch/s390/util/machine.c
new file mode 100644
index 000000000000..b9a95a1a8e69
--- /dev/null
+++ b/tools/perf/arch/s390/util/machine.c
@@ -0,0 +1,19 @@
1#include <unistd.h>
2#include <stdio.h>
3#include <string.h>
4#include "util.h"
5#include "machine.h"
6#include "api/fs/fs.h"
7
8int arch__fix_module_text_start(u64 *start, const char *name)
9{
10 char path[PATH_MAX];
11
12 snprintf(path, PATH_MAX, "module/%.*s/sections/.text",
13 (int)strlen(name) - 2, name + 1);
14
15 if (sysfs__read_ull(path, (unsigned long long *)start) < 0)
16 return -1;
17
18 return 0;
19}
diff --git a/tools/perf/arch/x86/Makefile b/tools/perf/arch/x86/Makefile
index 269af2143735..6c9211b18ec0 100644
--- a/tools/perf/arch/x86/Makefile
+++ b/tools/perf/arch/x86/Makefile
@@ -4,3 +4,26 @@ endif
4HAVE_KVM_STAT_SUPPORT := 1 4HAVE_KVM_STAT_SUPPORT := 1
5PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1 5PERF_HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET := 1
6PERF_HAVE_JITDUMP := 1 6PERF_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)
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
new file mode 100644
index 000000000000..555263e385c9
--- /dev/null
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -0,0 +1,378 @@
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
377534 x32 preadv2 compat_sys_preadv2
378535 x32 pwritev2 compat_sys_pwritev2
diff --git a/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
new file mode 100755
index 000000000000..49a18b9ad9cf
--- /dev/null
+++ b/tools/perf/arch/x86/entry/syscalls/syscalltbl.sh
@@ -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}"
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-32.c b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
index 3b491cfe204e..0f196eec9f48 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-32.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-32.c
@@ -6,6 +6,1016 @@
6 6
7{{0x0f, 0x31, }, 2, 0, "", "", 7{{0x0f, 0x31, }, 2, 0, "", "",
8"0f 31 \trdtsc ",}, 8"0f 31 \trdtsc ",},
9{{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "",
10"c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",},
11{{0x62, 0x81, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
12"62 81 78 56 34 12 \tbound %eax,0x12345678(%ecx)",},
13{{0x62, 0x88, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
14"62 88 78 56 34 12 \tbound %ecx,0x12345678(%eax)",},
15{{0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
16"62 90 78 56 34 12 \tbound %edx,0x12345678(%eax)",},
17{{0x62, 0x98, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
18"62 98 78 56 34 12 \tbound %ebx,0x12345678(%eax)",},
19{{0x62, 0xa0, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
20"62 a0 78 56 34 12 \tbound %esp,0x12345678(%eax)",},
21{{0x62, 0xa8, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
22"62 a8 78 56 34 12 \tbound %ebp,0x12345678(%eax)",},
23{{0x62, 0xb0, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
24"62 b0 78 56 34 12 \tbound %esi,0x12345678(%eax)",},
25{{0x62, 0xb8, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
26"62 b8 78 56 34 12 \tbound %edi,0x12345678(%eax)",},
27{{0x62, 0x08, }, 2, 0, "", "",
28"62 08 \tbound %ecx,(%eax)",},
29{{0x62, 0x05, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
30"62 05 78 56 34 12 \tbound %eax,0x12345678",},
31{{0x62, 0x14, 0x01, }, 3, 0, "", "",
32"62 14 01 \tbound %edx,(%ecx,%eax,1)",},
33{{0x62, 0x14, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
34"62 14 05 78 56 34 12 \tbound %edx,0x12345678(,%eax,1)",},
35{{0x62, 0x14, 0x08, }, 3, 0, "", "",
36"62 14 08 \tbound %edx,(%eax,%ecx,1)",},
37{{0x62, 0x14, 0xc8, }, 3, 0, "", "",
38"62 14 c8 \tbound %edx,(%eax,%ecx,8)",},
39{{0x62, 0x50, 0x12, }, 3, 0, "", "",
40"62 50 12 \tbound %edx,0x12(%eax)",},
41{{0x62, 0x55, 0x12, }, 3, 0, "", "",
42"62 55 12 \tbound %edx,0x12(%ebp)",},
43{{0x62, 0x54, 0x01, 0x12, }, 4, 0, "", "",
44"62 54 01 12 \tbound %edx,0x12(%ecx,%eax,1)",},
45{{0x62, 0x54, 0x05, 0x12, }, 4, 0, "", "",
46"62 54 05 12 \tbound %edx,0x12(%ebp,%eax,1)",},
47{{0x62, 0x54, 0x08, 0x12, }, 4, 0, "", "",
48"62 54 08 12 \tbound %edx,0x12(%eax,%ecx,1)",},
49{{0x62, 0x54, 0xc8, 0x12, }, 4, 0, "", "",
50"62 54 c8 12 \tbound %edx,0x12(%eax,%ecx,8)",},
51{{0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
52"62 90 78 56 34 12 \tbound %edx,0x12345678(%eax)",},
53{{0x62, 0x95, 0x78, 0x56, 0x34, 0x12, }, 6, 0, "", "",
54"62 95 78 56 34 12 \tbound %edx,0x12345678(%ebp)",},
55{{0x62, 0x94, 0x01, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
56"62 94 01 78 56 34 12 \tbound %edx,0x12345678(%ecx,%eax,1)",},
57{{0x62, 0x94, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
58"62 94 05 78 56 34 12 \tbound %edx,0x12345678(%ebp,%eax,1)",},
59{{0x62, 0x94, 0x08, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
60"62 94 08 78 56 34 12 \tbound %edx,0x12345678(%eax,%ecx,1)",},
61{{0x62, 0x94, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
62"62 94 c8 78 56 34 12 \tbound %edx,0x12345678(%eax,%ecx,8)",},
63{{0x66, 0x62, 0x81, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
64"66 62 81 78 56 34 12 \tbound %ax,0x12345678(%ecx)",},
65{{0x66, 0x62, 0x88, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
66"66 62 88 78 56 34 12 \tbound %cx,0x12345678(%eax)",},
67{{0x66, 0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
68"66 62 90 78 56 34 12 \tbound %dx,0x12345678(%eax)",},
69{{0x66, 0x62, 0x98, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
70"66 62 98 78 56 34 12 \tbound %bx,0x12345678(%eax)",},
71{{0x66, 0x62, 0xa0, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
72"66 62 a0 78 56 34 12 \tbound %sp,0x12345678(%eax)",},
73{{0x66, 0x62, 0xa8, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
74"66 62 a8 78 56 34 12 \tbound %bp,0x12345678(%eax)",},
75{{0x66, 0x62, 0xb0, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
76"66 62 b0 78 56 34 12 \tbound %si,0x12345678(%eax)",},
77{{0x66, 0x62, 0xb8, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
78"66 62 b8 78 56 34 12 \tbound %di,0x12345678(%eax)",},
79{{0x66, 0x62, 0x08, }, 3, 0, "", "",
80"66 62 08 \tbound %cx,(%eax)",},
81{{0x66, 0x62, 0x05, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
82"66 62 05 78 56 34 12 \tbound %ax,0x12345678",},
83{{0x66, 0x62, 0x14, 0x01, }, 4, 0, "", "",
84"66 62 14 01 \tbound %dx,(%ecx,%eax,1)",},
85{{0x66, 0x62, 0x14, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
86"66 62 14 05 78 56 34 12 \tbound %dx,0x12345678(,%eax,1)",},
87{{0x66, 0x62, 0x14, 0x08, }, 4, 0, "", "",
88"66 62 14 08 \tbound %dx,(%eax,%ecx,1)",},
89{{0x66, 0x62, 0x14, 0xc8, }, 4, 0, "", "",
90"66 62 14 c8 \tbound %dx,(%eax,%ecx,8)",},
91{{0x66, 0x62, 0x50, 0x12, }, 4, 0, "", "",
92"66 62 50 12 \tbound %dx,0x12(%eax)",},
93{{0x66, 0x62, 0x55, 0x12, }, 4, 0, "", "",
94"66 62 55 12 \tbound %dx,0x12(%ebp)",},
95{{0x66, 0x62, 0x54, 0x01, 0x12, }, 5, 0, "", "",
96"66 62 54 01 12 \tbound %dx,0x12(%ecx,%eax,1)",},
97{{0x66, 0x62, 0x54, 0x05, 0x12, }, 5, 0, "", "",
98"66 62 54 05 12 \tbound %dx,0x12(%ebp,%eax,1)",},
99{{0x66, 0x62, 0x54, 0x08, 0x12, }, 5, 0, "", "",
100"66 62 54 08 12 \tbound %dx,0x12(%eax,%ecx,1)",},
101{{0x66, 0x62, 0x54, 0xc8, 0x12, }, 5, 0, "", "",
102"66 62 54 c8 12 \tbound %dx,0x12(%eax,%ecx,8)",},
103{{0x66, 0x62, 0x90, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
104"66 62 90 78 56 34 12 \tbound %dx,0x12345678(%eax)",},
105{{0x66, 0x62, 0x95, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
106"66 62 95 78 56 34 12 \tbound %dx,0x12345678(%ebp)",},
107{{0x66, 0x62, 0x94, 0x01, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
108"66 62 94 01 78 56 34 12 \tbound %dx,0x12345678(%ecx,%eax,1)",},
109{{0x66, 0x62, 0x94, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
110"66 62 94 05 78 56 34 12 \tbound %dx,0x12345678(%ebp,%eax,1)",},
111{{0x66, 0x62, 0x94, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
112"66 62 94 08 78 56 34 12 \tbound %dx,0x12345678(%eax,%ecx,1)",},
113{{0x66, 0x62, 0x94, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
114"66 62 94 c8 78 56 34 12 \tbound %dx,0x12345678(%eax,%ecx,8)",},
115{{0x0f, 0x41, 0xd8, }, 3, 0, "", "",
116"0f 41 d8 \tcmovno %eax,%ebx",},
117{{0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
118"0f 41 88 78 56 34 12 \tcmovno 0x12345678(%eax),%ecx",},
119{{0x66, 0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
120"66 0f 41 88 78 56 34 12 \tcmovno 0x12345678(%eax),%cx",},
121{{0x0f, 0x44, 0xd8, }, 3, 0, "", "",
122"0f 44 d8 \tcmove %eax,%ebx",},
123{{0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
124"0f 44 88 78 56 34 12 \tcmove 0x12345678(%eax),%ecx",},
125{{0x66, 0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
126"66 0f 44 88 78 56 34 12 \tcmove 0x12345678(%eax),%cx",},
127{{0x0f, 0x90, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
128"0f 90 80 78 56 34 12 \tseto 0x12345678(%eax)",},
129{{0x0f, 0x91, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
130"0f 91 80 78 56 34 12 \tsetno 0x12345678(%eax)",},
131{{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
132"0f 92 80 78 56 34 12 \tsetb 0x12345678(%eax)",},
133{{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
134"0f 92 80 78 56 34 12 \tsetb 0x12345678(%eax)",},
135{{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
136"0f 92 80 78 56 34 12 \tsetb 0x12345678(%eax)",},
137{{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
138"0f 93 80 78 56 34 12 \tsetae 0x12345678(%eax)",},
139{{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
140"0f 93 80 78 56 34 12 \tsetae 0x12345678(%eax)",},
141{{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
142"0f 93 80 78 56 34 12 \tsetae 0x12345678(%eax)",},
143{{0x0f, 0x98, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
144"0f 98 80 78 56 34 12 \tsets 0x12345678(%eax)",},
145{{0x0f, 0x99, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
146"0f 99 80 78 56 34 12 \tsetns 0x12345678(%eax)",},
147{{0xc5, 0xcc, 0x41, 0xef, }, 4, 0, "", "",
148"c5 cc 41 ef \tkandw %k7,%k6,%k5",},
149{{0xc4, 0xe1, 0xcc, 0x41, 0xef, }, 5, 0, "", "",
150"c4 e1 cc 41 ef \tkandq %k7,%k6,%k5",},
151{{0xc5, 0xcd, 0x41, 0xef, }, 4, 0, "", "",
152"c5 cd 41 ef \tkandb %k7,%k6,%k5",},
153{{0xc4, 0xe1, 0xcd, 0x41, 0xef, }, 5, 0, "", "",
154"c4 e1 cd 41 ef \tkandd %k7,%k6,%k5",},
155{{0xc5, 0xcc, 0x42, 0xef, }, 4, 0, "", "",
156"c5 cc 42 ef \tkandnw %k7,%k6,%k5",},
157{{0xc4, 0xe1, 0xcc, 0x42, 0xef, }, 5, 0, "", "",
158"c4 e1 cc 42 ef \tkandnq %k7,%k6,%k5",},
159{{0xc5, 0xcd, 0x42, 0xef, }, 4, 0, "", "",
160"c5 cd 42 ef \tkandnb %k7,%k6,%k5",},
161{{0xc4, 0xe1, 0xcd, 0x42, 0xef, }, 5, 0, "", "",
162"c4 e1 cd 42 ef \tkandnd %k7,%k6,%k5",},
163{{0xc5, 0xf8, 0x44, 0xf7, }, 4, 0, "", "",
164"c5 f8 44 f7 \tknotw %k7,%k6",},
165{{0xc4, 0xe1, 0xf8, 0x44, 0xf7, }, 5, 0, "", "",
166"c4 e1 f8 44 f7 \tknotq %k7,%k6",},
167{{0xc5, 0xf9, 0x44, 0xf7, }, 4, 0, "", "",
168"c5 f9 44 f7 \tknotb %k7,%k6",},
169{{0xc4, 0xe1, 0xf9, 0x44, 0xf7, }, 5, 0, "", "",
170"c4 e1 f9 44 f7 \tknotd %k7,%k6",},
171{{0xc5, 0xcc, 0x45, 0xef, }, 4, 0, "", "",
172"c5 cc 45 ef \tkorw %k7,%k6,%k5",},
173{{0xc4, 0xe1, 0xcc, 0x45, 0xef, }, 5, 0, "", "",
174"c4 e1 cc 45 ef \tkorq %k7,%k6,%k5",},
175{{0xc5, 0xcd, 0x45, 0xef, }, 4, 0, "", "",
176"c5 cd 45 ef \tkorb %k7,%k6,%k5",},
177{{0xc4, 0xe1, 0xcd, 0x45, 0xef, }, 5, 0, "", "",
178"c4 e1 cd 45 ef \tkord %k7,%k6,%k5",},
179{{0xc5, 0xcc, 0x46, 0xef, }, 4, 0, "", "",
180"c5 cc 46 ef \tkxnorw %k7,%k6,%k5",},
181{{0xc4, 0xe1, 0xcc, 0x46, 0xef, }, 5, 0, "", "",
182"c4 e1 cc 46 ef \tkxnorq %k7,%k6,%k5",},
183{{0xc5, 0xcd, 0x46, 0xef, }, 4, 0, "", "",
184"c5 cd 46 ef \tkxnorb %k7,%k6,%k5",},
185{{0xc4, 0xe1, 0xcd, 0x46, 0xef, }, 5, 0, "", "",
186"c4 e1 cd 46 ef \tkxnord %k7,%k6,%k5",},
187{{0xc5, 0xcc, 0x47, 0xef, }, 4, 0, "", "",
188"c5 cc 47 ef \tkxorw %k7,%k6,%k5",},
189{{0xc4, 0xe1, 0xcc, 0x47, 0xef, }, 5, 0, "", "",
190"c4 e1 cc 47 ef \tkxorq %k7,%k6,%k5",},
191{{0xc5, 0xcd, 0x47, 0xef, }, 4, 0, "", "",
192"c5 cd 47 ef \tkxorb %k7,%k6,%k5",},
193{{0xc4, 0xe1, 0xcd, 0x47, 0xef, }, 5, 0, "", "",
194"c4 e1 cd 47 ef \tkxord %k7,%k6,%k5",},
195{{0xc5, 0xcc, 0x4a, 0xef, }, 4, 0, "", "",
196"c5 cc 4a ef \tkaddw %k7,%k6,%k5",},
197{{0xc4, 0xe1, 0xcc, 0x4a, 0xef, }, 5, 0, "", "",
198"c4 e1 cc 4a ef \tkaddq %k7,%k6,%k5",},
199{{0xc5, 0xcd, 0x4a, 0xef, }, 4, 0, "", "",
200"c5 cd 4a ef \tkaddb %k7,%k6,%k5",},
201{{0xc4, 0xe1, 0xcd, 0x4a, 0xef, }, 5, 0, "", "",
202"c4 e1 cd 4a ef \tkaddd %k7,%k6,%k5",},
203{{0xc5, 0xcd, 0x4b, 0xef, }, 4, 0, "", "",
204"c5 cd 4b ef \tkunpckbw %k7,%k6,%k5",},
205{{0xc5, 0xcc, 0x4b, 0xef, }, 4, 0, "", "",
206"c5 cc 4b ef \tkunpckwd %k7,%k6,%k5",},
207{{0xc4, 0xe1, 0xcc, 0x4b, 0xef, }, 5, 0, "", "",
208"c4 e1 cc 4b ef \tkunpckdq %k7,%k6,%k5",},
209{{0xc5, 0xf8, 0x90, 0xee, }, 4, 0, "", "",
210"c5 f8 90 ee \tkmovw %k6,%k5",},
211{{0xc5, 0xf8, 0x90, 0x29, }, 4, 0, "", "",
212"c5 f8 90 29 \tkmovw (%ecx),%k5",},
213{{0xc5, 0xf8, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "",
214"c5 f8 90 ac c8 23 01 00 00 \tkmovw 0x123(%eax,%ecx,8),%k5",},
215{{0xc5, 0xf8, 0x91, 0x29, }, 4, 0, "", "",
216"c5 f8 91 29 \tkmovw %k5,(%ecx)",},
217{{0xc5, 0xf8, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "",
218"c5 f8 91 ac c8 23 01 00 00 \tkmovw %k5,0x123(%eax,%ecx,8)",},
219{{0xc5, 0xf8, 0x92, 0xe8, }, 4, 0, "", "",
220"c5 f8 92 e8 \tkmovw %eax,%k5",},
221{{0xc5, 0xf8, 0x92, 0xed, }, 4, 0, "", "",
222"c5 f8 92 ed \tkmovw %ebp,%k5",},
223{{0xc5, 0xf8, 0x93, 0xc5, }, 4, 0, "", "",
224"c5 f8 93 c5 \tkmovw %k5,%eax",},
225{{0xc5, 0xf8, 0x93, 0xed, }, 4, 0, "", "",
226"c5 f8 93 ed \tkmovw %k5,%ebp",},
227{{0xc4, 0xe1, 0xf8, 0x90, 0xee, }, 5, 0, "", "",
228"c4 e1 f8 90 ee \tkmovq %k6,%k5",},
229{{0xc4, 0xe1, 0xf8, 0x90, 0x29, }, 5, 0, "", "",
230"c4 e1 f8 90 29 \tkmovq (%ecx),%k5",},
231{{0xc4, 0xe1, 0xf8, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
232"c4 e1 f8 90 ac c8 23 01 00 00 \tkmovq 0x123(%eax,%ecx,8),%k5",},
233{{0xc4, 0xe1, 0xf8, 0x91, 0x29, }, 5, 0, "", "",
234"c4 e1 f8 91 29 \tkmovq %k5,(%ecx)",},
235{{0xc4, 0xe1, 0xf8, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
236"c4 e1 f8 91 ac c8 23 01 00 00 \tkmovq %k5,0x123(%eax,%ecx,8)",},
237{{0xc5, 0xf9, 0x90, 0xee, }, 4, 0, "", "",
238"c5 f9 90 ee \tkmovb %k6,%k5",},
239{{0xc5, 0xf9, 0x90, 0x29, }, 4, 0, "", "",
240"c5 f9 90 29 \tkmovb (%ecx),%k5",},
241{{0xc5, 0xf9, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "",
242"c5 f9 90 ac c8 23 01 00 00 \tkmovb 0x123(%eax,%ecx,8),%k5",},
243{{0xc5, 0xf9, 0x91, 0x29, }, 4, 0, "", "",
244"c5 f9 91 29 \tkmovb %k5,(%ecx)",},
245{{0xc5, 0xf9, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 9, 0, "", "",
246"c5 f9 91 ac c8 23 01 00 00 \tkmovb %k5,0x123(%eax,%ecx,8)",},
247{{0xc5, 0xf9, 0x92, 0xe8, }, 4, 0, "", "",
248"c5 f9 92 e8 \tkmovb %eax,%k5",},
249{{0xc5, 0xf9, 0x92, 0xed, }, 4, 0, "", "",
250"c5 f9 92 ed \tkmovb %ebp,%k5",},
251{{0xc5, 0xf9, 0x93, 0xc5, }, 4, 0, "", "",
252"c5 f9 93 c5 \tkmovb %k5,%eax",},
253{{0xc5, 0xf9, 0x93, 0xed, }, 4, 0, "", "",
254"c5 f9 93 ed \tkmovb %k5,%ebp",},
255{{0xc4, 0xe1, 0xf9, 0x90, 0xee, }, 5, 0, "", "",
256"c4 e1 f9 90 ee \tkmovd %k6,%k5",},
257{{0xc4, 0xe1, 0xf9, 0x90, 0x29, }, 5, 0, "", "",
258"c4 e1 f9 90 29 \tkmovd (%ecx),%k5",},
259{{0xc4, 0xe1, 0xf9, 0x90, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
260"c4 e1 f9 90 ac c8 23 01 00 00 \tkmovd 0x123(%eax,%ecx,8),%k5",},
261{{0xc4, 0xe1, 0xf9, 0x91, 0x29, }, 5, 0, "", "",
262"c4 e1 f9 91 29 \tkmovd %k5,(%ecx)",},
263{{0xc4, 0xe1, 0xf9, 0x91, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
264"c4 e1 f9 91 ac c8 23 01 00 00 \tkmovd %k5,0x123(%eax,%ecx,8)",},
265{{0xc5, 0xfb, 0x92, 0xe8, }, 4, 0, "", "",
266"c5 fb 92 e8 \tkmovd %eax,%k5",},
267{{0xc5, 0xfb, 0x92, 0xed, }, 4, 0, "", "",
268"c5 fb 92 ed \tkmovd %ebp,%k5",},
269{{0xc5, 0xfb, 0x93, 0xc5, }, 4, 0, "", "",
270"c5 fb 93 c5 \tkmovd %k5,%eax",},
271{{0xc5, 0xfb, 0x93, 0xed, }, 4, 0, "", "",
272"c5 fb 93 ed \tkmovd %k5,%ebp",},
273{{0xc5, 0xf8, 0x98, 0xee, }, 4, 0, "", "",
274"c5 f8 98 ee \tkortestw %k6,%k5",},
275{{0xc4, 0xe1, 0xf8, 0x98, 0xee, }, 5, 0, "", "",
276"c4 e1 f8 98 ee \tkortestq %k6,%k5",},
277{{0xc5, 0xf9, 0x98, 0xee, }, 4, 0, "", "",
278"c5 f9 98 ee \tkortestb %k6,%k5",},
279{{0xc4, 0xe1, 0xf9, 0x98, 0xee, }, 5, 0, "", "",
280"c4 e1 f9 98 ee \tkortestd %k6,%k5",},
281{{0xc5, 0xf8, 0x99, 0xee, }, 4, 0, "", "",
282"c5 f8 99 ee \tktestw %k6,%k5",},
283{{0xc4, 0xe1, 0xf8, 0x99, 0xee, }, 5, 0, "", "",
284"c4 e1 f8 99 ee \tktestq %k6,%k5",},
285{{0xc5, 0xf9, 0x99, 0xee, }, 4, 0, "", "",
286"c5 f9 99 ee \tktestb %k6,%k5",},
287{{0xc4, 0xe1, 0xf9, 0x99, 0xee, }, 5, 0, "", "",
288"c4 e1 f9 99 ee \tktestd %k6,%k5",},
289{{0xc4, 0xe3, 0xf9, 0x30, 0xee, 0x12, }, 6, 0, "", "",
290"c4 e3 f9 30 ee 12 \tkshiftrw $0x12,%k6,%k5",},
291{{0xc4, 0xe3, 0xf9, 0x31, 0xee, 0x5b, }, 6, 0, "", "",
292"c4 e3 f9 31 ee 5b \tkshiftrq $0x5b,%k6,%k5",},
293{{0xc4, 0xe3, 0xf9, 0x32, 0xee, 0x12, }, 6, 0, "", "",
294"c4 e3 f9 32 ee 12 \tkshiftlw $0x12,%k6,%k5",},
295{{0xc4, 0xe3, 0xf9, 0x33, 0xee, 0x5b, }, 6, 0, "", "",
296"c4 e3 f9 33 ee 5b \tkshiftlq $0x5b,%k6,%k5",},
297{{0xc5, 0xf8, 0x5b, 0xf5, }, 4, 0, "", "",
298"c5 f8 5b f5 \tvcvtdq2ps %xmm5,%xmm6",},
299{{0x62, 0xf1, 0xfc, 0x4f, 0x5b, 0xf5, }, 6, 0, "", "",
300"62 f1 fc 4f 5b f5 \tvcvtqq2ps %zmm5,%ymm6{%k7}",},
301{{0xc5, 0xf9, 0x5b, 0xf5, }, 4, 0, "", "",
302"c5 f9 5b f5 \tvcvtps2dq %xmm5,%xmm6",},
303{{0xc5, 0xfa, 0x5b, 0xf5, }, 4, 0, "", "",
304"c5 fa 5b f5 \tvcvttps2dq %xmm5,%xmm6",},
305{{0x0f, 0x6f, 0xe0, }, 3, 0, "", "",
306"0f 6f e0 \tmovq %mm0,%mm4",},
307{{0xc5, 0xfd, 0x6f, 0xf4, }, 4, 0, "", "",
308"c5 fd 6f f4 \tvmovdqa %ymm4,%ymm6",},
309{{0x62, 0xf1, 0x7d, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
310"62 f1 7d 48 6f f5 \tvmovdqa32 %zmm5,%zmm6",},
311{{0x62, 0xf1, 0xfd, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
312"62 f1 fd 48 6f f5 \tvmovdqa64 %zmm5,%zmm6",},
313{{0xc5, 0xfe, 0x6f, 0xf4, }, 4, 0, "", "",
314"c5 fe 6f f4 \tvmovdqu %ymm4,%ymm6",},
315{{0x62, 0xf1, 0x7e, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
316"62 f1 7e 48 6f f5 \tvmovdqu32 %zmm5,%zmm6",},
317{{0x62, 0xf1, 0xfe, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
318"62 f1 fe 48 6f f5 \tvmovdqu64 %zmm5,%zmm6",},
319{{0x62, 0xf1, 0x7f, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
320"62 f1 7f 48 6f f5 \tvmovdqu8 %zmm5,%zmm6",},
321{{0x62, 0xf1, 0xff, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
322"62 f1 ff 48 6f f5 \tvmovdqu16 %zmm5,%zmm6",},
323{{0x0f, 0x78, 0xc3, }, 3, 0, "", "",
324"0f 78 c3 \tvmread %eax,%ebx",},
325{{0x62, 0xf1, 0x7c, 0x48, 0x78, 0xf5, }, 6, 0, "", "",
326"62 f1 7c 48 78 f5 \tvcvttps2udq %zmm5,%zmm6",},
327{{0x62, 0xf1, 0xfc, 0x4f, 0x78, 0xf5, }, 6, 0, "", "",
328"62 f1 fc 4f 78 f5 \tvcvttpd2udq %zmm5,%ymm6{%k7}",},
329{{0x62, 0xf1, 0x7f, 0x08, 0x78, 0xc6, }, 6, 0, "", "",
330"62 f1 7f 08 78 c6 \tvcvttsd2usi %xmm6,%eax",},
331{{0x62, 0xf1, 0x7e, 0x08, 0x78, 0xc6, }, 6, 0, "", "",
332"62 f1 7e 08 78 c6 \tvcvttss2usi %xmm6,%eax",},
333{{0x62, 0xf1, 0x7d, 0x4f, 0x78, 0xf5, }, 6, 0, "", "",
334"62 f1 7d 4f 78 f5 \tvcvttps2uqq %ymm5,%zmm6{%k7}",},
335{{0x62, 0xf1, 0xfd, 0x48, 0x78, 0xf5, }, 6, 0, "", "",
336"62 f1 fd 48 78 f5 \tvcvttpd2uqq %zmm5,%zmm6",},
337{{0x0f, 0x79, 0xd8, }, 3, 0, "", "",
338"0f 79 d8 \tvmwrite %eax,%ebx",},
339{{0x62, 0xf1, 0x7c, 0x48, 0x79, 0xf5, }, 6, 0, "", "",
340"62 f1 7c 48 79 f5 \tvcvtps2udq %zmm5,%zmm6",},
341{{0x62, 0xf1, 0xfc, 0x4f, 0x79, 0xf5, }, 6, 0, "", "",
342"62 f1 fc 4f 79 f5 \tvcvtpd2udq %zmm5,%ymm6{%k7}",},
343{{0x62, 0xf1, 0x7f, 0x08, 0x79, 0xc6, }, 6, 0, "", "",
344"62 f1 7f 08 79 c6 \tvcvtsd2usi %xmm6,%eax",},
345{{0x62, 0xf1, 0x7e, 0x08, 0x79, 0xc6, }, 6, 0, "", "",
346"62 f1 7e 08 79 c6 \tvcvtss2usi %xmm6,%eax",},
347{{0x62, 0xf1, 0x7d, 0x4f, 0x79, 0xf5, }, 6, 0, "", "",
348"62 f1 7d 4f 79 f5 \tvcvtps2uqq %ymm5,%zmm6{%k7}",},
349{{0x62, 0xf1, 0xfd, 0x48, 0x79, 0xf5, }, 6, 0, "", "",
350"62 f1 fd 48 79 f5 \tvcvtpd2uqq %zmm5,%zmm6",},
351{{0x62, 0xf1, 0x7e, 0x4f, 0x7a, 0xf5, }, 6, 0, "", "",
352"62 f1 7e 4f 7a f5 \tvcvtudq2pd %ymm5,%zmm6{%k7}",},
353{{0x62, 0xf1, 0xfe, 0x48, 0x7a, 0xf5, }, 6, 0, "", "",
354"62 f1 fe 48 7a f5 \tvcvtuqq2pd %zmm5,%zmm6",},
355{{0x62, 0xf1, 0x7f, 0x48, 0x7a, 0xf5, }, 6, 0, "", "",
356"62 f1 7f 48 7a f5 \tvcvtudq2ps %zmm5,%zmm6",},
357{{0x62, 0xf1, 0xff, 0x4f, 0x7a, 0xf5, }, 6, 0, "", "",
358"62 f1 ff 4f 7a f5 \tvcvtuqq2ps %zmm5,%ymm6{%k7}",},
359{{0x62, 0xf1, 0x7d, 0x4f, 0x7a, 0xf5, }, 6, 0, "", "",
360"62 f1 7d 4f 7a f5 \tvcvttps2qq %ymm5,%zmm6{%k7}",},
361{{0x62, 0xf1, 0xfd, 0x48, 0x7a, 0xf5, }, 6, 0, "", "",
362"62 f1 fd 48 7a f5 \tvcvttpd2qq %zmm5,%zmm6",},
363{{0x62, 0xf1, 0x57, 0x08, 0x7b, 0xf0, }, 6, 0, "", "",
364"62 f1 57 08 7b f0 \tvcvtusi2sd %eax,%xmm5,%xmm6",},
365{{0x62, 0xf1, 0x56, 0x08, 0x7b, 0xf0, }, 6, 0, "", "",
366"62 f1 56 08 7b f0 \tvcvtusi2ss %eax,%xmm5,%xmm6",},
367{{0x62, 0xf1, 0x7d, 0x4f, 0x7b, 0xf5, }, 6, 0, "", "",
368"62 f1 7d 4f 7b f5 \tvcvtps2qq %ymm5,%zmm6{%k7}",},
369{{0x62, 0xf1, 0xfd, 0x48, 0x7b, 0xf5, }, 6, 0, "", "",
370"62 f1 fd 48 7b f5 \tvcvtpd2qq %zmm5,%zmm6",},
371{{0x0f, 0x7f, 0xc4, }, 3, 0, "", "",
372"0f 7f c4 \tmovq %mm0,%mm4",},
373{{0xc5, 0xfd, 0x7f, 0xee, }, 4, 0, "", "",
374"c5 fd 7f ee \tvmovdqa %ymm5,%ymm6",},
375{{0x62, 0xf1, 0x7d, 0x48, 0x7f, 0xee, }, 6, 0, "", "",
376"62 f1 7d 48 7f ee \tvmovdqa32 %zmm5,%zmm6",},
377{{0x62, 0xf1, 0xfd, 0x48, 0x7f, 0xee, }, 6, 0, "", "",
378"62 f1 fd 48 7f ee \tvmovdqa64 %zmm5,%zmm6",},
379{{0xc5, 0xfe, 0x7f, 0xee, }, 4, 0, "", "",
380"c5 fe 7f ee \tvmovdqu %ymm5,%ymm6",},
381{{0x62, 0xf1, 0x7e, 0x48, 0x7f, 0xee, }, 6, 0, "", "",
382"62 f1 7e 48 7f ee \tvmovdqu32 %zmm5,%zmm6",},
383{{0x62, 0xf1, 0xfe, 0x48, 0x7f, 0xee, }, 6, 0, "", "",
384"62 f1 fe 48 7f ee \tvmovdqu64 %zmm5,%zmm6",},
385{{0x62, 0xf1, 0x7f, 0x48, 0x7f, 0xee, }, 6, 0, "", "",
386"62 f1 7f 48 7f ee \tvmovdqu8 %zmm5,%zmm6",},
387{{0x62, 0xf1, 0xff, 0x48, 0x7f, 0xee, }, 6, 0, "", "",
388"62 f1 ff 48 7f ee \tvmovdqu16 %zmm5,%zmm6",},
389{{0x0f, 0xdb, 0xd1, }, 3, 0, "", "",
390"0f db d1 \tpand %mm1,%mm2",},
391{{0x66, 0x0f, 0xdb, 0xd1, }, 4, 0, "", "",
392"66 0f db d1 \tpand %xmm1,%xmm2",},
393{{0xc5, 0xcd, 0xdb, 0xd4, }, 4, 0, "", "",
394"c5 cd db d4 \tvpand %ymm4,%ymm6,%ymm2",},
395{{0x62, 0xf1, 0x55, 0x48, 0xdb, 0xf4, }, 6, 0, "", "",
396"62 f1 55 48 db f4 \tvpandd %zmm4,%zmm5,%zmm6",},
397{{0x62, 0xf1, 0xd5, 0x48, 0xdb, 0xf4, }, 6, 0, "", "",
398"62 f1 d5 48 db f4 \tvpandq %zmm4,%zmm5,%zmm6",},
399{{0x0f, 0xdf, 0xd1, }, 3, 0, "", "",
400"0f df d1 \tpandn %mm1,%mm2",},
401{{0x66, 0x0f, 0xdf, 0xd1, }, 4, 0, "", "",
402"66 0f df d1 \tpandn %xmm1,%xmm2",},
403{{0xc5, 0xcd, 0xdf, 0xd4, }, 4, 0, "", "",
404"c5 cd df d4 \tvpandn %ymm4,%ymm6,%ymm2",},
405{{0x62, 0xf1, 0x55, 0x48, 0xdf, 0xf4, }, 6, 0, "", "",
406"62 f1 55 48 df f4 \tvpandnd %zmm4,%zmm5,%zmm6",},
407{{0x62, 0xf1, 0xd5, 0x48, 0xdf, 0xf4, }, 6, 0, "", "",
408"62 f1 d5 48 df f4 \tvpandnq %zmm4,%zmm5,%zmm6",},
409{{0xc5, 0xf9, 0xe6, 0xd1, }, 4, 0, "", "",
410"c5 f9 e6 d1 \tvcvttpd2dq %xmm1,%xmm2",},
411{{0xc5, 0xfa, 0xe6, 0xf5, }, 4, 0, "", "",
412"c5 fa e6 f5 \tvcvtdq2pd %xmm5,%xmm6",},
413{{0x62, 0xf1, 0x7e, 0x4f, 0xe6, 0xf5, }, 6, 0, "", "",
414"62 f1 7e 4f e6 f5 \tvcvtdq2pd %ymm5,%zmm6{%k7}",},
415{{0x62, 0xf1, 0xfe, 0x48, 0xe6, 0xf5, }, 6, 0, "", "",
416"62 f1 fe 48 e6 f5 \tvcvtqq2pd %zmm5,%zmm6",},
417{{0xc5, 0xfb, 0xe6, 0xd1, }, 4, 0, "", "",
418"c5 fb e6 d1 \tvcvtpd2dq %xmm1,%xmm2",},
419{{0x0f, 0xeb, 0xf4, }, 3, 0, "", "",
420"0f eb f4 \tpor %mm4,%mm6",},
421{{0xc5, 0xcd, 0xeb, 0xd4, }, 4, 0, "", "",
422"c5 cd eb d4 \tvpor %ymm4,%ymm6,%ymm2",},
423{{0x62, 0xf1, 0x55, 0x48, 0xeb, 0xf4, }, 6, 0, "", "",
424"62 f1 55 48 eb f4 \tvpord %zmm4,%zmm5,%zmm6",},
425{{0x62, 0xf1, 0xd5, 0x48, 0xeb, 0xf4, }, 6, 0, "", "",
426"62 f1 d5 48 eb f4 \tvporq %zmm4,%zmm5,%zmm6",},
427{{0x0f, 0xef, 0xf4, }, 3, 0, "", "",
428"0f ef f4 \tpxor %mm4,%mm6",},
429{{0xc5, 0xcd, 0xef, 0xd4, }, 4, 0, "", "",
430"c5 cd ef d4 \tvpxor %ymm4,%ymm6,%ymm2",},
431{{0x62, 0xf1, 0x55, 0x48, 0xef, 0xf4, }, 6, 0, "", "",
432"62 f1 55 48 ef f4 \tvpxord %zmm4,%zmm5,%zmm6",},
433{{0x62, 0xf1, 0xd5, 0x48, 0xef, 0xf4, }, 6, 0, "", "",
434"62 f1 d5 48 ef f4 \tvpxorq %zmm4,%zmm5,%zmm6",},
435{{0x66, 0x0f, 0x38, 0x10, 0xc1, }, 5, 0, "", "",
436"66 0f 38 10 c1 \tpblendvb %xmm0,%xmm1,%xmm0",},
437{{0x62, 0xf2, 0xd5, 0x48, 0x10, 0xf4, }, 6, 0, "", "",
438"62 f2 d5 48 10 f4 \tvpsrlvw %zmm4,%zmm5,%zmm6",},
439{{0x62, 0xf2, 0x7e, 0x4f, 0x10, 0xee, }, 6, 0, "", "",
440"62 f2 7e 4f 10 ee \tvpmovuswb %zmm5,%ymm6{%k7}",},
441{{0x62, 0xf2, 0x7e, 0x4f, 0x11, 0xee, }, 6, 0, "", "",
442"62 f2 7e 4f 11 ee \tvpmovusdb %zmm5,%xmm6{%k7}",},
443{{0x62, 0xf2, 0xd5, 0x48, 0x11, 0xf4, }, 6, 0, "", "",
444"62 f2 d5 48 11 f4 \tvpsravw %zmm4,%zmm5,%zmm6",},
445{{0x62, 0xf2, 0x7e, 0x4f, 0x12, 0xee, }, 6, 0, "", "",
446"62 f2 7e 4f 12 ee \tvpmovusqb %zmm5,%xmm6{%k7}",},
447{{0x62, 0xf2, 0xd5, 0x48, 0x12, 0xf4, }, 6, 0, "", "",
448"62 f2 d5 48 12 f4 \tvpsllvw %zmm4,%zmm5,%zmm6",},
449{{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "",
450"c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",},
451{{0x62, 0xf2, 0x7d, 0x4f, 0x13, 0xf5, }, 6, 0, "", "",
452"62 f2 7d 4f 13 f5 \tvcvtph2ps %ymm5,%zmm6{%k7}",},
453{{0x62, 0xf2, 0x7e, 0x4f, 0x13, 0xee, }, 6, 0, "", "",
454"62 f2 7e 4f 13 ee \tvpmovusdw %zmm5,%ymm6{%k7}",},
455{{0x66, 0x0f, 0x38, 0x14, 0xc1, }, 5, 0, "", "",
456"66 0f 38 14 c1 \tblendvps %xmm0,%xmm1,%xmm0",},
457{{0x62, 0xf2, 0x7e, 0x4f, 0x14, 0xee, }, 6, 0, "", "",
458"62 f2 7e 4f 14 ee \tvpmovusqw %zmm5,%xmm6{%k7}",},
459{{0x62, 0xf2, 0x55, 0x48, 0x14, 0xf4, }, 6, 0, "", "",
460"62 f2 55 48 14 f4 \tvprorvd %zmm4,%zmm5,%zmm6",},
461{{0x62, 0xf2, 0xd5, 0x48, 0x14, 0xf4, }, 6, 0, "", "",
462"62 f2 d5 48 14 f4 \tvprorvq %zmm4,%zmm5,%zmm6",},
463{{0x66, 0x0f, 0x38, 0x15, 0xc1, }, 5, 0, "", "",
464"66 0f 38 15 c1 \tblendvpd %xmm0,%xmm1,%xmm0",},
465{{0x62, 0xf2, 0x7e, 0x4f, 0x15, 0xee, }, 6, 0, "", "",
466"62 f2 7e 4f 15 ee \tvpmovusqd %zmm5,%ymm6{%k7}",},
467{{0x62, 0xf2, 0x55, 0x48, 0x15, 0xf4, }, 6, 0, "", "",
468"62 f2 55 48 15 f4 \tvprolvd %zmm4,%zmm5,%zmm6",},
469{{0x62, 0xf2, 0xd5, 0x48, 0x15, 0xf4, }, 6, 0, "", "",
470"62 f2 d5 48 15 f4 \tvprolvq %zmm4,%zmm5,%zmm6",},
471{{0xc4, 0xe2, 0x4d, 0x16, 0xd4, }, 5, 0, "", "",
472"c4 e2 4d 16 d4 \tvpermps %ymm4,%ymm6,%ymm2",},
473{{0x62, 0xf2, 0x4d, 0x2f, 0x16, 0xd4, }, 6, 0, "", "",
474"62 f2 4d 2f 16 d4 \tvpermps %ymm4,%ymm6,%ymm2{%k7}",},
475{{0x62, 0xf2, 0xcd, 0x2f, 0x16, 0xd4, }, 6, 0, "", "",
476"62 f2 cd 2f 16 d4 \tvpermpd %ymm4,%ymm6,%ymm2{%k7}",},
477{{0xc4, 0xe2, 0x7d, 0x19, 0xf4, }, 5, 0, "", "",
478"c4 e2 7d 19 f4 \tvbroadcastsd %xmm4,%ymm6",},
479{{0x62, 0xf2, 0x7d, 0x48, 0x19, 0xf7, }, 6, 0, "", "",
480"62 f2 7d 48 19 f7 \tvbroadcastf32x2 %xmm7,%zmm6",},
481{{0xc4, 0xe2, 0x7d, 0x1a, 0x21, }, 5, 0, "", "",
482"c4 e2 7d 1a 21 \tvbroadcastf128 (%ecx),%ymm4",},
483{{0x62, 0xf2, 0x7d, 0x48, 0x1a, 0x31, }, 6, 0, "", "",
484"62 f2 7d 48 1a 31 \tvbroadcastf32x4 (%ecx),%zmm6",},
485{{0x62, 0xf2, 0xfd, 0x48, 0x1a, 0x31, }, 6, 0, "", "",
486"62 f2 fd 48 1a 31 \tvbroadcastf64x2 (%ecx),%zmm6",},
487{{0x62, 0xf2, 0x7d, 0x48, 0x1b, 0x31, }, 6, 0, "", "",
488"62 f2 7d 48 1b 31 \tvbroadcastf32x8 (%ecx),%zmm6",},
489{{0x62, 0xf2, 0xfd, 0x48, 0x1b, 0x31, }, 6, 0, "", "",
490"62 f2 fd 48 1b 31 \tvbroadcastf64x4 (%ecx),%zmm6",},
491{{0x62, 0xf2, 0xfd, 0x48, 0x1f, 0xf4, }, 6, 0, "", "",
492"62 f2 fd 48 1f f4 \tvpabsq %zmm4,%zmm6",},
493{{0xc4, 0xe2, 0x79, 0x20, 0xec, }, 5, 0, "", "",
494"c4 e2 79 20 ec \tvpmovsxbw %xmm4,%xmm5",},
495{{0x62, 0xf2, 0x7e, 0x4f, 0x20, 0xee, }, 6, 0, "", "",
496"62 f2 7e 4f 20 ee \tvpmovswb %zmm5,%ymm6{%k7}",},
497{{0xc4, 0xe2, 0x7d, 0x21, 0xf4, }, 5, 0, "", "",
498"c4 e2 7d 21 f4 \tvpmovsxbd %xmm4,%ymm6",},
499{{0x62, 0xf2, 0x7e, 0x4f, 0x21, 0xee, }, 6, 0, "", "",
500"62 f2 7e 4f 21 ee \tvpmovsdb %zmm5,%xmm6{%k7}",},
501{{0xc4, 0xe2, 0x7d, 0x22, 0xe4, }, 5, 0, "", "",
502"c4 e2 7d 22 e4 \tvpmovsxbq %xmm4,%ymm4",},
503{{0x62, 0xf2, 0x7e, 0x4f, 0x22, 0xee, }, 6, 0, "", "",
504"62 f2 7e 4f 22 ee \tvpmovsqb %zmm5,%xmm6{%k7}",},
505{{0xc4, 0xe2, 0x7d, 0x23, 0xe4, }, 5, 0, "", "",
506"c4 e2 7d 23 e4 \tvpmovsxwd %xmm4,%ymm4",},
507{{0x62, 0xf2, 0x7e, 0x4f, 0x23, 0xee, }, 6, 0, "", "",
508"62 f2 7e 4f 23 ee \tvpmovsdw %zmm5,%ymm6{%k7}",},
509{{0xc4, 0xe2, 0x7d, 0x24, 0xf4, }, 5, 0, "", "",
510"c4 e2 7d 24 f4 \tvpmovsxwq %xmm4,%ymm6",},
511{{0x62, 0xf2, 0x7e, 0x4f, 0x24, 0xee, }, 6, 0, "", "",
512"62 f2 7e 4f 24 ee \tvpmovsqw %zmm5,%xmm6{%k7}",},
513{{0xc4, 0xe2, 0x7d, 0x25, 0xe4, }, 5, 0, "", "",
514"c4 e2 7d 25 e4 \tvpmovsxdq %xmm4,%ymm4",},
515{{0x62, 0xf2, 0x7e, 0x4f, 0x25, 0xee, }, 6, 0, "", "",
516"62 f2 7e 4f 25 ee \tvpmovsqd %zmm5,%ymm6{%k7}",},
517{{0x62, 0xf2, 0x4d, 0x48, 0x26, 0xed, }, 6, 0, "", "",
518"62 f2 4d 48 26 ed \tvptestmb %zmm5,%zmm6,%k5",},
519{{0x62, 0xf2, 0xcd, 0x48, 0x26, 0xed, }, 6, 0, "", "",
520"62 f2 cd 48 26 ed \tvptestmw %zmm5,%zmm6,%k5",},
521{{0x62, 0xf2, 0x56, 0x48, 0x26, 0xec, }, 6, 0, "", "",
522"62 f2 56 48 26 ec \tvptestnmb %zmm4,%zmm5,%k5",},
523{{0x62, 0xf2, 0xd6, 0x48, 0x26, 0xec, }, 6, 0, "", "",
524"62 f2 d6 48 26 ec \tvptestnmw %zmm4,%zmm5,%k5",},
525{{0x62, 0xf2, 0x4d, 0x48, 0x27, 0xed, }, 6, 0, "", "",
526"62 f2 4d 48 27 ed \tvptestmd %zmm5,%zmm6,%k5",},
527{{0x62, 0xf2, 0xcd, 0x48, 0x27, 0xed, }, 6, 0, "", "",
528"62 f2 cd 48 27 ed \tvptestmq %zmm5,%zmm6,%k5",},
529{{0x62, 0xf2, 0x56, 0x48, 0x27, 0xec, }, 6, 0, "", "",
530"62 f2 56 48 27 ec \tvptestnmd %zmm4,%zmm5,%k5",},
531{{0x62, 0xf2, 0xd6, 0x48, 0x27, 0xec, }, 6, 0, "", "",
532"62 f2 d6 48 27 ec \tvptestnmq %zmm4,%zmm5,%k5",},
533{{0xc4, 0xe2, 0x4d, 0x28, 0xd4, }, 5, 0, "", "",
534"c4 e2 4d 28 d4 \tvpmuldq %ymm4,%ymm6,%ymm2",},
535{{0x62, 0xf2, 0x7e, 0x48, 0x28, 0xf5, }, 6, 0, "", "",
536"62 f2 7e 48 28 f5 \tvpmovm2b %k5,%zmm6",},
537{{0x62, 0xf2, 0xfe, 0x48, 0x28, 0xf5, }, 6, 0, "", "",
538"62 f2 fe 48 28 f5 \tvpmovm2w %k5,%zmm6",},
539{{0xc4, 0xe2, 0x4d, 0x29, 0xd4, }, 5, 0, "", "",
540"c4 e2 4d 29 d4 \tvpcmpeqq %ymm4,%ymm6,%ymm2",},
541{{0x62, 0xf2, 0x7e, 0x48, 0x29, 0xee, }, 6, 0, "", "",
542"62 f2 7e 48 29 ee \tvpmovb2m %zmm6,%k5",},
543{{0x62, 0xf2, 0xfe, 0x48, 0x29, 0xee, }, 6, 0, "", "",
544"62 f2 fe 48 29 ee \tvpmovw2m %zmm6,%k5",},
545{{0xc4, 0xe2, 0x7d, 0x2a, 0x21, }, 5, 0, "", "",
546"c4 e2 7d 2a 21 \tvmovntdqa (%ecx),%ymm4",},
547{{0x62, 0xf2, 0xfe, 0x48, 0x2a, 0xce, }, 6, 0, "", "",
548"62 f2 fe 48 2a ce \tvpbroadcastmb2q %k6,%zmm1",},
549{{0xc4, 0xe2, 0x5d, 0x2c, 0x31, }, 5, 0, "", "",
550"c4 e2 5d 2c 31 \tvmaskmovps (%ecx),%ymm4,%ymm6",},
551{{0x62, 0xf2, 0x55, 0x48, 0x2c, 0xf4, }, 6, 0, "", "",
552"62 f2 55 48 2c f4 \tvscalefps %zmm4,%zmm5,%zmm6",},
553{{0x62, 0xf2, 0xd5, 0x48, 0x2c, 0xf4, }, 6, 0, "", "",
554"62 f2 d5 48 2c f4 \tvscalefpd %zmm4,%zmm5,%zmm6",},
555{{0xc4, 0xe2, 0x5d, 0x2d, 0x31, }, 5, 0, "", "",
556"c4 e2 5d 2d 31 \tvmaskmovpd (%ecx),%ymm4,%ymm6",},
557{{0x62, 0xf2, 0x55, 0x0f, 0x2d, 0xf4, }, 6, 0, "", "",
558"62 f2 55 0f 2d f4 \tvscalefss %xmm4,%xmm5,%xmm6{%k7}",},
559{{0x62, 0xf2, 0xd5, 0x0f, 0x2d, 0xf4, }, 6, 0, "", "",
560"62 f2 d5 0f 2d f4 \tvscalefsd %xmm4,%xmm5,%xmm6{%k7}",},
561{{0xc4, 0xe2, 0x7d, 0x30, 0xe4, }, 5, 0, "", "",
562"c4 e2 7d 30 e4 \tvpmovzxbw %xmm4,%ymm4",},
563{{0x62, 0xf2, 0x7e, 0x4f, 0x30, 0xee, }, 6, 0, "", "",
564"62 f2 7e 4f 30 ee \tvpmovwb %zmm5,%ymm6{%k7}",},
565{{0xc4, 0xe2, 0x7d, 0x31, 0xf4, }, 5, 0, "", "",
566"c4 e2 7d 31 f4 \tvpmovzxbd %xmm4,%ymm6",},
567{{0x62, 0xf2, 0x7e, 0x4f, 0x31, 0xee, }, 6, 0, "", "",
568"62 f2 7e 4f 31 ee \tvpmovdb %zmm5,%xmm6{%k7}",},
569{{0xc4, 0xe2, 0x7d, 0x32, 0xe4, }, 5, 0, "", "",
570"c4 e2 7d 32 e4 \tvpmovzxbq %xmm4,%ymm4",},
571{{0x62, 0xf2, 0x7e, 0x4f, 0x32, 0xee, }, 6, 0, "", "",
572"62 f2 7e 4f 32 ee \tvpmovqb %zmm5,%xmm6{%k7}",},
573{{0xc4, 0xe2, 0x7d, 0x33, 0xe4, }, 5, 0, "", "",
574"c4 e2 7d 33 e4 \tvpmovzxwd %xmm4,%ymm4",},
575{{0x62, 0xf2, 0x7e, 0x4f, 0x33, 0xee, }, 6, 0, "", "",
576"62 f2 7e 4f 33 ee \tvpmovdw %zmm5,%ymm6{%k7}",},
577{{0xc4, 0xe2, 0x7d, 0x34, 0xf4, }, 5, 0, "", "",
578"c4 e2 7d 34 f4 \tvpmovzxwq %xmm4,%ymm6",},
579{{0x62, 0xf2, 0x7e, 0x4f, 0x34, 0xee, }, 6, 0, "", "",
580"62 f2 7e 4f 34 ee \tvpmovqw %zmm5,%xmm6{%k7}",},
581{{0xc4, 0xe2, 0x7d, 0x35, 0xe4, }, 5, 0, "", "",
582"c4 e2 7d 35 e4 \tvpmovzxdq %xmm4,%ymm4",},
583{{0x62, 0xf2, 0x7e, 0x4f, 0x35, 0xee, }, 6, 0, "", "",
584"62 f2 7e 4f 35 ee \tvpmovqd %zmm5,%ymm6{%k7}",},
585{{0xc4, 0xe2, 0x4d, 0x36, 0xd4, }, 5, 0, "", "",
586"c4 e2 4d 36 d4 \tvpermd %ymm4,%ymm6,%ymm2",},
587{{0x62, 0xf2, 0x4d, 0x2f, 0x36, 0xd4, }, 6, 0, "", "",
588"62 f2 4d 2f 36 d4 \tvpermd %ymm4,%ymm6,%ymm2{%k7}",},
589{{0x62, 0xf2, 0xcd, 0x2f, 0x36, 0xd4, }, 6, 0, "", "",
590"62 f2 cd 2f 36 d4 \tvpermq %ymm4,%ymm6,%ymm2{%k7}",},
591{{0xc4, 0xe2, 0x4d, 0x38, 0xd4, }, 5, 0, "", "",
592"c4 e2 4d 38 d4 \tvpminsb %ymm4,%ymm6,%ymm2",},
593{{0x62, 0xf2, 0x7e, 0x48, 0x38, 0xf5, }, 6, 0, "", "",
594"62 f2 7e 48 38 f5 \tvpmovm2d %k5,%zmm6",},
595{{0x62, 0xf2, 0xfe, 0x48, 0x38, 0xf5, }, 6, 0, "", "",
596"62 f2 fe 48 38 f5 \tvpmovm2q %k5,%zmm6",},
597{{0xc4, 0xe2, 0x69, 0x39, 0xd9, }, 5, 0, "", "",
598"c4 e2 69 39 d9 \tvpminsd %xmm1,%xmm2,%xmm3",},
599{{0x62, 0xf2, 0x55, 0x48, 0x39, 0xf4, }, 6, 0, "", "",
600"62 f2 55 48 39 f4 \tvpminsd %zmm4,%zmm5,%zmm6",},
601{{0x62, 0xf2, 0xd5, 0x48, 0x39, 0xf4, }, 6, 0, "", "",
602"62 f2 d5 48 39 f4 \tvpminsq %zmm4,%zmm5,%zmm6",},
603{{0x62, 0xf2, 0x7e, 0x48, 0x39, 0xee, }, 6, 0, "", "",
604"62 f2 7e 48 39 ee \tvpmovd2m %zmm6,%k5",},
605{{0x62, 0xf2, 0xfe, 0x48, 0x39, 0xee, }, 6, 0, "", "",
606"62 f2 fe 48 39 ee \tvpmovq2m %zmm6,%k5",},
607{{0xc4, 0xe2, 0x4d, 0x3a, 0xd4, }, 5, 0, "", "",
608"c4 e2 4d 3a d4 \tvpminuw %ymm4,%ymm6,%ymm2",},
609{{0x62, 0xf2, 0x7e, 0x48, 0x3a, 0xf6, }, 6, 0, "", "",
610"62 f2 7e 48 3a f6 \tvpbroadcastmw2d %k6,%zmm6",},
611{{0xc4, 0xe2, 0x4d, 0x3b, 0xd4, }, 5, 0, "", "",
612"c4 e2 4d 3b d4 \tvpminud %ymm4,%ymm6,%ymm2",},
613{{0x62, 0xf2, 0x55, 0x48, 0x3b, 0xf4, }, 6, 0, "", "",
614"62 f2 55 48 3b f4 \tvpminud %zmm4,%zmm5,%zmm6",},
615{{0x62, 0xf2, 0xd5, 0x48, 0x3b, 0xf4, }, 6, 0, "", "",
616"62 f2 d5 48 3b f4 \tvpminuq %zmm4,%zmm5,%zmm6",},
617{{0xc4, 0xe2, 0x4d, 0x3d, 0xd4, }, 5, 0, "", "",
618"c4 e2 4d 3d d4 \tvpmaxsd %ymm4,%ymm6,%ymm2",},
619{{0x62, 0xf2, 0x55, 0x48, 0x3d, 0xf4, }, 6, 0, "", "",
620"62 f2 55 48 3d f4 \tvpmaxsd %zmm4,%zmm5,%zmm6",},
621{{0x62, 0xf2, 0xd5, 0x48, 0x3d, 0xf4, }, 6, 0, "", "",
622"62 f2 d5 48 3d f4 \tvpmaxsq %zmm4,%zmm5,%zmm6",},
623{{0xc4, 0xe2, 0x4d, 0x3f, 0xd4, }, 5, 0, "", "",
624"c4 e2 4d 3f d4 \tvpmaxud %ymm4,%ymm6,%ymm2",},
625{{0x62, 0xf2, 0x55, 0x48, 0x3f, 0xf4, }, 6, 0, "", "",
626"62 f2 55 48 3f f4 \tvpmaxud %zmm4,%zmm5,%zmm6",},
627{{0x62, 0xf2, 0xd5, 0x48, 0x3f, 0xf4, }, 6, 0, "", "",
628"62 f2 d5 48 3f f4 \tvpmaxuq %zmm4,%zmm5,%zmm6",},
629{{0xc4, 0xe2, 0x4d, 0x40, 0xd4, }, 5, 0, "", "",
630"c4 e2 4d 40 d4 \tvpmulld %ymm4,%ymm6,%ymm2",},
631{{0x62, 0xf2, 0x55, 0x48, 0x40, 0xf4, }, 6, 0, "", "",
632"62 f2 55 48 40 f4 \tvpmulld %zmm4,%zmm5,%zmm6",},
633{{0x62, 0xf2, 0xd5, 0x48, 0x40, 0xf4, }, 6, 0, "", "",
634"62 f2 d5 48 40 f4 \tvpmullq %zmm4,%zmm5,%zmm6",},
635{{0x62, 0xf2, 0x7d, 0x48, 0x42, 0xf5, }, 6, 0, "", "",
636"62 f2 7d 48 42 f5 \tvgetexpps %zmm5,%zmm6",},
637{{0x62, 0xf2, 0xfd, 0x48, 0x42, 0xf5, }, 6, 0, "", "",
638"62 f2 fd 48 42 f5 \tvgetexppd %zmm5,%zmm6",},
639{{0x62, 0xf2, 0x55, 0x0f, 0x43, 0xf4, }, 6, 0, "", "",
640"62 f2 55 0f 43 f4 \tvgetexpss %xmm4,%xmm5,%xmm6{%k7}",},
641{{0x62, 0xf2, 0xe5, 0x0f, 0x43, 0xe2, }, 6, 0, "", "",
642"62 f2 e5 0f 43 e2 \tvgetexpsd %xmm2,%xmm3,%xmm4{%k7}",},
643{{0x62, 0xf2, 0x7d, 0x48, 0x44, 0xf5, }, 6, 0, "", "",
644"62 f2 7d 48 44 f5 \tvplzcntd %zmm5,%zmm6",},
645{{0x62, 0xf2, 0xfd, 0x48, 0x44, 0xf5, }, 6, 0, "", "",
646"62 f2 fd 48 44 f5 \tvplzcntq %zmm5,%zmm6",},
647{{0xc4, 0xe2, 0x4d, 0x46, 0xd4, }, 5, 0, "", "",
648"c4 e2 4d 46 d4 \tvpsravd %ymm4,%ymm6,%ymm2",},
649{{0x62, 0xf2, 0x55, 0x48, 0x46, 0xf4, }, 6, 0, "", "",
650"62 f2 55 48 46 f4 \tvpsravd %zmm4,%zmm5,%zmm6",},
651{{0x62, 0xf2, 0xd5, 0x48, 0x46, 0xf4, }, 6, 0, "", "",
652"62 f2 d5 48 46 f4 \tvpsravq %zmm4,%zmm5,%zmm6",},
653{{0x62, 0xf2, 0x7d, 0x48, 0x4c, 0xf5, }, 6, 0, "", "",
654"62 f2 7d 48 4c f5 \tvrcp14ps %zmm5,%zmm6",},
655{{0x62, 0xf2, 0xfd, 0x48, 0x4c, 0xf5, }, 6, 0, "", "",
656"62 f2 fd 48 4c f5 \tvrcp14pd %zmm5,%zmm6",},
657{{0x62, 0xf2, 0x55, 0x0f, 0x4d, 0xf4, }, 6, 0, "", "",
658"62 f2 55 0f 4d f4 \tvrcp14ss %xmm4,%xmm5,%xmm6{%k7}",},
659{{0x62, 0xf2, 0xd5, 0x0f, 0x4d, 0xf4, }, 6, 0, "", "",
660"62 f2 d5 0f 4d f4 \tvrcp14sd %xmm4,%xmm5,%xmm6{%k7}",},
661{{0x62, 0xf2, 0x7d, 0x48, 0x4e, 0xf5, }, 6, 0, "", "",
662"62 f2 7d 48 4e f5 \tvrsqrt14ps %zmm5,%zmm6",},
663{{0x62, 0xf2, 0xfd, 0x48, 0x4e, 0xf5, }, 6, 0, "", "",
664"62 f2 fd 48 4e f5 \tvrsqrt14pd %zmm5,%zmm6",},
665{{0x62, 0xf2, 0x55, 0x0f, 0x4f, 0xf4, }, 6, 0, "", "",
666"62 f2 55 0f 4f f4 \tvrsqrt14ss %xmm4,%xmm5,%xmm6{%k7}",},
667{{0x62, 0xf2, 0xd5, 0x0f, 0x4f, 0xf4, }, 6, 0, "", "",
668"62 f2 d5 0f 4f f4 \tvrsqrt14sd %xmm4,%xmm5,%xmm6{%k7}",},
669{{0xc4, 0xe2, 0x79, 0x59, 0xf4, }, 5, 0, "", "",
670"c4 e2 79 59 f4 \tvpbroadcastq %xmm4,%xmm6",},
671{{0x62, 0xf2, 0x7d, 0x48, 0x59, 0xf7, }, 6, 0, "", "",
672"62 f2 7d 48 59 f7 \tvbroadcasti32x2 %xmm7,%zmm6",},
673{{0xc4, 0xe2, 0x7d, 0x5a, 0x21, }, 5, 0, "", "",
674"c4 e2 7d 5a 21 \tvbroadcasti128 (%ecx),%ymm4",},
675{{0x62, 0xf2, 0x7d, 0x48, 0x5a, 0x31, }, 6, 0, "", "",
676"62 f2 7d 48 5a 31 \tvbroadcasti32x4 (%ecx),%zmm6",},
677{{0x62, 0xf2, 0xfd, 0x48, 0x5a, 0x31, }, 6, 0, "", "",
678"62 f2 fd 48 5a 31 \tvbroadcasti64x2 (%ecx),%zmm6",},
679{{0x62, 0xf2, 0x7d, 0x48, 0x5b, 0x31, }, 6, 0, "", "",
680"62 f2 7d 48 5b 31 \tvbroadcasti32x8 (%ecx),%zmm6",},
681{{0x62, 0xf2, 0xfd, 0x48, 0x5b, 0x31, }, 6, 0, "", "",
682"62 f2 fd 48 5b 31 \tvbroadcasti64x4 (%ecx),%zmm6",},
683{{0x62, 0xf2, 0x55, 0x48, 0x64, 0xf4, }, 6, 0, "", "",
684"62 f2 55 48 64 f4 \tvpblendmd %zmm4,%zmm5,%zmm6",},
685{{0x62, 0xf2, 0xd5, 0x48, 0x64, 0xf4, }, 6, 0, "", "",
686"62 f2 d5 48 64 f4 \tvpblendmq %zmm4,%zmm5,%zmm6",},
687{{0x62, 0xf2, 0x55, 0x48, 0x65, 0xf4, }, 6, 0, "", "",
688"62 f2 55 48 65 f4 \tvblendmps %zmm4,%zmm5,%zmm6",},
689{{0x62, 0xf2, 0xd5, 0x48, 0x65, 0xf4, }, 6, 0, "", "",
690"62 f2 d5 48 65 f4 \tvblendmpd %zmm4,%zmm5,%zmm6",},
691{{0x62, 0xf2, 0x55, 0x48, 0x66, 0xf4, }, 6, 0, "", "",
692"62 f2 55 48 66 f4 \tvpblendmb %zmm4,%zmm5,%zmm6",},
693{{0x62, 0xf2, 0xd5, 0x48, 0x66, 0xf4, }, 6, 0, "", "",
694"62 f2 d5 48 66 f4 \tvpblendmw %zmm4,%zmm5,%zmm6",},
695{{0x62, 0xf2, 0x55, 0x48, 0x75, 0xf4, }, 6, 0, "", "",
696"62 f2 55 48 75 f4 \tvpermi2b %zmm4,%zmm5,%zmm6",},
697{{0x62, 0xf2, 0xd5, 0x48, 0x75, 0xf4, }, 6, 0, "", "",
698"62 f2 d5 48 75 f4 \tvpermi2w %zmm4,%zmm5,%zmm6",},
699{{0x62, 0xf2, 0x55, 0x48, 0x76, 0xf4, }, 6, 0, "", "",
700"62 f2 55 48 76 f4 \tvpermi2d %zmm4,%zmm5,%zmm6",},
701{{0x62, 0xf2, 0xd5, 0x48, 0x76, 0xf4, }, 6, 0, "", "",
702"62 f2 d5 48 76 f4 \tvpermi2q %zmm4,%zmm5,%zmm6",},
703{{0x62, 0xf2, 0x55, 0x48, 0x77, 0xf4, }, 6, 0, "", "",
704"62 f2 55 48 77 f4 \tvpermi2ps %zmm4,%zmm5,%zmm6",},
705{{0x62, 0xf2, 0xd5, 0x48, 0x77, 0xf4, }, 6, 0, "", "",
706"62 f2 d5 48 77 f4 \tvpermi2pd %zmm4,%zmm5,%zmm6",},
707{{0x62, 0xf2, 0x7d, 0x08, 0x7a, 0xd8, }, 6, 0, "", "",
708"62 f2 7d 08 7a d8 \tvpbroadcastb %eax,%xmm3",},
709{{0x62, 0xf2, 0x7d, 0x08, 0x7b, 0xd8, }, 6, 0, "", "",
710"62 f2 7d 08 7b d8 \tvpbroadcastw %eax,%xmm3",},
711{{0x62, 0xf2, 0x7d, 0x08, 0x7c, 0xd8, }, 6, 0, "", "",
712"62 f2 7d 08 7c d8 \tvpbroadcastd %eax,%xmm3",},
713{{0x62, 0xf2, 0x55, 0x48, 0x7d, 0xf4, }, 6, 0, "", "",
714"62 f2 55 48 7d f4 \tvpermt2b %zmm4,%zmm5,%zmm6",},
715{{0x62, 0xf2, 0xd5, 0x48, 0x7d, 0xf4, }, 6, 0, "", "",
716"62 f2 d5 48 7d f4 \tvpermt2w %zmm4,%zmm5,%zmm6",},
717{{0x62, 0xf2, 0x55, 0x48, 0x7e, 0xf4, }, 6, 0, "", "",
718"62 f2 55 48 7e f4 \tvpermt2d %zmm4,%zmm5,%zmm6",},
719{{0x62, 0xf2, 0xd5, 0x48, 0x7e, 0xf4, }, 6, 0, "", "",
720"62 f2 d5 48 7e f4 \tvpermt2q %zmm4,%zmm5,%zmm6",},
721{{0x62, 0xf2, 0x55, 0x48, 0x7f, 0xf4, }, 6, 0, "", "",
722"62 f2 55 48 7f f4 \tvpermt2ps %zmm4,%zmm5,%zmm6",},
723{{0x62, 0xf2, 0xd5, 0x48, 0x7f, 0xf4, }, 6, 0, "", "",
724"62 f2 d5 48 7f f4 \tvpermt2pd %zmm4,%zmm5,%zmm6",},
725{{0x62, 0xf2, 0xd5, 0x48, 0x83, 0xf4, }, 6, 0, "", "",
726"62 f2 d5 48 83 f4 \tvpmultishiftqb %zmm4,%zmm5,%zmm6",},
727{{0x62, 0xf2, 0x7d, 0x48, 0x88, 0x31, }, 6, 0, "", "",
728"62 f2 7d 48 88 31 \tvexpandps (%ecx),%zmm6",},
729{{0x62, 0xf2, 0xfd, 0x48, 0x88, 0x31, }, 6, 0, "", "",
730"62 f2 fd 48 88 31 \tvexpandpd (%ecx),%zmm6",},
731{{0x62, 0xf2, 0x7d, 0x48, 0x89, 0x31, }, 6, 0, "", "",
732"62 f2 7d 48 89 31 \tvpexpandd (%ecx),%zmm6",},
733{{0x62, 0xf2, 0xfd, 0x48, 0x89, 0x31, }, 6, 0, "", "",
734"62 f2 fd 48 89 31 \tvpexpandq (%ecx),%zmm6",},
735{{0x62, 0xf2, 0x7d, 0x48, 0x8a, 0x31, }, 6, 0, "", "",
736"62 f2 7d 48 8a 31 \tvcompressps %zmm6,(%ecx)",},
737{{0x62, 0xf2, 0xfd, 0x48, 0x8a, 0x31, }, 6, 0, "", "",
738"62 f2 fd 48 8a 31 \tvcompresspd %zmm6,(%ecx)",},
739{{0x62, 0xf2, 0x7d, 0x48, 0x8b, 0x31, }, 6, 0, "", "",
740"62 f2 7d 48 8b 31 \tvpcompressd %zmm6,(%ecx)",},
741{{0x62, 0xf2, 0xfd, 0x48, 0x8b, 0x31, }, 6, 0, "", "",
742"62 f2 fd 48 8b 31 \tvpcompressq %zmm6,(%ecx)",},
743{{0x62, 0xf2, 0x55, 0x48, 0x8d, 0xf4, }, 6, 0, "", "",
744"62 f2 55 48 8d f4 \tvpermb %zmm4,%zmm5,%zmm6",},
745{{0x62, 0xf2, 0xd5, 0x48, 0x8d, 0xf4, }, 6, 0, "", "",
746"62 f2 d5 48 8d f4 \tvpermw %zmm4,%zmm5,%zmm6",},
747{{0xc4, 0xe2, 0x69, 0x90, 0x4c, 0x7d, 0x02, }, 7, 0, "", "",
748"c4 e2 69 90 4c 7d 02 \tvpgatherdd %xmm2,0x2(%ebp,%xmm7,2),%xmm1",},
749{{0xc4, 0xe2, 0xe9, 0x90, 0x4c, 0x7d, 0x04, }, 7, 0, "", "",
750"c4 e2 e9 90 4c 7d 04 \tvpgatherdq %xmm2,0x4(%ebp,%xmm7,2),%xmm1",},
751{{0x62, 0xf2, 0x7d, 0x49, 0x90, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
752"62 f2 7d 49 90 b4 fd 7b 00 00 00 \tvpgatherdd 0x7b(%ebp,%zmm7,8),%zmm6{%k1}",},
753{{0x62, 0xf2, 0xfd, 0x49, 0x90, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
754"62 f2 fd 49 90 b4 fd 7b 00 00 00 \tvpgatherdq 0x7b(%ebp,%ymm7,8),%zmm6{%k1}",},
755{{0xc4, 0xe2, 0x69, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "",
756"c4 e2 69 91 4c 7d 02 \tvpgatherqd %xmm2,0x2(%ebp,%xmm7,2),%xmm1",},
757{{0xc4, 0xe2, 0xe9, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "",
758"c4 e2 e9 91 4c 7d 02 \tvpgatherqq %xmm2,0x2(%ebp,%xmm7,2),%xmm1",},
759{{0x62, 0xf2, 0x7d, 0x49, 0x91, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
760"62 f2 7d 49 91 b4 fd 7b 00 00 00 \tvpgatherqd 0x7b(%ebp,%zmm7,8),%ymm6{%k1}",},
761{{0x62, 0xf2, 0xfd, 0x49, 0x91, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
762"62 f2 fd 49 91 b4 fd 7b 00 00 00 \tvpgatherqq 0x7b(%ebp,%zmm7,8),%zmm6{%k1}",},
763{{0x62, 0xf2, 0x7d, 0x49, 0xa0, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
764"62 f2 7d 49 a0 b4 fd 7b 00 00 00 \tvpscatterdd %zmm6,0x7b(%ebp,%zmm7,8){%k1}",},
765{{0x62, 0xf2, 0xfd, 0x49, 0xa0, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
766"62 f2 fd 49 a0 b4 fd 7b 00 00 00 \tvpscatterdq %zmm6,0x7b(%ebp,%ymm7,8){%k1}",},
767{{0x62, 0xf2, 0x7d, 0x49, 0xa1, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
768"62 f2 7d 49 a1 b4 fd 7b 00 00 00 \tvpscatterqd %ymm6,0x7b(%ebp,%zmm7,8){%k1}",},
769{{0x62, 0xf2, 0xfd, 0x29, 0xa1, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
770"62 f2 fd 29 a1 b4 fd 7b 00 00 00 \tvpscatterqq %ymm6,0x7b(%ebp,%ymm7,8){%k1}",},
771{{0x62, 0xf2, 0x7d, 0x49, 0xa2, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
772"62 f2 7d 49 a2 b4 fd 7b 00 00 00 \tvscatterdps %zmm6,0x7b(%ebp,%zmm7,8){%k1}",},
773{{0x62, 0xf2, 0xfd, 0x49, 0xa2, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
774"62 f2 fd 49 a2 b4 fd 7b 00 00 00 \tvscatterdpd %zmm6,0x7b(%ebp,%ymm7,8){%k1}",},
775{{0x62, 0xf2, 0x7d, 0x49, 0xa3, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
776"62 f2 7d 49 a3 b4 fd 7b 00 00 00 \tvscatterqps %ymm6,0x7b(%ebp,%zmm7,8){%k1}",},
777{{0x62, 0xf2, 0xfd, 0x49, 0xa3, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
778"62 f2 fd 49 a3 b4 fd 7b 00 00 00 \tvscatterqpd %zmm6,0x7b(%ebp,%zmm7,8){%k1}",},
779{{0x62, 0xf2, 0xd5, 0x48, 0xb4, 0xf4, }, 6, 0, "", "",
780"62 f2 d5 48 b4 f4 \tvpmadd52luq %zmm4,%zmm5,%zmm6",},
781{{0x62, 0xf2, 0xd5, 0x48, 0xb5, 0xf4, }, 6, 0, "", "",
782"62 f2 d5 48 b5 f4 \tvpmadd52huq %zmm4,%zmm5,%zmm6",},
783{{0x62, 0xf2, 0x7d, 0x48, 0xc4, 0xf5, }, 6, 0, "", "",
784"62 f2 7d 48 c4 f5 \tvpconflictd %zmm5,%zmm6",},
785{{0x62, 0xf2, 0xfd, 0x48, 0xc4, 0xf5, }, 6, 0, "", "",
786"62 f2 fd 48 c4 f5 \tvpconflictq %zmm5,%zmm6",},
787{{0x62, 0xf2, 0x7d, 0x48, 0xc8, 0xfe, }, 6, 0, "", "",
788"62 f2 7d 48 c8 fe \tvexp2ps %zmm6,%zmm7",},
789{{0x62, 0xf2, 0xfd, 0x48, 0xc8, 0xfe, }, 6, 0, "", "",
790"62 f2 fd 48 c8 fe \tvexp2pd %zmm6,%zmm7",},
791{{0x62, 0xf2, 0x7d, 0x48, 0xca, 0xfe, }, 6, 0, "", "",
792"62 f2 7d 48 ca fe \tvrcp28ps %zmm6,%zmm7",},
793{{0x62, 0xf2, 0xfd, 0x48, 0xca, 0xfe, }, 6, 0, "", "",
794"62 f2 fd 48 ca fe \tvrcp28pd %zmm6,%zmm7",},
795{{0x62, 0xf2, 0x4d, 0x0f, 0xcb, 0xfd, }, 6, 0, "", "",
796"62 f2 4d 0f cb fd \tvrcp28ss %xmm5,%xmm6,%xmm7{%k7}",},
797{{0x62, 0xf2, 0xcd, 0x0f, 0xcb, 0xfd, }, 6, 0, "", "",
798"62 f2 cd 0f cb fd \tvrcp28sd %xmm5,%xmm6,%xmm7{%k7}",},
799{{0x62, 0xf2, 0x7d, 0x48, 0xcc, 0xfe, }, 6, 0, "", "",
800"62 f2 7d 48 cc fe \tvrsqrt28ps %zmm6,%zmm7",},
801{{0x62, 0xf2, 0xfd, 0x48, 0xcc, 0xfe, }, 6, 0, "", "",
802"62 f2 fd 48 cc fe \tvrsqrt28pd %zmm6,%zmm7",},
803{{0x62, 0xf2, 0x4d, 0x0f, 0xcd, 0xfd, }, 6, 0, "", "",
804"62 f2 4d 0f cd fd \tvrsqrt28ss %xmm5,%xmm6,%xmm7{%k7}",},
805{{0x62, 0xf2, 0xcd, 0x0f, 0xcd, 0xfd, }, 6, 0, "", "",
806"62 f2 cd 0f cd fd \tvrsqrt28sd %xmm5,%xmm6,%xmm7{%k7}",},
807{{0x62, 0xf3, 0x4d, 0x48, 0x03, 0xfd, 0x12, }, 7, 0, "", "",
808"62 f3 4d 48 03 fd 12 \tvalignd $0x12,%zmm5,%zmm6,%zmm7",},
809{{0x62, 0xf3, 0xcd, 0x48, 0x03, 0xfd, 0x12, }, 7, 0, "", "",
810"62 f3 cd 48 03 fd 12 \tvalignq $0x12,%zmm5,%zmm6,%zmm7",},
811{{0xc4, 0xe3, 0x7d, 0x08, 0xd6, 0x05, }, 6, 0, "", "",
812"c4 e3 7d 08 d6 05 \tvroundps $0x5,%ymm6,%ymm2",},
813{{0x62, 0xf3, 0x7d, 0x48, 0x08, 0xf5, 0x12, }, 7, 0, "", "",
814"62 f3 7d 48 08 f5 12 \tvrndscaleps $0x12,%zmm5,%zmm6",},
815{{0xc4, 0xe3, 0x7d, 0x09, 0xd6, 0x05, }, 6, 0, "", "",
816"c4 e3 7d 09 d6 05 \tvroundpd $0x5,%ymm6,%ymm2",},
817{{0x62, 0xf3, 0xfd, 0x48, 0x09, 0xf5, 0x12, }, 7, 0, "", "",
818"62 f3 fd 48 09 f5 12 \tvrndscalepd $0x12,%zmm5,%zmm6",},
819{{0xc4, 0xe3, 0x49, 0x0a, 0xd4, 0x05, }, 6, 0, "", "",
820"c4 e3 49 0a d4 05 \tvroundss $0x5,%xmm4,%xmm6,%xmm2",},
821{{0x62, 0xf3, 0x55, 0x0f, 0x0a, 0xf4, 0x12, }, 7, 0, "", "",
822"62 f3 55 0f 0a f4 12 \tvrndscaless $0x12,%xmm4,%xmm5,%xmm6{%k7}",},
823{{0xc4, 0xe3, 0x49, 0x0b, 0xd4, 0x05, }, 6, 0, "", "",
824"c4 e3 49 0b d4 05 \tvroundsd $0x5,%xmm4,%xmm6,%xmm2",},
825{{0x62, 0xf3, 0xd5, 0x0f, 0x0b, 0xf4, 0x12, }, 7, 0, "", "",
826"62 f3 d5 0f 0b f4 12 \tvrndscalesd $0x12,%xmm4,%xmm5,%xmm6{%k7}",},
827{{0xc4, 0xe3, 0x5d, 0x18, 0xf4, 0x05, }, 6, 0, "", "",
828"c4 e3 5d 18 f4 05 \tvinsertf128 $0x5,%xmm4,%ymm4,%ymm6",},
829{{0x62, 0xf3, 0x55, 0x4f, 0x18, 0xf4, 0x12, }, 7, 0, "", "",
830"62 f3 55 4f 18 f4 12 \tvinsertf32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}",},
831{{0x62, 0xf3, 0xd5, 0x4f, 0x18, 0xf4, 0x12, }, 7, 0, "", "",
832"62 f3 d5 4f 18 f4 12 \tvinsertf64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}",},
833{{0xc4, 0xe3, 0x7d, 0x19, 0xe4, 0x05, }, 6, 0, "", "",
834"c4 e3 7d 19 e4 05 \tvextractf128 $0x5,%ymm4,%xmm4",},
835{{0x62, 0xf3, 0x7d, 0x4f, 0x19, 0xee, 0x12, }, 7, 0, "", "",
836"62 f3 7d 4f 19 ee 12 \tvextractf32x4 $0x12,%zmm5,%xmm6{%k7}",},
837{{0x62, 0xf3, 0xfd, 0x4f, 0x19, 0xee, 0x12, }, 7, 0, "", "",
838"62 f3 fd 4f 19 ee 12 \tvextractf64x2 $0x12,%zmm5,%xmm6{%k7}",},
839{{0x62, 0xf3, 0x4d, 0x4f, 0x1a, 0xfd, 0x12, }, 7, 0, "", "",
840"62 f3 4d 4f 1a fd 12 \tvinsertf32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}",},
841{{0x62, 0xf3, 0xcd, 0x4f, 0x1a, 0xfd, 0x12, }, 7, 0, "", "",
842"62 f3 cd 4f 1a fd 12 \tvinsertf64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}",},
843{{0x62, 0xf3, 0x7d, 0x4f, 0x1b, 0xf7, 0x12, }, 7, 0, "", "",
844"62 f3 7d 4f 1b f7 12 \tvextractf32x8 $0x12,%zmm6,%ymm7{%k7}",},
845{{0x62, 0xf3, 0xfd, 0x4f, 0x1b, 0xf7, 0x12, }, 7, 0, "", "",
846"62 f3 fd 4f 1b f7 12 \tvextractf64x4 $0x12,%zmm6,%ymm7{%k7}",},
847{{0x62, 0xf3, 0x45, 0x48, 0x1e, 0xee, 0x12, }, 7, 0, "", "",
848"62 f3 45 48 1e ee 12 \tvpcmpud $0x12,%zmm6,%zmm7,%k5",},
849{{0x62, 0xf3, 0xc5, 0x48, 0x1e, 0xee, 0x12, }, 7, 0, "", "",
850"62 f3 c5 48 1e ee 12 \tvpcmpuq $0x12,%zmm6,%zmm7,%k5",},
851{{0x62, 0xf3, 0x45, 0x48, 0x1f, 0xee, 0x12, }, 7, 0, "", "",
852"62 f3 45 48 1f ee 12 \tvpcmpd $0x12,%zmm6,%zmm7,%k5",},
853{{0x62, 0xf3, 0xc5, 0x48, 0x1f, 0xee, 0x12, }, 7, 0, "", "",
854"62 f3 c5 48 1f ee 12 \tvpcmpq $0x12,%zmm6,%zmm7,%k5",},
855{{0x62, 0xf3, 0x4d, 0x48, 0x23, 0xfd, 0x12, }, 7, 0, "", "",
856"62 f3 4d 48 23 fd 12 \tvshuff32x4 $0x12,%zmm5,%zmm6,%zmm7",},
857{{0x62, 0xf3, 0xcd, 0x48, 0x23, 0xfd, 0x12, }, 7, 0, "", "",
858"62 f3 cd 48 23 fd 12 \tvshuff64x2 $0x12,%zmm5,%zmm6,%zmm7",},
859{{0x62, 0xf3, 0x4d, 0x48, 0x25, 0xfd, 0x12, }, 7, 0, "", "",
860"62 f3 4d 48 25 fd 12 \tvpternlogd $0x12,%zmm5,%zmm6,%zmm7",},
861{{0x62, 0xf3, 0xcd, 0x48, 0x25, 0xfd, 0x12, }, 7, 0, "", "",
862"62 f3 cd 48 25 fd 12 \tvpternlogq $0x12,%zmm5,%zmm6,%zmm7",},
863{{0x62, 0xf3, 0x7d, 0x48, 0x26, 0xfe, 0x12, }, 7, 0, "", "",
864"62 f3 7d 48 26 fe 12 \tvgetmantps $0x12,%zmm6,%zmm7",},
865{{0x62, 0xf3, 0xfd, 0x48, 0x26, 0xfe, 0x12, }, 7, 0, "", "",
866"62 f3 fd 48 26 fe 12 \tvgetmantpd $0x12,%zmm6,%zmm7",},
867{{0x62, 0xf3, 0x4d, 0x0f, 0x27, 0xfd, 0x12, }, 7, 0, "", "",
868"62 f3 4d 0f 27 fd 12 \tvgetmantss $0x12,%xmm5,%xmm6,%xmm7{%k7}",},
869{{0x62, 0xf3, 0xcd, 0x0f, 0x27, 0xfd, 0x12, }, 7, 0, "", "",
870"62 f3 cd 0f 27 fd 12 \tvgetmantsd $0x12,%xmm5,%xmm6,%xmm7{%k7}",},
871{{0xc4, 0xe3, 0x5d, 0x38, 0xf4, 0x05, }, 6, 0, "", "",
872"c4 e3 5d 38 f4 05 \tvinserti128 $0x5,%xmm4,%ymm4,%ymm6",},
873{{0x62, 0xf3, 0x55, 0x4f, 0x38, 0xf4, 0x12, }, 7, 0, "", "",
874"62 f3 55 4f 38 f4 12 \tvinserti32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}",},
875{{0x62, 0xf3, 0xd5, 0x4f, 0x38, 0xf4, 0x12, }, 7, 0, "", "",
876"62 f3 d5 4f 38 f4 12 \tvinserti64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}",},
877{{0xc4, 0xe3, 0x7d, 0x39, 0xe6, 0x05, }, 6, 0, "", "",
878"c4 e3 7d 39 e6 05 \tvextracti128 $0x5,%ymm4,%xmm6",},
879{{0x62, 0xf3, 0x7d, 0x4f, 0x39, 0xee, 0x12, }, 7, 0, "", "",
880"62 f3 7d 4f 39 ee 12 \tvextracti32x4 $0x12,%zmm5,%xmm6{%k7}",},
881{{0x62, 0xf3, 0xfd, 0x4f, 0x39, 0xee, 0x12, }, 7, 0, "", "",
882"62 f3 fd 4f 39 ee 12 \tvextracti64x2 $0x12,%zmm5,%xmm6{%k7}",},
883{{0x62, 0xf3, 0x4d, 0x4f, 0x3a, 0xfd, 0x12, }, 7, 0, "", "",
884"62 f3 4d 4f 3a fd 12 \tvinserti32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}",},
885{{0x62, 0xf3, 0xcd, 0x4f, 0x3a, 0xfd, 0x12, }, 7, 0, "", "",
886"62 f3 cd 4f 3a fd 12 \tvinserti64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}",},
887{{0x62, 0xf3, 0x7d, 0x4f, 0x3b, 0xf7, 0x12, }, 7, 0, "", "",
888"62 f3 7d 4f 3b f7 12 \tvextracti32x8 $0x12,%zmm6,%ymm7{%k7}",},
889{{0x62, 0xf3, 0xfd, 0x4f, 0x3b, 0xf7, 0x12, }, 7, 0, "", "",
890"62 f3 fd 4f 3b f7 12 \tvextracti64x4 $0x12,%zmm6,%ymm7{%k7}",},
891{{0x62, 0xf3, 0x45, 0x48, 0x3e, 0xee, 0x12, }, 7, 0, "", "",
892"62 f3 45 48 3e ee 12 \tvpcmpub $0x12,%zmm6,%zmm7,%k5",},
893{{0x62, 0xf3, 0xc5, 0x48, 0x3e, 0xee, 0x12, }, 7, 0, "", "",
894"62 f3 c5 48 3e ee 12 \tvpcmpuw $0x12,%zmm6,%zmm7,%k5",},
895{{0x62, 0xf3, 0x45, 0x48, 0x3f, 0xee, 0x12, }, 7, 0, "", "",
896"62 f3 45 48 3f ee 12 \tvpcmpb $0x12,%zmm6,%zmm7,%k5",},
897{{0x62, 0xf3, 0xc5, 0x48, 0x3f, 0xee, 0x12, }, 7, 0, "", "",
898"62 f3 c5 48 3f ee 12 \tvpcmpw $0x12,%zmm6,%zmm7,%k5",},
899{{0xc4, 0xe3, 0x4d, 0x42, 0xd4, 0x05, }, 6, 0, "", "",
900"c4 e3 4d 42 d4 05 \tvmpsadbw $0x5,%ymm4,%ymm6,%ymm2",},
901{{0x62, 0xf3, 0x55, 0x48, 0x42, 0xf4, 0x12, }, 7, 0, "", "",
902"62 f3 55 48 42 f4 12 \tvdbpsadbw $0x12,%zmm4,%zmm5,%zmm6",},
903{{0x62, 0xf3, 0x4d, 0x48, 0x43, 0xfd, 0x12, }, 7, 0, "", "",
904"62 f3 4d 48 43 fd 12 \tvshufi32x4 $0x12,%zmm5,%zmm6,%zmm7",},
905{{0x62, 0xf3, 0xcd, 0x48, 0x43, 0xfd, 0x12, }, 7, 0, "", "",
906"62 f3 cd 48 43 fd 12 \tvshufi64x2 $0x12,%zmm5,%zmm6,%zmm7",},
907{{0x62, 0xf3, 0x4d, 0x48, 0x50, 0xfd, 0x12, }, 7, 0, "", "",
908"62 f3 4d 48 50 fd 12 \tvrangeps $0x12,%zmm5,%zmm6,%zmm7",},
909{{0x62, 0xf3, 0xcd, 0x48, 0x50, 0xfd, 0x12, }, 7, 0, "", "",
910"62 f3 cd 48 50 fd 12 \tvrangepd $0x12,%zmm5,%zmm6,%zmm7",},
911{{0x62, 0xf3, 0x4d, 0x08, 0x51, 0xfd, 0x12, }, 7, 0, "", "",
912"62 f3 4d 08 51 fd 12 \tvrangess $0x12,%xmm5,%xmm6,%xmm7",},
913{{0x62, 0xf3, 0xcd, 0x08, 0x51, 0xfd, 0x12, }, 7, 0, "", "",
914"62 f3 cd 08 51 fd 12 \tvrangesd $0x12,%xmm5,%xmm6,%xmm7",},
915{{0x62, 0xf3, 0x4d, 0x48, 0x54, 0xfd, 0x12, }, 7, 0, "", "",
916"62 f3 4d 48 54 fd 12 \tvfixupimmps $0x12,%zmm5,%zmm6,%zmm7",},
917{{0x62, 0xf3, 0xcd, 0x48, 0x54, 0xfd, 0x12, }, 7, 0, "", "",
918"62 f3 cd 48 54 fd 12 \tvfixupimmpd $0x12,%zmm5,%zmm6,%zmm7",},
919{{0x62, 0xf3, 0x4d, 0x0f, 0x55, 0xfd, 0x12, }, 7, 0, "", "",
920"62 f3 4d 0f 55 fd 12 \tvfixupimmss $0x12,%xmm5,%xmm6,%xmm7{%k7}",},
921{{0x62, 0xf3, 0xcd, 0x0f, 0x55, 0xfd, 0x12, }, 7, 0, "", "",
922"62 f3 cd 0f 55 fd 12 \tvfixupimmsd $0x12,%xmm5,%xmm6,%xmm7{%k7}",},
923{{0x62, 0xf3, 0x7d, 0x48, 0x56, 0xfe, 0x12, }, 7, 0, "", "",
924"62 f3 7d 48 56 fe 12 \tvreduceps $0x12,%zmm6,%zmm7",},
925{{0x62, 0xf3, 0xfd, 0x48, 0x56, 0xfe, 0x12, }, 7, 0, "", "",
926"62 f3 fd 48 56 fe 12 \tvreducepd $0x12,%zmm6,%zmm7",},
927{{0x62, 0xf3, 0x4d, 0x08, 0x57, 0xfd, 0x12, }, 7, 0, "", "",
928"62 f3 4d 08 57 fd 12 \tvreducess $0x12,%xmm5,%xmm6,%xmm7",},
929{{0x62, 0xf3, 0xcd, 0x08, 0x57, 0xfd, 0x12, }, 7, 0, "", "",
930"62 f3 cd 08 57 fd 12 \tvreducesd $0x12,%xmm5,%xmm6,%xmm7",},
931{{0x62, 0xf3, 0x7d, 0x48, 0x66, 0xef, 0x12, }, 7, 0, "", "",
932"62 f3 7d 48 66 ef 12 \tvfpclassps $0x12,%zmm7,%k5",},
933{{0x62, 0xf3, 0xfd, 0x48, 0x66, 0xef, 0x12, }, 7, 0, "", "",
934"62 f3 fd 48 66 ef 12 \tvfpclasspd $0x12,%zmm7,%k5",},
935{{0x62, 0xf3, 0x7d, 0x08, 0x67, 0xef, 0x12, }, 7, 0, "", "",
936"62 f3 7d 08 67 ef 12 \tvfpclassss $0x12,%xmm7,%k5",},
937{{0x62, 0xf3, 0xfd, 0x08, 0x67, 0xef, 0x12, }, 7, 0, "", "",
938"62 f3 fd 08 67 ef 12 \tvfpclasssd $0x12,%xmm7,%k5",},
939{{0x62, 0xf1, 0x4d, 0x48, 0x72, 0xc5, 0x12, }, 7, 0, "", "",
940"62 f1 4d 48 72 c5 12 \tvprord $0x12,%zmm5,%zmm6",},
941{{0x62, 0xf1, 0xcd, 0x48, 0x72, 0xc5, 0x12, }, 7, 0, "", "",
942"62 f1 cd 48 72 c5 12 \tvprorq $0x12,%zmm5,%zmm6",},
943{{0x62, 0xf1, 0x4d, 0x48, 0x72, 0xcd, 0x12, }, 7, 0, "", "",
944"62 f1 4d 48 72 cd 12 \tvprold $0x12,%zmm5,%zmm6",},
945{{0x62, 0xf1, 0xcd, 0x48, 0x72, 0xcd, 0x12, }, 7, 0, "", "",
946"62 f1 cd 48 72 cd 12 \tvprolq $0x12,%zmm5,%zmm6",},
947{{0x0f, 0x72, 0xe6, 0x02, }, 4, 0, "", "",
948"0f 72 e6 02 \tpsrad $0x2,%mm6",},
949{{0xc5, 0xed, 0x72, 0xe6, 0x05, }, 5, 0, "", "",
950"c5 ed 72 e6 05 \tvpsrad $0x5,%ymm6,%ymm2",},
951{{0x62, 0xf1, 0x6d, 0x48, 0x72, 0xe6, 0x05, }, 7, 0, "", "",
952"62 f1 6d 48 72 e6 05 \tvpsrad $0x5,%zmm6,%zmm2",},
953{{0x62, 0xf1, 0xed, 0x48, 0x72, 0xe6, 0x05, }, 7, 0, "", "",
954"62 f1 ed 48 72 e6 05 \tvpsraq $0x5,%zmm6,%zmm2",},
955{{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
956"62 f2 7d 49 c6 8c fd 7b 00 00 00 \tvgatherpf0dps 0x7b(%ebp,%zmm7,8){%k1}",},
957{{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
958"62 f2 fd 49 c6 8c fd 7b 00 00 00 \tvgatherpf0dpd 0x7b(%ebp,%ymm7,8){%k1}",},
959{{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
960"62 f2 7d 49 c6 94 fd 7b 00 00 00 \tvgatherpf1dps 0x7b(%ebp,%zmm7,8){%k1}",},
961{{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
962"62 f2 fd 49 c6 94 fd 7b 00 00 00 \tvgatherpf1dpd 0x7b(%ebp,%ymm7,8){%k1}",},
963{{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
964"62 f2 7d 49 c6 ac fd 7b 00 00 00 \tvscatterpf0dps 0x7b(%ebp,%zmm7,8){%k1}",},
965{{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
966"62 f2 fd 49 c6 ac fd 7b 00 00 00 \tvscatterpf0dpd 0x7b(%ebp,%ymm7,8){%k1}",},
967{{0x62, 0xf2, 0x7d, 0x49, 0xc6, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
968"62 f2 7d 49 c6 b4 fd 7b 00 00 00 \tvscatterpf1dps 0x7b(%ebp,%zmm7,8){%k1}",},
969{{0x62, 0xf2, 0xfd, 0x49, 0xc6, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
970"62 f2 fd 49 c6 b4 fd 7b 00 00 00 \tvscatterpf1dpd 0x7b(%ebp,%ymm7,8){%k1}",},
971{{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
972"62 f2 7d 49 c7 8c fd 7b 00 00 00 \tvgatherpf0qps 0x7b(%ebp,%zmm7,8){%k1}",},
973{{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0x8c, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
974"62 f2 fd 49 c7 8c fd 7b 00 00 00 \tvgatherpf0qpd 0x7b(%ebp,%zmm7,8){%k1}",},
975{{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
976"62 f2 7d 49 c7 94 fd 7b 00 00 00 \tvgatherpf1qps 0x7b(%ebp,%zmm7,8){%k1}",},
977{{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0x94, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
978"62 f2 fd 49 c7 94 fd 7b 00 00 00 \tvgatherpf1qpd 0x7b(%ebp,%zmm7,8){%k1}",},
979{{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
980"62 f2 7d 49 c7 ac fd 7b 00 00 00 \tvscatterpf0qps 0x7b(%ebp,%zmm7,8){%k1}",},
981{{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0xac, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
982"62 f2 fd 49 c7 ac fd 7b 00 00 00 \tvscatterpf0qpd 0x7b(%ebp,%zmm7,8){%k1}",},
983{{0x62, 0xf2, 0x7d, 0x49, 0xc7, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
984"62 f2 7d 49 c7 b4 fd 7b 00 00 00 \tvscatterpf1qps 0x7b(%ebp,%zmm7,8){%k1}",},
985{{0x62, 0xf2, 0xfd, 0x49, 0xc7, 0xb4, 0xfd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
986"62 f2 fd 49 c7 b4 fd 7b 00 00 00 \tvscatterpf1qpd 0x7b(%ebp,%zmm7,8){%k1}",},
987{{0x62, 0xf1, 0xd5, 0x48, 0x58, 0xf4, }, 6, 0, "", "",
988"62 f1 d5 48 58 f4 \tvaddpd %zmm4,%zmm5,%zmm6",},
989{{0x62, 0xf1, 0xd5, 0x4f, 0x58, 0xf4, }, 6, 0, "", "",
990"62 f1 d5 4f 58 f4 \tvaddpd %zmm4,%zmm5,%zmm6{%k7}",},
991{{0x62, 0xf1, 0xd5, 0xcf, 0x58, 0xf4, }, 6, 0, "", "",
992"62 f1 d5 cf 58 f4 \tvaddpd %zmm4,%zmm5,%zmm6{%k7}{z}",},
993{{0x62, 0xf1, 0xd5, 0x18, 0x58, 0xf4, }, 6, 0, "", "",
994"62 f1 d5 18 58 f4 \tvaddpd {rn-sae},%zmm4,%zmm5,%zmm6",},
995{{0x62, 0xf1, 0xd5, 0x58, 0x58, 0xf4, }, 6, 0, "", "",
996"62 f1 d5 58 58 f4 \tvaddpd {ru-sae},%zmm4,%zmm5,%zmm6",},
997{{0x62, 0xf1, 0xd5, 0x38, 0x58, 0xf4, }, 6, 0, "", "",
998"62 f1 d5 38 58 f4 \tvaddpd {rd-sae},%zmm4,%zmm5,%zmm6",},
999{{0x62, 0xf1, 0xd5, 0x78, 0x58, 0xf4, }, 6, 0, "", "",
1000"62 f1 d5 78 58 f4 \tvaddpd {rz-sae},%zmm4,%zmm5,%zmm6",},
1001{{0x62, 0xf1, 0xd5, 0x48, 0x58, 0x31, }, 6, 0, "", "",
1002"62 f1 d5 48 58 31 \tvaddpd (%ecx),%zmm5,%zmm6",},
1003{{0x62, 0xf1, 0xd5, 0x48, 0x58, 0xb4, 0xc8, 0x23, 0x01, 0x00, 0x00, }, 11, 0, "", "",
1004"62 f1 d5 48 58 b4 c8 23 01 00 00 \tvaddpd 0x123(%eax,%ecx,8),%zmm5,%zmm6",},
1005{{0x62, 0xf1, 0xd5, 0x58, 0x58, 0x31, }, 6, 0, "", "",
1006"62 f1 d5 58 58 31 \tvaddpd (%ecx){1to8},%zmm5,%zmm6",},
1007{{0x62, 0xf1, 0xd5, 0x48, 0x58, 0x72, 0x7f, }, 7, 0, "", "",
1008"62 f1 d5 48 58 72 7f \tvaddpd 0x1fc0(%edx),%zmm5,%zmm6",},
1009{{0x62, 0xf1, 0xd5, 0x58, 0x58, 0x72, 0x7f, }, 7, 0, "", "",
1010"62 f1 d5 58 58 72 7f \tvaddpd 0x3f8(%edx){1to8},%zmm5,%zmm6",},
1011{{0x62, 0xf1, 0x4c, 0x58, 0xc2, 0x6a, 0x7f, 0x08, }, 8, 0, "", "",
1012"62 f1 4c 58 c2 6a 7f 08 \tvcmpeq_uqps 0x1fc(%edx){1to16},%zmm6,%k5",},
1013{{0x62, 0xf1, 0xe7, 0x0f, 0xc2, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, 0x01, }, 12, 0, "", "",
1014"62 f1 e7 0f c2 ac c8 23 01 00 00 01 \tvcmpltsd 0x123(%eax,%ecx,8),%xmm3,%k5{%k7}",},
1015{{0x62, 0xf1, 0xd7, 0x1f, 0xc2, 0xec, 0x02, }, 7, 0, "", "",
1016"62 f1 d7 1f c2 ec 02 \tvcmplesd {sae},%xmm4,%xmm5,%k5{%k7}",},
1017{{0x62, 0xf3, 0x5d, 0x0f, 0x27, 0xac, 0xc8, 0x23, 0x01, 0x00, 0x00, 0x5b, }, 12, 0, "", "",
1018"62 f3 5d 0f 27 ac c8 23 01 00 00 5b \tvgetmantss $0x5b,0x123(%eax,%ecx,8),%xmm4,%xmm5{%k7}",},
9{{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", 1019{{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
10"f3 0f 1b 00 \tbndmk (%eax),%bnd0",}, 1020"f3 0f 1b 00 \tbndmk (%eax),%bnd0",},
11{{0xf3, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", 1021{{0xf3, 0x0f, 0x1b, 0x05, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
@@ -309,19 +1319,19 @@
309{{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", 1319{{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
310"0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%eax,%ecx,1)",}, 1320"0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%eax,%ecx,1)",},
311{{0xf2, 0xe8, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "call", "unconditional", 1321{{0xf2, 0xe8, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "call", "unconditional",
312"f2 e8 fc ff ff ff \tbnd call 3c3 <main+0x3c3>",}, 1322"f2 e8 fc ff ff ff \tbnd call fce <main+0xfce>",},
313{{0xf2, 0xff, 0x10, }, 3, 0, "call", "indirect", 1323{{0xf2, 0xff, 0x10, }, 3, 0, "call", "indirect",
314"f2 ff 10 \tbnd call *(%eax)",}, 1324"f2 ff 10 \tbnd call *(%eax)",},
315{{0xf2, 0xc3, }, 2, 0, "ret", "indirect", 1325{{0xf2, 0xc3, }, 2, 0, "ret", "indirect",
316"f2 c3 \tbnd ret ",}, 1326"f2 c3 \tbnd ret ",},
317{{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", 1327{{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional",
318"f2 e9 fc ff ff ff \tbnd jmp 3ce <main+0x3ce>",}, 1328"f2 e9 fc ff ff ff \tbnd jmp fd9 <main+0xfd9>",},
319{{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional", 1329{{0xf2, 0xe9, 0xfc, 0xff, 0xff, 0xff, }, 6, 0xfffffffc, "jmp", "unconditional",
320"f2 e9 fc ff ff ff \tbnd jmp 3d4 <main+0x3d4>",}, 1330"f2 e9 fc ff ff ff \tbnd jmp fdf <main+0xfdf>",},
321{{0xf2, 0xff, 0x21, }, 3, 0, "jmp", "indirect", 1331{{0xf2, 0xff, 0x21, }, 3, 0, "jmp", "indirect",
322"f2 ff 21 \tbnd jmp *(%ecx)",}, 1332"f2 ff 21 \tbnd jmp *(%ecx)",},
323{{0xf2, 0x0f, 0x85, 0xfc, 0xff, 0xff, 0xff, }, 7, 0xfffffffc, "jcc", "conditional", 1333{{0xf2, 0x0f, 0x85, 0xfc, 0xff, 0xff, 0xff, }, 7, 0xfffffffc, "jcc", "conditional",
324"f2 0f 85 fc ff ff ff \tbnd jne 3de <main+0x3de>",}, 1334"f2 0f 85 fc ff ff ff \tbnd jne fe9 <main+0xfe9>",},
325{{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", 1335{{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "",
326"0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, 1336"0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",},
327{{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", 1337{{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "",
@@ -654,5 +1664,3 @@
654"0f c7 1d 78 56 34 12 \txrstors 0x12345678",}, 1664"0f c7 1d 78 56 34 12 \txrstors 0x12345678",},
655{{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", 1665{{0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
656"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",}, 1666"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%eax,%ecx,8)",},
657{{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "",
658"66 0f ae f8 \tpcommit ",},
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-64.c b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
index 4fe7cce179c4..af25bc8240d0 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-64.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-64.c
@@ -6,6 +6,938 @@
6 6
7{{0x0f, 0x31, }, 2, 0, "", "", 7{{0x0f, 0x31, }, 2, 0, "", "",
8"0f 31 \trdtsc ",}, 8"0f 31 \trdtsc ",},
9{{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "",
10"c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",},
11{{0x48, 0x0f, 0x41, 0xd8, }, 4, 0, "", "",
12"48 0f 41 d8 \tcmovno %rax,%rbx",},
13{{0x48, 0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
14"48 0f 41 88 78 56 34 12 \tcmovno 0x12345678(%rax),%rcx",},
15{{0x66, 0x0f, 0x41, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
16"66 0f 41 88 78 56 34 12 \tcmovno 0x12345678(%rax),%cx",},
17{{0x48, 0x0f, 0x44, 0xd8, }, 4, 0, "", "",
18"48 0f 44 d8 \tcmove %rax,%rbx",},
19{{0x48, 0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
20"48 0f 44 88 78 56 34 12 \tcmove 0x12345678(%rax),%rcx",},
21{{0x66, 0x0f, 0x44, 0x88, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
22"66 0f 44 88 78 56 34 12 \tcmove 0x12345678(%rax),%cx",},
23{{0x0f, 0x90, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
24"0f 90 80 78 56 34 12 \tseto 0x12345678(%rax)",},
25{{0x0f, 0x91, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
26"0f 91 80 78 56 34 12 \tsetno 0x12345678(%rax)",},
27{{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
28"0f 92 80 78 56 34 12 \tsetb 0x12345678(%rax)",},
29{{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
30"0f 92 80 78 56 34 12 \tsetb 0x12345678(%rax)",},
31{{0x0f, 0x92, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
32"0f 92 80 78 56 34 12 \tsetb 0x12345678(%rax)",},
33{{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
34"0f 93 80 78 56 34 12 \tsetae 0x12345678(%rax)",},
35{{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
36"0f 93 80 78 56 34 12 \tsetae 0x12345678(%rax)",},
37{{0x0f, 0x93, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
38"0f 93 80 78 56 34 12 \tsetae 0x12345678(%rax)",},
39{{0x0f, 0x98, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
40"0f 98 80 78 56 34 12 \tsets 0x12345678(%rax)",},
41{{0x0f, 0x99, 0x80, 0x78, 0x56, 0x34, 0x12, }, 7, 0, "", "",
42"0f 99 80 78 56 34 12 \tsetns 0x12345678(%rax)",},
43{{0xc5, 0xcc, 0x41, 0xef, }, 4, 0, "", "",
44"c5 cc 41 ef \tkandw %k7,%k6,%k5",},
45{{0xc4, 0xe1, 0xcc, 0x41, 0xef, }, 5, 0, "", "",
46"c4 e1 cc 41 ef \tkandq %k7,%k6,%k5",},
47{{0xc5, 0xcd, 0x41, 0xef, }, 4, 0, "", "",
48"c5 cd 41 ef \tkandb %k7,%k6,%k5",},
49{{0xc4, 0xe1, 0xcd, 0x41, 0xef, }, 5, 0, "", "",
50"c4 e1 cd 41 ef \tkandd %k7,%k6,%k5",},
51{{0xc5, 0xcc, 0x42, 0xef, }, 4, 0, "", "",
52"c5 cc 42 ef \tkandnw %k7,%k6,%k5",},
53{{0xc4, 0xe1, 0xcc, 0x42, 0xef, }, 5, 0, "", "",
54"c4 e1 cc 42 ef \tkandnq %k7,%k6,%k5",},
55{{0xc5, 0xcd, 0x42, 0xef, }, 4, 0, "", "",
56"c5 cd 42 ef \tkandnb %k7,%k6,%k5",},
57{{0xc4, 0xe1, 0xcd, 0x42, 0xef, }, 5, 0, "", "",
58"c4 e1 cd 42 ef \tkandnd %k7,%k6,%k5",},
59{{0xc5, 0xf8, 0x44, 0xf7, }, 4, 0, "", "",
60"c5 f8 44 f7 \tknotw %k7,%k6",},
61{{0xc4, 0xe1, 0xf8, 0x44, 0xf7, }, 5, 0, "", "",
62"c4 e1 f8 44 f7 \tknotq %k7,%k6",},
63{{0xc5, 0xf9, 0x44, 0xf7, }, 4, 0, "", "",
64"c5 f9 44 f7 \tknotb %k7,%k6",},
65{{0xc4, 0xe1, 0xf9, 0x44, 0xf7, }, 5, 0, "", "",
66"c4 e1 f9 44 f7 \tknotd %k7,%k6",},
67{{0xc5, 0xcc, 0x45, 0xef, }, 4, 0, "", "",
68"c5 cc 45 ef \tkorw %k7,%k6,%k5",},
69{{0xc4, 0xe1, 0xcc, 0x45, 0xef, }, 5, 0, "", "",
70"c4 e1 cc 45 ef \tkorq %k7,%k6,%k5",},
71{{0xc5, 0xcd, 0x45, 0xef, }, 4, 0, "", "",
72"c5 cd 45 ef \tkorb %k7,%k6,%k5",},
73{{0xc4, 0xe1, 0xcd, 0x45, 0xef, }, 5, 0, "", "",
74"c4 e1 cd 45 ef \tkord %k7,%k6,%k5",},
75{{0xc5, 0xcc, 0x46, 0xef, }, 4, 0, "", "",
76"c5 cc 46 ef \tkxnorw %k7,%k6,%k5",},
77{{0xc4, 0xe1, 0xcc, 0x46, 0xef, }, 5, 0, "", "",
78"c4 e1 cc 46 ef \tkxnorq %k7,%k6,%k5",},
79{{0xc5, 0xcd, 0x46, 0xef, }, 4, 0, "", "",
80"c5 cd 46 ef \tkxnorb %k7,%k6,%k5",},
81{{0xc4, 0xe1, 0xcd, 0x46, 0xef, }, 5, 0, "", "",
82"c4 e1 cd 46 ef \tkxnord %k7,%k6,%k5",},
83{{0xc5, 0xcc, 0x47, 0xef, }, 4, 0, "", "",
84"c5 cc 47 ef \tkxorw %k7,%k6,%k5",},
85{{0xc4, 0xe1, 0xcc, 0x47, 0xef, }, 5, 0, "", "",
86"c4 e1 cc 47 ef \tkxorq %k7,%k6,%k5",},
87{{0xc5, 0xcd, 0x47, 0xef, }, 4, 0, "", "",
88"c5 cd 47 ef \tkxorb %k7,%k6,%k5",},
89{{0xc4, 0xe1, 0xcd, 0x47, 0xef, }, 5, 0, "", "",
90"c4 e1 cd 47 ef \tkxord %k7,%k6,%k5",},
91{{0xc5, 0xcc, 0x4a, 0xef, }, 4, 0, "", "",
92"c5 cc 4a ef \tkaddw %k7,%k6,%k5",},
93{{0xc4, 0xe1, 0xcc, 0x4a, 0xef, }, 5, 0, "", "",
94"c4 e1 cc 4a ef \tkaddq %k7,%k6,%k5",},
95{{0xc5, 0xcd, 0x4a, 0xef, }, 4, 0, "", "",
96"c5 cd 4a ef \tkaddb %k7,%k6,%k5",},
97{{0xc4, 0xe1, 0xcd, 0x4a, 0xef, }, 5, 0, "", "",
98"c4 e1 cd 4a ef \tkaddd %k7,%k6,%k5",},
99{{0xc5, 0xcd, 0x4b, 0xef, }, 4, 0, "", "",
100"c5 cd 4b ef \tkunpckbw %k7,%k6,%k5",},
101{{0xc5, 0xcc, 0x4b, 0xef, }, 4, 0, "", "",
102"c5 cc 4b ef \tkunpckwd %k7,%k6,%k5",},
103{{0xc4, 0xe1, 0xcc, 0x4b, 0xef, }, 5, 0, "", "",
104"c4 e1 cc 4b ef \tkunpckdq %k7,%k6,%k5",},
105{{0xc5, 0xf8, 0x90, 0xee, }, 4, 0, "", "",
106"c5 f8 90 ee \tkmovw %k6,%k5",},
107{{0xc5, 0xf8, 0x90, 0x29, }, 4, 0, "", "",
108"c5 f8 90 29 \tkmovw (%rcx),%k5",},
109{{0xc4, 0xa1, 0x78, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
110"c4 a1 78 90 ac f0 23 01 00 00 \tkmovw 0x123(%rax,%r14,8),%k5",},
111{{0xc5, 0xf8, 0x91, 0x29, }, 4, 0, "", "",
112"c5 f8 91 29 \tkmovw %k5,(%rcx)",},
113{{0xc4, 0xa1, 0x78, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
114"c4 a1 78 91 ac f0 23 01 00 00 \tkmovw %k5,0x123(%rax,%r14,8)",},
115{{0xc5, 0xf8, 0x92, 0xe8, }, 4, 0, "", "",
116"c5 f8 92 e8 \tkmovw %eax,%k5",},
117{{0xc5, 0xf8, 0x92, 0xed, }, 4, 0, "", "",
118"c5 f8 92 ed \tkmovw %ebp,%k5",},
119{{0xc4, 0xc1, 0x78, 0x92, 0xed, }, 5, 0, "", "",
120"c4 c1 78 92 ed \tkmovw %r13d,%k5",},
121{{0xc5, 0xf8, 0x93, 0xc5, }, 4, 0, "", "",
122"c5 f8 93 c5 \tkmovw %k5,%eax",},
123{{0xc5, 0xf8, 0x93, 0xed, }, 4, 0, "", "",
124"c5 f8 93 ed \tkmovw %k5,%ebp",},
125{{0xc5, 0x78, 0x93, 0xed, }, 4, 0, "", "",
126"c5 78 93 ed \tkmovw %k5,%r13d",},
127{{0xc4, 0xe1, 0xf8, 0x90, 0xee, }, 5, 0, "", "",
128"c4 e1 f8 90 ee \tkmovq %k6,%k5",},
129{{0xc4, 0xe1, 0xf8, 0x90, 0x29, }, 5, 0, "", "",
130"c4 e1 f8 90 29 \tkmovq (%rcx),%k5",},
131{{0xc4, 0xa1, 0xf8, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
132"c4 a1 f8 90 ac f0 23 01 00 00 \tkmovq 0x123(%rax,%r14,8),%k5",},
133{{0xc4, 0xe1, 0xf8, 0x91, 0x29, }, 5, 0, "", "",
134"c4 e1 f8 91 29 \tkmovq %k5,(%rcx)",},
135{{0xc4, 0xa1, 0xf8, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
136"c4 a1 f8 91 ac f0 23 01 00 00 \tkmovq %k5,0x123(%rax,%r14,8)",},
137{{0xc4, 0xe1, 0xfb, 0x92, 0xe8, }, 5, 0, "", "",
138"c4 e1 fb 92 e8 \tkmovq %rax,%k5",},
139{{0xc4, 0xe1, 0xfb, 0x92, 0xed, }, 5, 0, "", "",
140"c4 e1 fb 92 ed \tkmovq %rbp,%k5",},
141{{0xc4, 0xc1, 0xfb, 0x92, 0xed, }, 5, 0, "", "",
142"c4 c1 fb 92 ed \tkmovq %r13,%k5",},
143{{0xc4, 0xe1, 0xfb, 0x93, 0xc5, }, 5, 0, "", "",
144"c4 e1 fb 93 c5 \tkmovq %k5,%rax",},
145{{0xc4, 0xe1, 0xfb, 0x93, 0xed, }, 5, 0, "", "",
146"c4 e1 fb 93 ed \tkmovq %k5,%rbp",},
147{{0xc4, 0x61, 0xfb, 0x93, 0xed, }, 5, 0, "", "",
148"c4 61 fb 93 ed \tkmovq %k5,%r13",},
149{{0xc5, 0xf9, 0x90, 0xee, }, 4, 0, "", "",
150"c5 f9 90 ee \tkmovb %k6,%k5",},
151{{0xc5, 0xf9, 0x90, 0x29, }, 4, 0, "", "",
152"c5 f9 90 29 \tkmovb (%rcx),%k5",},
153{{0xc4, 0xa1, 0x79, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
154"c4 a1 79 90 ac f0 23 01 00 00 \tkmovb 0x123(%rax,%r14,8),%k5",},
155{{0xc5, 0xf9, 0x91, 0x29, }, 4, 0, "", "",
156"c5 f9 91 29 \tkmovb %k5,(%rcx)",},
157{{0xc4, 0xa1, 0x79, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
158"c4 a1 79 91 ac f0 23 01 00 00 \tkmovb %k5,0x123(%rax,%r14,8)",},
159{{0xc5, 0xf9, 0x92, 0xe8, }, 4, 0, "", "",
160"c5 f9 92 e8 \tkmovb %eax,%k5",},
161{{0xc5, 0xf9, 0x92, 0xed, }, 4, 0, "", "",
162"c5 f9 92 ed \tkmovb %ebp,%k5",},
163{{0xc4, 0xc1, 0x79, 0x92, 0xed, }, 5, 0, "", "",
164"c4 c1 79 92 ed \tkmovb %r13d,%k5",},
165{{0xc5, 0xf9, 0x93, 0xc5, }, 4, 0, "", "",
166"c5 f9 93 c5 \tkmovb %k5,%eax",},
167{{0xc5, 0xf9, 0x93, 0xed, }, 4, 0, "", "",
168"c5 f9 93 ed \tkmovb %k5,%ebp",},
169{{0xc5, 0x79, 0x93, 0xed, }, 4, 0, "", "",
170"c5 79 93 ed \tkmovb %k5,%r13d",},
171{{0xc4, 0xe1, 0xf9, 0x90, 0xee, }, 5, 0, "", "",
172"c4 e1 f9 90 ee \tkmovd %k6,%k5",},
173{{0xc4, 0xe1, 0xf9, 0x90, 0x29, }, 5, 0, "", "",
174"c4 e1 f9 90 29 \tkmovd (%rcx),%k5",},
175{{0xc4, 0xa1, 0xf9, 0x90, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
176"c4 a1 f9 90 ac f0 23 01 00 00 \tkmovd 0x123(%rax,%r14,8),%k5",},
177{{0xc4, 0xe1, 0xf9, 0x91, 0x29, }, 5, 0, "", "",
178"c4 e1 f9 91 29 \tkmovd %k5,(%rcx)",},
179{{0xc4, 0xa1, 0xf9, 0x91, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 10, 0, "", "",
180"c4 a1 f9 91 ac f0 23 01 00 00 \tkmovd %k5,0x123(%rax,%r14,8)",},
181{{0xc5, 0xfb, 0x92, 0xe8, }, 4, 0, "", "",
182"c5 fb 92 e8 \tkmovd %eax,%k5",},
183{{0xc5, 0xfb, 0x92, 0xed, }, 4, 0, "", "",
184"c5 fb 92 ed \tkmovd %ebp,%k5",},
185{{0xc4, 0xc1, 0x7b, 0x92, 0xed, }, 5, 0, "", "",
186"c4 c1 7b 92 ed \tkmovd %r13d,%k5",},
187{{0xc5, 0xfb, 0x93, 0xc5, }, 4, 0, "", "",
188"c5 fb 93 c5 \tkmovd %k5,%eax",},
189{{0xc5, 0xfb, 0x93, 0xed, }, 4, 0, "", "",
190"c5 fb 93 ed \tkmovd %k5,%ebp",},
191{{0xc5, 0x7b, 0x93, 0xed, }, 4, 0, "", "",
192"c5 7b 93 ed \tkmovd %k5,%r13d",},
193{{0xc5, 0xf8, 0x98, 0xee, }, 4, 0, "", "",
194"c5 f8 98 ee \tkortestw %k6,%k5",},
195{{0xc4, 0xe1, 0xf8, 0x98, 0xee, }, 5, 0, "", "",
196"c4 e1 f8 98 ee \tkortestq %k6,%k5",},
197{{0xc5, 0xf9, 0x98, 0xee, }, 4, 0, "", "",
198"c5 f9 98 ee \tkortestb %k6,%k5",},
199{{0xc4, 0xe1, 0xf9, 0x98, 0xee, }, 5, 0, "", "",
200"c4 e1 f9 98 ee \tkortestd %k6,%k5",},
201{{0xc5, 0xf8, 0x99, 0xee, }, 4, 0, "", "",
202"c5 f8 99 ee \tktestw %k6,%k5",},
203{{0xc4, 0xe1, 0xf8, 0x99, 0xee, }, 5, 0, "", "",
204"c4 e1 f8 99 ee \tktestq %k6,%k5",},
205{{0xc5, 0xf9, 0x99, 0xee, }, 4, 0, "", "",
206"c5 f9 99 ee \tktestb %k6,%k5",},
207{{0xc4, 0xe1, 0xf9, 0x99, 0xee, }, 5, 0, "", "",
208"c4 e1 f9 99 ee \tktestd %k6,%k5",},
209{{0xc4, 0xe3, 0xf9, 0x30, 0xee, 0x12, }, 6, 0, "", "",
210"c4 e3 f9 30 ee 12 \tkshiftrw $0x12,%k6,%k5",},
211{{0xc4, 0xe3, 0xf9, 0x31, 0xee, 0x5b, }, 6, 0, "", "",
212"c4 e3 f9 31 ee 5b \tkshiftrq $0x5b,%k6,%k5",},
213{{0xc4, 0xe3, 0xf9, 0x32, 0xee, 0x12, }, 6, 0, "", "",
214"c4 e3 f9 32 ee 12 \tkshiftlw $0x12,%k6,%k5",},
215{{0xc4, 0xe3, 0xf9, 0x33, 0xee, 0x5b, }, 6, 0, "", "",
216"c4 e3 f9 33 ee 5b \tkshiftlq $0x5b,%k6,%k5",},
217{{0xc5, 0xf8, 0x5b, 0xf5, }, 4, 0, "", "",
218"c5 f8 5b f5 \tvcvtdq2ps %xmm5,%xmm6",},
219{{0x62, 0x91, 0xfc, 0x4f, 0x5b, 0xf5, }, 6, 0, "", "",
220"62 91 fc 4f 5b f5 \tvcvtqq2ps %zmm29,%ymm6{%k7}",},
221{{0xc5, 0xf9, 0x5b, 0xf5, }, 4, 0, "", "",
222"c5 f9 5b f5 \tvcvtps2dq %xmm5,%xmm6",},
223{{0xc5, 0xfa, 0x5b, 0xf5, }, 4, 0, "", "",
224"c5 fa 5b f5 \tvcvttps2dq %xmm5,%xmm6",},
225{{0x0f, 0x6f, 0xe0, }, 3, 0, "", "",
226"0f 6f e0 \tmovq %mm0,%mm4",},
227{{0xc5, 0xfd, 0x6f, 0xf4, }, 4, 0, "", "",
228"c5 fd 6f f4 \tvmovdqa %ymm4,%ymm6",},
229{{0x62, 0x01, 0x7d, 0x48, 0x6f, 0xd1, }, 6, 0, "", "",
230"62 01 7d 48 6f d1 \tvmovdqa32 %zmm25,%zmm26",},
231{{0x62, 0x01, 0xfd, 0x48, 0x6f, 0xd1, }, 6, 0, "", "",
232"62 01 fd 48 6f d1 \tvmovdqa64 %zmm25,%zmm26",},
233{{0xc5, 0xfe, 0x6f, 0xf4, }, 4, 0, "", "",
234"c5 fe 6f f4 \tvmovdqu %ymm4,%ymm6",},
235{{0x62, 0x01, 0x7e, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
236"62 01 7e 48 6f f5 \tvmovdqu32 %zmm29,%zmm30",},
237{{0x62, 0x01, 0xfe, 0x48, 0x6f, 0xd1, }, 6, 0, "", "",
238"62 01 fe 48 6f d1 \tvmovdqu64 %zmm25,%zmm26",},
239{{0x62, 0x01, 0x7f, 0x48, 0x6f, 0xf5, }, 6, 0, "", "",
240"62 01 7f 48 6f f5 \tvmovdqu8 %zmm29,%zmm30",},
241{{0x62, 0x01, 0xff, 0x48, 0x6f, 0xd1, }, 6, 0, "", "",
242"62 01 ff 48 6f d1 \tvmovdqu16 %zmm25,%zmm26",},
243{{0x0f, 0x78, 0xc3, }, 3, 0, "", "",
244"0f 78 c3 \tvmread %rax,%rbx",},
245{{0x62, 0x01, 0x7c, 0x48, 0x78, 0xd1, }, 6, 0, "", "",
246"62 01 7c 48 78 d1 \tvcvttps2udq %zmm25,%zmm26",},
247{{0x62, 0x91, 0xfc, 0x4f, 0x78, 0xf5, }, 6, 0, "", "",
248"62 91 fc 4f 78 f5 \tvcvttpd2udq %zmm29,%ymm6{%k7}",},
249{{0x62, 0xf1, 0xff, 0x08, 0x78, 0xc6, }, 6, 0, "", "",
250"62 f1 ff 08 78 c6 \tvcvttsd2usi %xmm6,%rax",},
251{{0x62, 0xf1, 0xfe, 0x08, 0x78, 0xc6, }, 6, 0, "", "",
252"62 f1 fe 08 78 c6 \tvcvttss2usi %xmm6,%rax",},
253{{0x62, 0x61, 0x7d, 0x4f, 0x78, 0xd5, }, 6, 0, "", "",
254"62 61 7d 4f 78 d5 \tvcvttps2uqq %ymm5,%zmm26{%k7}",},
255{{0x62, 0x01, 0xfd, 0x48, 0x78, 0xf5, }, 6, 0, "", "",
256"62 01 fd 48 78 f5 \tvcvttpd2uqq %zmm29,%zmm30",},
257{{0x0f, 0x79, 0xd8, }, 3, 0, "", "",
258"0f 79 d8 \tvmwrite %rax,%rbx",},
259{{0x62, 0x01, 0x7c, 0x48, 0x79, 0xd1, }, 6, 0, "", "",
260"62 01 7c 48 79 d1 \tvcvtps2udq %zmm25,%zmm26",},
261{{0x62, 0x91, 0xfc, 0x4f, 0x79, 0xf5, }, 6, 0, "", "",
262"62 91 fc 4f 79 f5 \tvcvtpd2udq %zmm29,%ymm6{%k7}",},
263{{0x62, 0xf1, 0xff, 0x08, 0x79, 0xc6, }, 6, 0, "", "",
264"62 f1 ff 08 79 c6 \tvcvtsd2usi %xmm6,%rax",},
265{{0x62, 0xf1, 0xfe, 0x08, 0x79, 0xc6, }, 6, 0, "", "",
266"62 f1 fe 08 79 c6 \tvcvtss2usi %xmm6,%rax",},
267{{0x62, 0x61, 0x7d, 0x4f, 0x79, 0xd5, }, 6, 0, "", "",
268"62 61 7d 4f 79 d5 \tvcvtps2uqq %ymm5,%zmm26{%k7}",},
269{{0x62, 0x01, 0xfd, 0x48, 0x79, 0xf5, }, 6, 0, "", "",
270"62 01 fd 48 79 f5 \tvcvtpd2uqq %zmm29,%zmm30",},
271{{0x62, 0x61, 0x7e, 0x4f, 0x7a, 0xed, }, 6, 0, "", "",
272"62 61 7e 4f 7a ed \tvcvtudq2pd %ymm5,%zmm29{%k7}",},
273{{0x62, 0x01, 0xfe, 0x48, 0x7a, 0xd1, }, 6, 0, "", "",
274"62 01 fe 48 7a d1 \tvcvtuqq2pd %zmm25,%zmm26",},
275{{0x62, 0x01, 0x7f, 0x48, 0x7a, 0xf5, }, 6, 0, "", "",
276"62 01 7f 48 7a f5 \tvcvtudq2ps %zmm29,%zmm30",},
277{{0x62, 0x01, 0xff, 0x4f, 0x7a, 0xd1, }, 6, 0, "", "",
278"62 01 ff 4f 7a d1 \tvcvtuqq2ps %zmm25,%ymm26{%k7}",},
279{{0x62, 0x01, 0x7d, 0x4f, 0x7a, 0xd1, }, 6, 0, "", "",
280"62 01 7d 4f 7a d1 \tvcvttps2qq %ymm25,%zmm26{%k7}",},
281{{0x62, 0x01, 0xfd, 0x48, 0x7a, 0xf5, }, 6, 0, "", "",
282"62 01 fd 48 7a f5 \tvcvttpd2qq %zmm29,%zmm30",},
283{{0x62, 0xf1, 0x57, 0x08, 0x7b, 0xf0, }, 6, 0, "", "",
284"62 f1 57 08 7b f0 \tvcvtusi2sd %eax,%xmm5,%xmm6",},
285{{0x62, 0xf1, 0x56, 0x08, 0x7b, 0xf0, }, 6, 0, "", "",
286"62 f1 56 08 7b f0 \tvcvtusi2ss %eax,%xmm5,%xmm6",},
287{{0x62, 0x61, 0x7d, 0x4f, 0x7b, 0xd5, }, 6, 0, "", "",
288"62 61 7d 4f 7b d5 \tvcvtps2qq %ymm5,%zmm26{%k7}",},
289{{0x62, 0x01, 0xfd, 0x48, 0x7b, 0xf5, }, 6, 0, "", "",
290"62 01 fd 48 7b f5 \tvcvtpd2qq %zmm29,%zmm30",},
291{{0x0f, 0x7f, 0xc4, }, 3, 0, "", "",
292"0f 7f c4 \tmovq %mm0,%mm4",},
293{{0xc5, 0x7d, 0x7f, 0xc6, }, 4, 0, "", "",
294"c5 7d 7f c6 \tvmovdqa %ymm8,%ymm6",},
295{{0x62, 0x01, 0x7d, 0x48, 0x7f, 0xca, }, 6, 0, "", "",
296"62 01 7d 48 7f ca \tvmovdqa32 %zmm25,%zmm26",},
297{{0x62, 0x01, 0xfd, 0x48, 0x7f, 0xca, }, 6, 0, "", "",
298"62 01 fd 48 7f ca \tvmovdqa64 %zmm25,%zmm26",},
299{{0xc5, 0x7e, 0x7f, 0xc6, }, 4, 0, "", "",
300"c5 7e 7f c6 \tvmovdqu %ymm8,%ymm6",},
301{{0x62, 0x01, 0x7e, 0x48, 0x7f, 0xca, }, 6, 0, "", "",
302"62 01 7e 48 7f ca \tvmovdqu32 %zmm25,%zmm26",},
303{{0x62, 0x01, 0xfe, 0x48, 0x7f, 0xca, }, 6, 0, "", "",
304"62 01 fe 48 7f ca \tvmovdqu64 %zmm25,%zmm26",},
305{{0x62, 0x61, 0x7f, 0x48, 0x7f, 0x31, }, 6, 0, "", "",
306"62 61 7f 48 7f 31 \tvmovdqu8 %zmm30,(%rcx)",},
307{{0x62, 0x01, 0xff, 0x48, 0x7f, 0xca, }, 6, 0, "", "",
308"62 01 ff 48 7f ca \tvmovdqu16 %zmm25,%zmm26",},
309{{0x0f, 0xdb, 0xd1, }, 3, 0, "", "",
310"0f db d1 \tpand %mm1,%mm2",},
311{{0x66, 0x0f, 0xdb, 0xd1, }, 4, 0, "", "",
312"66 0f db d1 \tpand %xmm1,%xmm2",},
313{{0xc5, 0xcd, 0xdb, 0xd4, }, 4, 0, "", "",
314"c5 cd db d4 \tvpand %ymm4,%ymm6,%ymm2",},
315{{0x62, 0x01, 0x35, 0x40, 0xdb, 0xd0, }, 6, 0, "", "",
316"62 01 35 40 db d0 \tvpandd %zmm24,%zmm25,%zmm26",},
317{{0x62, 0x01, 0xb5, 0x40, 0xdb, 0xd0, }, 6, 0, "", "",
318"62 01 b5 40 db d0 \tvpandq %zmm24,%zmm25,%zmm26",},
319{{0x0f, 0xdf, 0xd1, }, 3, 0, "", "",
320"0f df d1 \tpandn %mm1,%mm2",},
321{{0x66, 0x0f, 0xdf, 0xd1, }, 4, 0, "", "",
322"66 0f df d1 \tpandn %xmm1,%xmm2",},
323{{0xc5, 0xcd, 0xdf, 0xd4, }, 4, 0, "", "",
324"c5 cd df d4 \tvpandn %ymm4,%ymm6,%ymm2",},
325{{0x62, 0x01, 0x35, 0x40, 0xdf, 0xd0, }, 6, 0, "", "",
326"62 01 35 40 df d0 \tvpandnd %zmm24,%zmm25,%zmm26",},
327{{0x62, 0x01, 0xb5, 0x40, 0xdf, 0xd0, }, 6, 0, "", "",
328"62 01 b5 40 df d0 \tvpandnq %zmm24,%zmm25,%zmm26",},
329{{0xc5, 0xf9, 0xe6, 0xd1, }, 4, 0, "", "",
330"c5 f9 e6 d1 \tvcvttpd2dq %xmm1,%xmm2",},
331{{0xc5, 0xfa, 0xe6, 0xf5, }, 4, 0, "", "",
332"c5 fa e6 f5 \tvcvtdq2pd %xmm5,%xmm6",},
333{{0x62, 0x61, 0x7e, 0x4f, 0xe6, 0xd5, }, 6, 0, "", "",
334"62 61 7e 4f e6 d5 \tvcvtdq2pd %ymm5,%zmm26{%k7}",},
335{{0x62, 0x01, 0xfe, 0x48, 0xe6, 0xd1, }, 6, 0, "", "",
336"62 01 fe 48 e6 d1 \tvcvtqq2pd %zmm25,%zmm26",},
337{{0xc5, 0xfb, 0xe6, 0xd1, }, 4, 0, "", "",
338"c5 fb e6 d1 \tvcvtpd2dq %xmm1,%xmm2",},
339{{0x0f, 0xeb, 0xf4, }, 3, 0, "", "",
340"0f eb f4 \tpor %mm4,%mm6",},
341{{0xc5, 0xcd, 0xeb, 0xd4, }, 4, 0, "", "",
342"c5 cd eb d4 \tvpor %ymm4,%ymm6,%ymm2",},
343{{0x62, 0x01, 0x35, 0x40, 0xeb, 0xd0, }, 6, 0, "", "",
344"62 01 35 40 eb d0 \tvpord %zmm24,%zmm25,%zmm26",},
345{{0x62, 0x01, 0xb5, 0x40, 0xeb, 0xd0, }, 6, 0, "", "",
346"62 01 b5 40 eb d0 \tvporq %zmm24,%zmm25,%zmm26",},
347{{0x0f, 0xef, 0xf4, }, 3, 0, "", "",
348"0f ef f4 \tpxor %mm4,%mm6",},
349{{0xc5, 0xcd, 0xef, 0xd4, }, 4, 0, "", "",
350"c5 cd ef d4 \tvpxor %ymm4,%ymm6,%ymm2",},
351{{0x62, 0x01, 0x35, 0x40, 0xef, 0xd0, }, 6, 0, "", "",
352"62 01 35 40 ef d0 \tvpxord %zmm24,%zmm25,%zmm26",},
353{{0x62, 0x01, 0xb5, 0x40, 0xef, 0xd0, }, 6, 0, "", "",
354"62 01 b5 40 ef d0 \tvpxorq %zmm24,%zmm25,%zmm26",},
355{{0x66, 0x0f, 0x38, 0x10, 0xc1, }, 5, 0, "", "",
356"66 0f 38 10 c1 \tpblendvb %xmm0,%xmm1,%xmm0",},
357{{0x62, 0x02, 0x9d, 0x40, 0x10, 0xeb, }, 6, 0, "", "",
358"62 02 9d 40 10 eb \tvpsrlvw %zmm27,%zmm28,%zmm29",},
359{{0x62, 0x62, 0x7e, 0x4f, 0x10, 0xe6, }, 6, 0, "", "",
360"62 62 7e 4f 10 e6 \tvpmovuswb %zmm28,%ymm6{%k7}",},
361{{0x62, 0x62, 0x7e, 0x4f, 0x11, 0xe6, }, 6, 0, "", "",
362"62 62 7e 4f 11 e6 \tvpmovusdb %zmm28,%xmm6{%k7}",},
363{{0x62, 0x02, 0x9d, 0x40, 0x11, 0xeb, }, 6, 0, "", "",
364"62 02 9d 40 11 eb \tvpsravw %zmm27,%zmm28,%zmm29",},
365{{0x62, 0x62, 0x7e, 0x4f, 0x12, 0xde, }, 6, 0, "", "",
366"62 62 7e 4f 12 de \tvpmovusqb %zmm27,%xmm6{%k7}",},
367{{0x62, 0x02, 0x9d, 0x40, 0x12, 0xeb, }, 6, 0, "", "",
368"62 02 9d 40 12 eb \tvpsllvw %zmm27,%zmm28,%zmm29",},
369{{0xc4, 0xe2, 0x7d, 0x13, 0xeb, }, 5, 0, "", "",
370"c4 e2 7d 13 eb \tvcvtph2ps %xmm3,%ymm5",},
371{{0x62, 0x62, 0x7d, 0x4f, 0x13, 0xdd, }, 6, 0, "", "",
372"62 62 7d 4f 13 dd \tvcvtph2ps %ymm5,%zmm27{%k7}",},
373{{0x62, 0x62, 0x7e, 0x4f, 0x13, 0xde, }, 6, 0, "", "",
374"62 62 7e 4f 13 de \tvpmovusdw %zmm27,%ymm6{%k7}",},
375{{0x66, 0x0f, 0x38, 0x14, 0xc1, }, 5, 0, "", "",
376"66 0f 38 14 c1 \tblendvps %xmm0,%xmm1,%xmm0",},
377{{0x62, 0x62, 0x7e, 0x4f, 0x14, 0xde, }, 6, 0, "", "",
378"62 62 7e 4f 14 de \tvpmovusqw %zmm27,%xmm6{%k7}",},
379{{0x62, 0x02, 0x1d, 0x40, 0x14, 0xeb, }, 6, 0, "", "",
380"62 02 1d 40 14 eb \tvprorvd %zmm27,%zmm28,%zmm29",},
381{{0x62, 0x02, 0x9d, 0x40, 0x14, 0xeb, }, 6, 0, "", "",
382"62 02 9d 40 14 eb \tvprorvq %zmm27,%zmm28,%zmm29",},
383{{0x66, 0x0f, 0x38, 0x15, 0xc1, }, 5, 0, "", "",
384"66 0f 38 15 c1 \tblendvpd %xmm0,%xmm1,%xmm0",},
385{{0x62, 0x62, 0x7e, 0x4f, 0x15, 0xde, }, 6, 0, "", "",
386"62 62 7e 4f 15 de \tvpmovusqd %zmm27,%ymm6{%k7}",},
387{{0x62, 0x02, 0x1d, 0x40, 0x15, 0xeb, }, 6, 0, "", "",
388"62 02 1d 40 15 eb \tvprolvd %zmm27,%zmm28,%zmm29",},
389{{0x62, 0x02, 0x9d, 0x40, 0x15, 0xeb, }, 6, 0, "", "",
390"62 02 9d 40 15 eb \tvprolvq %zmm27,%zmm28,%zmm29",},
391{{0xc4, 0xe2, 0x4d, 0x16, 0xd4, }, 5, 0, "", "",
392"c4 e2 4d 16 d4 \tvpermps %ymm4,%ymm6,%ymm2",},
393{{0x62, 0x82, 0x2d, 0x27, 0x16, 0xf0, }, 6, 0, "", "",
394"62 82 2d 27 16 f0 \tvpermps %ymm24,%ymm26,%ymm22{%k7}",},
395{{0x62, 0x82, 0xad, 0x27, 0x16, 0xf0, }, 6, 0, "", "",
396"62 82 ad 27 16 f0 \tvpermpd %ymm24,%ymm26,%ymm22{%k7}",},
397{{0xc4, 0xe2, 0x7d, 0x19, 0xf4, }, 5, 0, "", "",
398"c4 e2 7d 19 f4 \tvbroadcastsd %xmm4,%ymm6",},
399{{0x62, 0x02, 0x7d, 0x48, 0x19, 0xd3, }, 6, 0, "", "",
400"62 02 7d 48 19 d3 \tvbroadcastf32x2 %xmm27,%zmm26",},
401{{0xc4, 0xe2, 0x7d, 0x1a, 0x21, }, 5, 0, "", "",
402"c4 e2 7d 1a 21 \tvbroadcastf128 (%rcx),%ymm4",},
403{{0x62, 0x62, 0x7d, 0x48, 0x1a, 0x11, }, 6, 0, "", "",
404"62 62 7d 48 1a 11 \tvbroadcastf32x4 (%rcx),%zmm26",},
405{{0x62, 0x62, 0xfd, 0x48, 0x1a, 0x11, }, 6, 0, "", "",
406"62 62 fd 48 1a 11 \tvbroadcastf64x2 (%rcx),%zmm26",},
407{{0x62, 0x62, 0x7d, 0x48, 0x1b, 0x19, }, 6, 0, "", "",
408"62 62 7d 48 1b 19 \tvbroadcastf32x8 (%rcx),%zmm27",},
409{{0x62, 0x62, 0xfd, 0x48, 0x1b, 0x11, }, 6, 0, "", "",
410"62 62 fd 48 1b 11 \tvbroadcastf64x4 (%rcx),%zmm26",},
411{{0x62, 0x02, 0xfd, 0x48, 0x1f, 0xe3, }, 6, 0, "", "",
412"62 02 fd 48 1f e3 \tvpabsq %zmm27,%zmm28",},
413{{0xc4, 0xe2, 0x79, 0x20, 0xec, }, 5, 0, "", "",
414"c4 e2 79 20 ec \tvpmovsxbw %xmm4,%xmm5",},
415{{0x62, 0x62, 0x7e, 0x4f, 0x20, 0xde, }, 6, 0, "", "",
416"62 62 7e 4f 20 de \tvpmovswb %zmm27,%ymm6{%k7}",},
417{{0xc4, 0xe2, 0x7d, 0x21, 0xf4, }, 5, 0, "", "",
418"c4 e2 7d 21 f4 \tvpmovsxbd %xmm4,%ymm6",},
419{{0x62, 0x62, 0x7e, 0x4f, 0x21, 0xde, }, 6, 0, "", "",
420"62 62 7e 4f 21 de \tvpmovsdb %zmm27,%xmm6{%k7}",},
421{{0xc4, 0xe2, 0x7d, 0x22, 0xe4, }, 5, 0, "", "",
422"c4 e2 7d 22 e4 \tvpmovsxbq %xmm4,%ymm4",},
423{{0x62, 0x62, 0x7e, 0x4f, 0x22, 0xde, }, 6, 0, "", "",
424"62 62 7e 4f 22 de \tvpmovsqb %zmm27,%xmm6{%k7}",},
425{{0xc4, 0xe2, 0x7d, 0x23, 0xe4, }, 5, 0, "", "",
426"c4 e2 7d 23 e4 \tvpmovsxwd %xmm4,%ymm4",},
427{{0x62, 0x62, 0x7e, 0x4f, 0x23, 0xde, }, 6, 0, "", "",
428"62 62 7e 4f 23 de \tvpmovsdw %zmm27,%ymm6{%k7}",},
429{{0xc4, 0xe2, 0x7d, 0x24, 0xf4, }, 5, 0, "", "",
430"c4 e2 7d 24 f4 \tvpmovsxwq %xmm4,%ymm6",},
431{{0x62, 0x62, 0x7e, 0x4f, 0x24, 0xde, }, 6, 0, "", "",
432"62 62 7e 4f 24 de \tvpmovsqw %zmm27,%xmm6{%k7}",},
433{{0xc4, 0xe2, 0x7d, 0x25, 0xe4, }, 5, 0, "", "",
434"c4 e2 7d 25 e4 \tvpmovsxdq %xmm4,%ymm4",},
435{{0x62, 0x62, 0x7e, 0x4f, 0x25, 0xde, }, 6, 0, "", "",
436"62 62 7e 4f 25 de \tvpmovsqd %zmm27,%ymm6{%k7}",},
437{{0x62, 0x92, 0x1d, 0x40, 0x26, 0xeb, }, 6, 0, "", "",
438"62 92 1d 40 26 eb \tvptestmb %zmm27,%zmm28,%k5",},
439{{0x62, 0x92, 0x9d, 0x40, 0x26, 0xeb, }, 6, 0, "", "",
440"62 92 9d 40 26 eb \tvptestmw %zmm27,%zmm28,%k5",},
441{{0x62, 0x92, 0x26, 0x40, 0x26, 0xea, }, 6, 0, "", "",
442"62 92 26 40 26 ea \tvptestnmb %zmm26,%zmm27,%k5",},
443{{0x62, 0x92, 0xa6, 0x40, 0x26, 0xea, }, 6, 0, "", "",
444"62 92 a6 40 26 ea \tvptestnmw %zmm26,%zmm27,%k5",},
445{{0x62, 0x92, 0x1d, 0x40, 0x27, 0xeb, }, 6, 0, "", "",
446"62 92 1d 40 27 eb \tvptestmd %zmm27,%zmm28,%k5",},
447{{0x62, 0x92, 0x9d, 0x40, 0x27, 0xeb, }, 6, 0, "", "",
448"62 92 9d 40 27 eb \tvptestmq %zmm27,%zmm28,%k5",},
449{{0x62, 0x92, 0x26, 0x40, 0x27, 0xea, }, 6, 0, "", "",
450"62 92 26 40 27 ea \tvptestnmd %zmm26,%zmm27,%k5",},
451{{0x62, 0x92, 0xa6, 0x40, 0x27, 0xea, }, 6, 0, "", "",
452"62 92 a6 40 27 ea \tvptestnmq %zmm26,%zmm27,%k5",},
453{{0xc4, 0xe2, 0x4d, 0x28, 0xd4, }, 5, 0, "", "",
454"c4 e2 4d 28 d4 \tvpmuldq %ymm4,%ymm6,%ymm2",},
455{{0x62, 0x62, 0x7e, 0x48, 0x28, 0xe5, }, 6, 0, "", "",
456"62 62 7e 48 28 e5 \tvpmovm2b %k5,%zmm28",},
457{{0x62, 0x62, 0xfe, 0x48, 0x28, 0xe5, }, 6, 0, "", "",
458"62 62 fe 48 28 e5 \tvpmovm2w %k5,%zmm28",},
459{{0xc4, 0xe2, 0x4d, 0x29, 0xd4, }, 5, 0, "", "",
460"c4 e2 4d 29 d4 \tvpcmpeqq %ymm4,%ymm6,%ymm2",},
461{{0x62, 0x92, 0x7e, 0x48, 0x29, 0xec, }, 6, 0, "", "",
462"62 92 7e 48 29 ec \tvpmovb2m %zmm28,%k5",},
463{{0x62, 0x92, 0xfe, 0x48, 0x29, 0xec, }, 6, 0, "", "",
464"62 92 fe 48 29 ec \tvpmovw2m %zmm28,%k5",},
465{{0xc4, 0xe2, 0x7d, 0x2a, 0x21, }, 5, 0, "", "",
466"c4 e2 7d 2a 21 \tvmovntdqa (%rcx),%ymm4",},
467{{0x62, 0x62, 0xfe, 0x48, 0x2a, 0xf6, }, 6, 0, "", "",
468"62 62 fe 48 2a f6 \tvpbroadcastmb2q %k6,%zmm30",},
469{{0xc4, 0xe2, 0x5d, 0x2c, 0x31, }, 5, 0, "", "",
470"c4 e2 5d 2c 31 \tvmaskmovps (%rcx),%ymm4,%ymm6",},
471{{0x62, 0x02, 0x35, 0x40, 0x2c, 0xd0, }, 6, 0, "", "",
472"62 02 35 40 2c d0 \tvscalefps %zmm24,%zmm25,%zmm26",},
473{{0x62, 0x02, 0xb5, 0x40, 0x2c, 0xd0, }, 6, 0, "", "",
474"62 02 b5 40 2c d0 \tvscalefpd %zmm24,%zmm25,%zmm26",},
475{{0xc4, 0xe2, 0x5d, 0x2d, 0x31, }, 5, 0, "", "",
476"c4 e2 5d 2d 31 \tvmaskmovpd (%rcx),%ymm4,%ymm6",},
477{{0x62, 0x02, 0x35, 0x07, 0x2d, 0xd0, }, 6, 0, "", "",
478"62 02 35 07 2d d0 \tvscalefss %xmm24,%xmm25,%xmm26{%k7}",},
479{{0x62, 0x02, 0xb5, 0x07, 0x2d, 0xd0, }, 6, 0, "", "",
480"62 02 b5 07 2d d0 \tvscalefsd %xmm24,%xmm25,%xmm26{%k7}",},
481{{0xc4, 0xe2, 0x7d, 0x30, 0xe4, }, 5, 0, "", "",
482"c4 e2 7d 30 e4 \tvpmovzxbw %xmm4,%ymm4",},
483{{0x62, 0x62, 0x7e, 0x4f, 0x30, 0xde, }, 6, 0, "", "",
484"62 62 7e 4f 30 de \tvpmovwb %zmm27,%ymm6{%k7}",},
485{{0xc4, 0xe2, 0x7d, 0x31, 0xf4, }, 5, 0, "", "",
486"c4 e2 7d 31 f4 \tvpmovzxbd %xmm4,%ymm6",},
487{{0x62, 0x62, 0x7e, 0x4f, 0x31, 0xde, }, 6, 0, "", "",
488"62 62 7e 4f 31 de \tvpmovdb %zmm27,%xmm6{%k7}",},
489{{0xc4, 0xe2, 0x7d, 0x32, 0xe4, }, 5, 0, "", "",
490"c4 e2 7d 32 e4 \tvpmovzxbq %xmm4,%ymm4",},
491{{0x62, 0x62, 0x7e, 0x4f, 0x32, 0xde, }, 6, 0, "", "",
492"62 62 7e 4f 32 de \tvpmovqb %zmm27,%xmm6{%k7}",},
493{{0xc4, 0xe2, 0x7d, 0x33, 0xe4, }, 5, 0, "", "",
494"c4 e2 7d 33 e4 \tvpmovzxwd %xmm4,%ymm4",},
495{{0x62, 0x62, 0x7e, 0x4f, 0x33, 0xde, }, 6, 0, "", "",
496"62 62 7e 4f 33 de \tvpmovdw %zmm27,%ymm6{%k7}",},
497{{0xc4, 0xe2, 0x7d, 0x34, 0xf4, }, 5, 0, "", "",
498"c4 e2 7d 34 f4 \tvpmovzxwq %xmm4,%ymm6",},
499{{0x62, 0x62, 0x7e, 0x4f, 0x34, 0xde, }, 6, 0, "", "",
500"62 62 7e 4f 34 de \tvpmovqw %zmm27,%xmm6{%k7}",},
501{{0xc4, 0xe2, 0x7d, 0x35, 0xe4, }, 5, 0, "", "",
502"c4 e2 7d 35 e4 \tvpmovzxdq %xmm4,%ymm4",},
503{{0x62, 0x62, 0x7e, 0x4f, 0x35, 0xde, }, 6, 0, "", "",
504"62 62 7e 4f 35 de \tvpmovqd %zmm27,%ymm6{%k7}",},
505{{0xc4, 0xe2, 0x4d, 0x36, 0xd4, }, 5, 0, "", "",
506"c4 e2 4d 36 d4 \tvpermd %ymm4,%ymm6,%ymm2",},
507{{0x62, 0x82, 0x2d, 0x27, 0x36, 0xf0, }, 6, 0, "", "",
508"62 82 2d 27 36 f0 \tvpermd %ymm24,%ymm26,%ymm22{%k7}",},
509{{0x62, 0x82, 0xad, 0x27, 0x36, 0xf0, }, 6, 0, "", "",
510"62 82 ad 27 36 f0 \tvpermq %ymm24,%ymm26,%ymm22{%k7}",},
511{{0xc4, 0xe2, 0x4d, 0x38, 0xd4, }, 5, 0, "", "",
512"c4 e2 4d 38 d4 \tvpminsb %ymm4,%ymm6,%ymm2",},
513{{0x62, 0x62, 0x7e, 0x48, 0x38, 0xe5, }, 6, 0, "", "",
514"62 62 7e 48 38 e5 \tvpmovm2d %k5,%zmm28",},
515{{0x62, 0x62, 0xfe, 0x48, 0x38, 0xe5, }, 6, 0, "", "",
516"62 62 fe 48 38 e5 \tvpmovm2q %k5,%zmm28",},
517{{0xc4, 0xe2, 0x69, 0x39, 0xd9, }, 5, 0, "", "",
518"c4 e2 69 39 d9 \tvpminsd %xmm1,%xmm2,%xmm3",},
519{{0x62, 0x02, 0x35, 0x40, 0x39, 0xd0, }, 6, 0, "", "",
520"62 02 35 40 39 d0 \tvpminsd %zmm24,%zmm25,%zmm26",},
521{{0x62, 0x02, 0xb5, 0x40, 0x39, 0xd0, }, 6, 0, "", "",
522"62 02 b5 40 39 d0 \tvpminsq %zmm24,%zmm25,%zmm26",},
523{{0x62, 0x92, 0x7e, 0x48, 0x39, 0xec, }, 6, 0, "", "",
524"62 92 7e 48 39 ec \tvpmovd2m %zmm28,%k5",},
525{{0x62, 0x92, 0xfe, 0x48, 0x39, 0xec, }, 6, 0, "", "",
526"62 92 fe 48 39 ec \tvpmovq2m %zmm28,%k5",},
527{{0xc4, 0xe2, 0x4d, 0x3a, 0xd4, }, 5, 0, "", "",
528"c4 e2 4d 3a d4 \tvpminuw %ymm4,%ymm6,%ymm2",},
529{{0x62, 0x62, 0x7e, 0x48, 0x3a, 0xe6, }, 6, 0, "", "",
530"62 62 7e 48 3a e6 \tvpbroadcastmw2d %k6,%zmm28",},
531{{0xc4, 0xe2, 0x4d, 0x3b, 0xd4, }, 5, 0, "", "",
532"c4 e2 4d 3b d4 \tvpminud %ymm4,%ymm6,%ymm2",},
533{{0x62, 0x02, 0x35, 0x40, 0x3b, 0xd0, }, 6, 0, "", "",
534"62 02 35 40 3b d0 \tvpminud %zmm24,%zmm25,%zmm26",},
535{{0x62, 0x02, 0xb5, 0x40, 0x3b, 0xd0, }, 6, 0, "", "",
536"62 02 b5 40 3b d0 \tvpminuq %zmm24,%zmm25,%zmm26",},
537{{0xc4, 0xe2, 0x4d, 0x3d, 0xd4, }, 5, 0, "", "",
538"c4 e2 4d 3d d4 \tvpmaxsd %ymm4,%ymm6,%ymm2",},
539{{0x62, 0x02, 0x35, 0x40, 0x3d, 0xd0, }, 6, 0, "", "",
540"62 02 35 40 3d d0 \tvpmaxsd %zmm24,%zmm25,%zmm26",},
541{{0x62, 0x02, 0xb5, 0x40, 0x3d, 0xd0, }, 6, 0, "", "",
542"62 02 b5 40 3d d0 \tvpmaxsq %zmm24,%zmm25,%zmm26",},
543{{0xc4, 0xe2, 0x4d, 0x3f, 0xd4, }, 5, 0, "", "",
544"c4 e2 4d 3f d4 \tvpmaxud %ymm4,%ymm6,%ymm2",},
545{{0x62, 0x02, 0x35, 0x40, 0x3f, 0xd0, }, 6, 0, "", "",
546"62 02 35 40 3f d0 \tvpmaxud %zmm24,%zmm25,%zmm26",},
547{{0x62, 0x02, 0xb5, 0x40, 0x3f, 0xd0, }, 6, 0, "", "",
548"62 02 b5 40 3f d0 \tvpmaxuq %zmm24,%zmm25,%zmm26",},
549{{0xc4, 0xe2, 0x4d, 0x40, 0xd4, }, 5, 0, "", "",
550"c4 e2 4d 40 d4 \tvpmulld %ymm4,%ymm6,%ymm2",},
551{{0x62, 0x02, 0x35, 0x40, 0x40, 0xd0, }, 6, 0, "", "",
552"62 02 35 40 40 d0 \tvpmulld %zmm24,%zmm25,%zmm26",},
553{{0x62, 0x02, 0xb5, 0x40, 0x40, 0xd0, }, 6, 0, "", "",
554"62 02 b5 40 40 d0 \tvpmullq %zmm24,%zmm25,%zmm26",},
555{{0x62, 0x02, 0x7d, 0x48, 0x42, 0xd1, }, 6, 0, "", "",
556"62 02 7d 48 42 d1 \tvgetexpps %zmm25,%zmm26",},
557{{0x62, 0x02, 0xfd, 0x48, 0x42, 0xe3, }, 6, 0, "", "",
558"62 02 fd 48 42 e3 \tvgetexppd %zmm27,%zmm28",},
559{{0x62, 0x02, 0x35, 0x07, 0x43, 0xd0, }, 6, 0, "", "",
560"62 02 35 07 43 d0 \tvgetexpss %xmm24,%xmm25,%xmm26{%k7}",},
561{{0x62, 0x02, 0x95, 0x07, 0x43, 0xf4, }, 6, 0, "", "",
562"62 02 95 07 43 f4 \tvgetexpsd %xmm28,%xmm29,%xmm30{%k7}",},
563{{0x62, 0x02, 0x7d, 0x48, 0x44, 0xe3, }, 6, 0, "", "",
564"62 02 7d 48 44 e3 \tvplzcntd %zmm27,%zmm28",},
565{{0x62, 0x02, 0xfd, 0x48, 0x44, 0xe3, }, 6, 0, "", "",
566"62 02 fd 48 44 e3 \tvplzcntq %zmm27,%zmm28",},
567{{0xc4, 0xe2, 0x4d, 0x46, 0xd4, }, 5, 0, "", "",
568"c4 e2 4d 46 d4 \tvpsravd %ymm4,%ymm6,%ymm2",},
569{{0x62, 0x02, 0x35, 0x40, 0x46, 0xd0, }, 6, 0, "", "",
570"62 02 35 40 46 d0 \tvpsravd %zmm24,%zmm25,%zmm26",},
571{{0x62, 0x02, 0xb5, 0x40, 0x46, 0xd0, }, 6, 0, "", "",
572"62 02 b5 40 46 d0 \tvpsravq %zmm24,%zmm25,%zmm26",},
573{{0x62, 0x02, 0x7d, 0x48, 0x4c, 0xd1, }, 6, 0, "", "",
574"62 02 7d 48 4c d1 \tvrcp14ps %zmm25,%zmm26",},
575{{0x62, 0x02, 0xfd, 0x48, 0x4c, 0xe3, }, 6, 0, "", "",
576"62 02 fd 48 4c e3 \tvrcp14pd %zmm27,%zmm28",},
577{{0x62, 0x02, 0x35, 0x07, 0x4d, 0xd0, }, 6, 0, "", "",
578"62 02 35 07 4d d0 \tvrcp14ss %xmm24,%xmm25,%xmm26{%k7}",},
579{{0x62, 0x02, 0xb5, 0x07, 0x4d, 0xd0, }, 6, 0, "", "",
580"62 02 b5 07 4d d0 \tvrcp14sd %xmm24,%xmm25,%xmm26{%k7}",},
581{{0x62, 0x02, 0x7d, 0x48, 0x4e, 0xd1, }, 6, 0, "", "",
582"62 02 7d 48 4e d1 \tvrsqrt14ps %zmm25,%zmm26",},
583{{0x62, 0x02, 0xfd, 0x48, 0x4e, 0xe3, }, 6, 0, "", "",
584"62 02 fd 48 4e e3 \tvrsqrt14pd %zmm27,%zmm28",},
585{{0x62, 0x02, 0x35, 0x07, 0x4f, 0xd0, }, 6, 0, "", "",
586"62 02 35 07 4f d0 \tvrsqrt14ss %xmm24,%xmm25,%xmm26{%k7}",},
587{{0x62, 0x02, 0xb5, 0x07, 0x4f, 0xd0, }, 6, 0, "", "",
588"62 02 b5 07 4f d0 \tvrsqrt14sd %xmm24,%xmm25,%xmm26{%k7}",},
589{{0xc4, 0xe2, 0x79, 0x59, 0xf4, }, 5, 0, "", "",
590"c4 e2 79 59 f4 \tvpbroadcastq %xmm4,%xmm6",},
591{{0x62, 0x02, 0x7d, 0x48, 0x59, 0xd3, }, 6, 0, "", "",
592"62 02 7d 48 59 d3 \tvbroadcasti32x2 %xmm27,%zmm26",},
593{{0xc4, 0xe2, 0x7d, 0x5a, 0x21, }, 5, 0, "", "",
594"c4 e2 7d 5a 21 \tvbroadcasti128 (%rcx),%ymm4",},
595{{0x62, 0x62, 0x7d, 0x48, 0x5a, 0x11, }, 6, 0, "", "",
596"62 62 7d 48 5a 11 \tvbroadcasti32x4 (%rcx),%zmm26",},
597{{0x62, 0x62, 0xfd, 0x48, 0x5a, 0x11, }, 6, 0, "", "",
598"62 62 fd 48 5a 11 \tvbroadcasti64x2 (%rcx),%zmm26",},
599{{0x62, 0x62, 0x7d, 0x48, 0x5b, 0x21, }, 6, 0, "", "",
600"62 62 7d 48 5b 21 \tvbroadcasti32x8 (%rcx),%zmm28",},
601{{0x62, 0x62, 0xfd, 0x48, 0x5b, 0x11, }, 6, 0, "", "",
602"62 62 fd 48 5b 11 \tvbroadcasti64x4 (%rcx),%zmm26",},
603{{0x62, 0x02, 0x25, 0x40, 0x64, 0xe2, }, 6, 0, "", "",
604"62 02 25 40 64 e2 \tvpblendmd %zmm26,%zmm27,%zmm28",},
605{{0x62, 0x02, 0xa5, 0x40, 0x64, 0xe2, }, 6, 0, "", "",
606"62 02 a5 40 64 e2 \tvpblendmq %zmm26,%zmm27,%zmm28",},
607{{0x62, 0x02, 0x35, 0x40, 0x65, 0xd0, }, 6, 0, "", "",
608"62 02 35 40 65 d0 \tvblendmps %zmm24,%zmm25,%zmm26",},
609{{0x62, 0x02, 0xa5, 0x40, 0x65, 0xe2, }, 6, 0, "", "",
610"62 02 a5 40 65 e2 \tvblendmpd %zmm26,%zmm27,%zmm28",},
611{{0x62, 0x02, 0x25, 0x40, 0x66, 0xe2, }, 6, 0, "", "",
612"62 02 25 40 66 e2 \tvpblendmb %zmm26,%zmm27,%zmm28",},
613{{0x62, 0x02, 0xa5, 0x40, 0x66, 0xe2, }, 6, 0, "", "",
614"62 02 a5 40 66 e2 \tvpblendmw %zmm26,%zmm27,%zmm28",},
615{{0x62, 0x02, 0x35, 0x40, 0x75, 0xd0, }, 6, 0, "", "",
616"62 02 35 40 75 d0 \tvpermi2b %zmm24,%zmm25,%zmm26",},
617{{0x62, 0x02, 0xa5, 0x40, 0x75, 0xe2, }, 6, 0, "", "",
618"62 02 a5 40 75 e2 \tvpermi2w %zmm26,%zmm27,%zmm28",},
619{{0x62, 0x02, 0x25, 0x40, 0x76, 0xe2, }, 6, 0, "", "",
620"62 02 25 40 76 e2 \tvpermi2d %zmm26,%zmm27,%zmm28",},
621{{0x62, 0x02, 0xa5, 0x40, 0x76, 0xe2, }, 6, 0, "", "",
622"62 02 a5 40 76 e2 \tvpermi2q %zmm26,%zmm27,%zmm28",},
623{{0x62, 0x02, 0x25, 0x40, 0x77, 0xe2, }, 6, 0, "", "",
624"62 02 25 40 77 e2 \tvpermi2ps %zmm26,%zmm27,%zmm28",},
625{{0x62, 0x02, 0xa5, 0x40, 0x77, 0xe2, }, 6, 0, "", "",
626"62 02 a5 40 77 e2 \tvpermi2pd %zmm26,%zmm27,%zmm28",},
627{{0x62, 0x62, 0x7d, 0x08, 0x7a, 0xf0, }, 6, 0, "", "",
628"62 62 7d 08 7a f0 \tvpbroadcastb %eax,%xmm30",},
629{{0x62, 0x62, 0x7d, 0x08, 0x7b, 0xf0, }, 6, 0, "", "",
630"62 62 7d 08 7b f0 \tvpbroadcastw %eax,%xmm30",},
631{{0x62, 0x62, 0x7d, 0x08, 0x7c, 0xf0, }, 6, 0, "", "",
632"62 62 7d 08 7c f0 \tvpbroadcastd %eax,%xmm30",},
633{{0x62, 0x62, 0xfd, 0x48, 0x7c, 0xf0, }, 6, 0, "", "",
634"62 62 fd 48 7c f0 \tvpbroadcastq %rax,%zmm30",},
635{{0x62, 0x02, 0x25, 0x40, 0x7d, 0xe2, }, 6, 0, "", "",
636"62 02 25 40 7d e2 \tvpermt2b %zmm26,%zmm27,%zmm28",},
637{{0x62, 0x02, 0xa5, 0x40, 0x7d, 0xe2, }, 6, 0, "", "",
638"62 02 a5 40 7d e2 \tvpermt2w %zmm26,%zmm27,%zmm28",},
639{{0x62, 0x02, 0x25, 0x40, 0x7e, 0xe2, }, 6, 0, "", "",
640"62 02 25 40 7e e2 \tvpermt2d %zmm26,%zmm27,%zmm28",},
641{{0x62, 0x02, 0xa5, 0x40, 0x7e, 0xe2, }, 6, 0, "", "",
642"62 02 a5 40 7e e2 \tvpermt2q %zmm26,%zmm27,%zmm28",},
643{{0x62, 0x02, 0x25, 0x40, 0x7f, 0xe2, }, 6, 0, "", "",
644"62 02 25 40 7f e2 \tvpermt2ps %zmm26,%zmm27,%zmm28",},
645{{0x62, 0x02, 0xa5, 0x40, 0x7f, 0xe2, }, 6, 0, "", "",
646"62 02 a5 40 7f e2 \tvpermt2pd %zmm26,%zmm27,%zmm28",},
647{{0x62, 0x02, 0xa5, 0x40, 0x83, 0xe2, }, 6, 0, "", "",
648"62 02 a5 40 83 e2 \tvpmultishiftqb %zmm26,%zmm27,%zmm28",},
649{{0x62, 0x62, 0x7d, 0x48, 0x88, 0x11, }, 6, 0, "", "",
650"62 62 7d 48 88 11 \tvexpandps (%rcx),%zmm26",},
651{{0x62, 0x62, 0xfd, 0x48, 0x88, 0x21, }, 6, 0, "", "",
652"62 62 fd 48 88 21 \tvexpandpd (%rcx),%zmm28",},
653{{0x62, 0x62, 0x7d, 0x48, 0x89, 0x21, }, 6, 0, "", "",
654"62 62 7d 48 89 21 \tvpexpandd (%rcx),%zmm28",},
655{{0x62, 0x62, 0xfd, 0x48, 0x89, 0x11, }, 6, 0, "", "",
656"62 62 fd 48 89 11 \tvpexpandq (%rcx),%zmm26",},
657{{0x62, 0x62, 0x7d, 0x48, 0x8a, 0x21, }, 6, 0, "", "",
658"62 62 7d 48 8a 21 \tvcompressps %zmm28,(%rcx)",},
659{{0x62, 0x62, 0xfd, 0x48, 0x8a, 0x21, }, 6, 0, "", "",
660"62 62 fd 48 8a 21 \tvcompresspd %zmm28,(%rcx)",},
661{{0x62, 0x62, 0x7d, 0x48, 0x8b, 0x21, }, 6, 0, "", "",
662"62 62 7d 48 8b 21 \tvpcompressd %zmm28,(%rcx)",},
663{{0x62, 0x62, 0xfd, 0x48, 0x8b, 0x11, }, 6, 0, "", "",
664"62 62 fd 48 8b 11 \tvpcompressq %zmm26,(%rcx)",},
665{{0x62, 0x02, 0x25, 0x40, 0x8d, 0xe2, }, 6, 0, "", "",
666"62 02 25 40 8d e2 \tvpermb %zmm26,%zmm27,%zmm28",},
667{{0x62, 0x02, 0xa5, 0x40, 0x8d, 0xe2, }, 6, 0, "", "",
668"62 02 a5 40 8d e2 \tvpermw %zmm26,%zmm27,%zmm28",},
669{{0xc4, 0xe2, 0x69, 0x90, 0x4c, 0x7d, 0x02, }, 7, 0, "", "",
670"c4 e2 69 90 4c 7d 02 \tvpgatherdd %xmm2,0x2(%rbp,%xmm7,2),%xmm1",},
671{{0xc4, 0xe2, 0xe9, 0x90, 0x4c, 0x7d, 0x04, }, 7, 0, "", "",
672"c4 e2 e9 90 4c 7d 04 \tvpgatherdq %xmm2,0x4(%rbp,%xmm7,2),%xmm1",},
673{{0x62, 0x22, 0x7d, 0x41, 0x90, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
674"62 22 7d 41 90 94 dd 7b 00 00 00 \tvpgatherdd 0x7b(%rbp,%zmm27,8),%zmm26{%k1}",},
675{{0x62, 0x22, 0xfd, 0x41, 0x90, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
676"62 22 fd 41 90 94 dd 7b 00 00 00 \tvpgatherdq 0x7b(%rbp,%ymm27,8),%zmm26{%k1}",},
677{{0xc4, 0xe2, 0x69, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "",
678"c4 e2 69 91 4c 7d 02 \tvpgatherqd %xmm2,0x2(%rbp,%xmm7,2),%xmm1",},
679{{0xc4, 0xe2, 0xe9, 0x91, 0x4c, 0x7d, 0x02, }, 7, 0, "", "",
680"c4 e2 e9 91 4c 7d 02 \tvpgatherqq %xmm2,0x2(%rbp,%xmm7,2),%xmm1",},
681{{0x62, 0x22, 0x7d, 0x41, 0x91, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
682"62 22 7d 41 91 94 dd 7b 00 00 00 \tvpgatherqd 0x7b(%rbp,%zmm27,8),%ymm26{%k1}",},
683{{0x62, 0x22, 0xfd, 0x41, 0x91, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
684"62 22 fd 41 91 94 dd 7b 00 00 00 \tvpgatherqq 0x7b(%rbp,%zmm27,8),%zmm26{%k1}",},
685{{0x62, 0x22, 0x7d, 0x41, 0xa0, 0xa4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
686"62 22 7d 41 a0 a4 ed 7b 00 00 00 \tvpscatterdd %zmm28,0x7b(%rbp,%zmm29,8){%k1}",},
687{{0x62, 0x22, 0xfd, 0x41, 0xa0, 0x94, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
688"62 22 fd 41 a0 94 dd 7b 00 00 00 \tvpscatterdq %zmm26,0x7b(%rbp,%ymm27,8){%k1}",},
689{{0x62, 0xb2, 0x7d, 0x41, 0xa1, 0xb4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
690"62 b2 7d 41 a1 b4 ed 7b 00 00 00 \tvpscatterqd %ymm6,0x7b(%rbp,%zmm29,8){%k1}",},
691{{0x62, 0xb2, 0xfd, 0x21, 0xa1, 0xb4, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
692"62 b2 fd 21 a1 b4 dd 7b 00 00 00 \tvpscatterqq %ymm6,0x7b(%rbp,%ymm27,8){%k1}",},
693{{0x62, 0x22, 0x7d, 0x41, 0xa2, 0xa4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
694"62 22 7d 41 a2 a4 ed 7b 00 00 00 \tvscatterdps %zmm28,0x7b(%rbp,%zmm29,8){%k1}",},
695{{0x62, 0x22, 0xfd, 0x41, 0xa2, 0xa4, 0xdd, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
696"62 22 fd 41 a2 a4 dd 7b 00 00 00 \tvscatterdpd %zmm28,0x7b(%rbp,%ymm27,8){%k1}",},
697{{0x62, 0xb2, 0x7d, 0x41, 0xa3, 0xb4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
698"62 b2 7d 41 a3 b4 ed 7b 00 00 00 \tvscatterqps %ymm6,0x7b(%rbp,%zmm29,8){%k1}",},
699{{0x62, 0x22, 0xfd, 0x41, 0xa3, 0xa4, 0xed, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
700"62 22 fd 41 a3 a4 ed 7b 00 00 00 \tvscatterqpd %zmm28,0x7b(%rbp,%zmm29,8){%k1}",},
701{{0x62, 0x02, 0xa5, 0x40, 0xb4, 0xe2, }, 6, 0, "", "",
702"62 02 a5 40 b4 e2 \tvpmadd52luq %zmm26,%zmm27,%zmm28",},
703{{0x62, 0x02, 0xa5, 0x40, 0xb5, 0xe2, }, 6, 0, "", "",
704"62 02 a5 40 b5 e2 \tvpmadd52huq %zmm26,%zmm27,%zmm28",},
705{{0x62, 0x02, 0x7d, 0x48, 0xc4, 0xda, }, 6, 0, "", "",
706"62 02 7d 48 c4 da \tvpconflictd %zmm26,%zmm27",},
707{{0x62, 0x02, 0xfd, 0x48, 0xc4, 0xda, }, 6, 0, "", "",
708"62 02 fd 48 c4 da \tvpconflictq %zmm26,%zmm27",},
709{{0x62, 0x02, 0x7d, 0x48, 0xc8, 0xf5, }, 6, 0, "", "",
710"62 02 7d 48 c8 f5 \tvexp2ps %zmm29,%zmm30",},
711{{0x62, 0x02, 0xfd, 0x48, 0xc8, 0xda, }, 6, 0, "", "",
712"62 02 fd 48 c8 da \tvexp2pd %zmm26,%zmm27",},
713{{0x62, 0x02, 0x7d, 0x48, 0xca, 0xf5, }, 6, 0, "", "",
714"62 02 7d 48 ca f5 \tvrcp28ps %zmm29,%zmm30",},
715{{0x62, 0x02, 0xfd, 0x48, 0xca, 0xda, }, 6, 0, "", "",
716"62 02 fd 48 ca da \tvrcp28pd %zmm26,%zmm27",},
717{{0x62, 0x02, 0x15, 0x07, 0xcb, 0xf4, }, 6, 0, "", "",
718"62 02 15 07 cb f4 \tvrcp28ss %xmm28,%xmm29,%xmm30{%k7}",},
719{{0x62, 0x02, 0xad, 0x07, 0xcb, 0xd9, }, 6, 0, "", "",
720"62 02 ad 07 cb d9 \tvrcp28sd %xmm25,%xmm26,%xmm27{%k7}",},
721{{0x62, 0x02, 0x7d, 0x48, 0xcc, 0xf5, }, 6, 0, "", "",
722"62 02 7d 48 cc f5 \tvrsqrt28ps %zmm29,%zmm30",},
723{{0x62, 0x02, 0xfd, 0x48, 0xcc, 0xda, }, 6, 0, "", "",
724"62 02 fd 48 cc da \tvrsqrt28pd %zmm26,%zmm27",},
725{{0x62, 0x02, 0x15, 0x07, 0xcd, 0xf4, }, 6, 0, "", "",
726"62 02 15 07 cd f4 \tvrsqrt28ss %xmm28,%xmm29,%xmm30{%k7}",},
727{{0x62, 0x02, 0xad, 0x07, 0xcd, 0xd9, }, 6, 0, "", "",
728"62 02 ad 07 cd d9 \tvrsqrt28sd %xmm25,%xmm26,%xmm27{%k7}",},
729{{0x62, 0x03, 0x15, 0x40, 0x03, 0xf4, 0x12, }, 7, 0, "", "",
730"62 03 15 40 03 f4 12 \tvalignd $0x12,%zmm28,%zmm29,%zmm30",},
731{{0x62, 0x03, 0xad, 0x40, 0x03, 0xd9, 0x12, }, 7, 0, "", "",
732"62 03 ad 40 03 d9 12 \tvalignq $0x12,%zmm25,%zmm26,%zmm27",},
733{{0xc4, 0xe3, 0x7d, 0x08, 0xd6, 0x05, }, 6, 0, "", "",
734"c4 e3 7d 08 d6 05 \tvroundps $0x5,%ymm6,%ymm2",},
735{{0x62, 0x03, 0x7d, 0x48, 0x08, 0xd1, 0x12, }, 7, 0, "", "",
736"62 03 7d 48 08 d1 12 \tvrndscaleps $0x12,%zmm25,%zmm26",},
737{{0xc4, 0xe3, 0x7d, 0x09, 0xd6, 0x05, }, 6, 0, "", "",
738"c4 e3 7d 09 d6 05 \tvroundpd $0x5,%ymm6,%ymm2",},
739{{0x62, 0x03, 0xfd, 0x48, 0x09, 0xd1, 0x12, }, 7, 0, "", "",
740"62 03 fd 48 09 d1 12 \tvrndscalepd $0x12,%zmm25,%zmm26",},
741{{0xc4, 0xe3, 0x49, 0x0a, 0xd4, 0x05, }, 6, 0, "", "",
742"c4 e3 49 0a d4 05 \tvroundss $0x5,%xmm4,%xmm6,%xmm2",},
743{{0x62, 0x03, 0x35, 0x07, 0x0a, 0xd0, 0x12, }, 7, 0, "", "",
744"62 03 35 07 0a d0 12 \tvrndscaless $0x12,%xmm24,%xmm25,%xmm26{%k7}",},
745{{0xc4, 0xe3, 0x49, 0x0b, 0xd4, 0x05, }, 6, 0, "", "",
746"c4 e3 49 0b d4 05 \tvroundsd $0x5,%xmm4,%xmm6,%xmm2",},
747{{0x62, 0x03, 0xb5, 0x07, 0x0b, 0xd0, 0x12, }, 7, 0, "", "",
748"62 03 b5 07 0b d0 12 \tvrndscalesd $0x12,%xmm24,%xmm25,%xmm26{%k7}",},
749{{0xc4, 0xe3, 0x5d, 0x18, 0xf4, 0x05, }, 6, 0, "", "",
750"c4 e3 5d 18 f4 05 \tvinsertf128 $0x5,%xmm4,%ymm4,%ymm6",},
751{{0x62, 0x03, 0x35, 0x47, 0x18, 0xd0, 0x12, }, 7, 0, "", "",
752"62 03 35 47 18 d0 12 \tvinsertf32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}",},
753{{0x62, 0x03, 0xb5, 0x47, 0x18, 0xd0, 0x12, }, 7, 0, "", "",
754"62 03 b5 47 18 d0 12 \tvinsertf64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}",},
755{{0xc4, 0xe3, 0x7d, 0x19, 0xe4, 0x05, }, 6, 0, "", "",
756"c4 e3 7d 19 e4 05 \tvextractf128 $0x5,%ymm4,%xmm4",},
757{{0x62, 0x03, 0x7d, 0x4f, 0x19, 0xca, 0x12, }, 7, 0, "", "",
758"62 03 7d 4f 19 ca 12 \tvextractf32x4 $0x12,%zmm25,%xmm26{%k7}",},
759{{0x62, 0x03, 0xfd, 0x4f, 0x19, 0xca, 0x12, }, 7, 0, "", "",
760"62 03 fd 4f 19 ca 12 \tvextractf64x2 $0x12,%zmm25,%xmm26{%k7}",},
761{{0x62, 0x03, 0x2d, 0x47, 0x1a, 0xd9, 0x12, }, 7, 0, "", "",
762"62 03 2d 47 1a d9 12 \tvinsertf32x8 $0x12,%ymm25,%zmm26,%zmm27{%k7}",},
763{{0x62, 0x03, 0x95, 0x47, 0x1a, 0xf4, 0x12, }, 7, 0, "", "",
764"62 03 95 47 1a f4 12 \tvinsertf64x4 $0x12,%ymm28,%zmm29,%zmm30{%k7}",},
765{{0x62, 0x03, 0x7d, 0x4f, 0x1b, 0xee, 0x12, }, 7, 0, "", "",
766"62 03 7d 4f 1b ee 12 \tvextractf32x8 $0x12,%zmm29,%ymm30{%k7}",},
767{{0x62, 0x03, 0xfd, 0x4f, 0x1b, 0xd3, 0x12, }, 7, 0, "", "",
768"62 03 fd 4f 1b d3 12 \tvextractf64x4 $0x12,%zmm26,%ymm27{%k7}",},
769{{0x62, 0x93, 0x0d, 0x40, 0x1e, 0xed, 0x12, }, 7, 0, "", "",
770"62 93 0d 40 1e ed 12 \tvpcmpud $0x12,%zmm29,%zmm30,%k5",},
771{{0x62, 0x93, 0xa5, 0x40, 0x1e, 0xea, 0x12, }, 7, 0, "", "",
772"62 93 a5 40 1e ea 12 \tvpcmpuq $0x12,%zmm26,%zmm27,%k5",},
773{{0x62, 0x93, 0x0d, 0x40, 0x1f, 0xed, 0x12, }, 7, 0, "", "",
774"62 93 0d 40 1f ed 12 \tvpcmpd $0x12,%zmm29,%zmm30,%k5",},
775{{0x62, 0x93, 0xa5, 0x40, 0x1f, 0xea, 0x12, }, 7, 0, "", "",
776"62 93 a5 40 1f ea 12 \tvpcmpq $0x12,%zmm26,%zmm27,%k5",},
777{{0x62, 0x03, 0x15, 0x40, 0x23, 0xf4, 0x12, }, 7, 0, "", "",
778"62 03 15 40 23 f4 12 \tvshuff32x4 $0x12,%zmm28,%zmm29,%zmm30",},
779{{0x62, 0x03, 0xad, 0x40, 0x23, 0xd9, 0x12, }, 7, 0, "", "",
780"62 03 ad 40 23 d9 12 \tvshuff64x2 $0x12,%zmm25,%zmm26,%zmm27",},
781{{0x62, 0x03, 0x15, 0x40, 0x25, 0xf4, 0x12, }, 7, 0, "", "",
782"62 03 15 40 25 f4 12 \tvpternlogd $0x12,%zmm28,%zmm29,%zmm30",},
783{{0x62, 0x03, 0x95, 0x40, 0x25, 0xf4, 0x12, }, 7, 0, "", "",
784"62 03 95 40 25 f4 12 \tvpternlogq $0x12,%zmm28,%zmm29,%zmm30",},
785{{0x62, 0x03, 0x7d, 0x48, 0x26, 0xda, 0x12, }, 7, 0, "", "",
786"62 03 7d 48 26 da 12 \tvgetmantps $0x12,%zmm26,%zmm27",},
787{{0x62, 0x03, 0xfd, 0x48, 0x26, 0xf5, 0x12, }, 7, 0, "", "",
788"62 03 fd 48 26 f5 12 \tvgetmantpd $0x12,%zmm29,%zmm30",},
789{{0x62, 0x03, 0x2d, 0x07, 0x27, 0xd9, 0x12, }, 7, 0, "", "",
790"62 03 2d 07 27 d9 12 \tvgetmantss $0x12,%xmm25,%xmm26,%xmm27{%k7}",},
791{{0x62, 0x03, 0x95, 0x07, 0x27, 0xf4, 0x12, }, 7, 0, "", "",
792"62 03 95 07 27 f4 12 \tvgetmantsd $0x12,%xmm28,%xmm29,%xmm30{%k7}",},
793{{0xc4, 0xe3, 0x5d, 0x38, 0xf4, 0x05, }, 6, 0, "", "",
794"c4 e3 5d 38 f4 05 \tvinserti128 $0x5,%xmm4,%ymm4,%ymm6",},
795{{0x62, 0x03, 0x35, 0x47, 0x38, 0xd0, 0x12, }, 7, 0, "", "",
796"62 03 35 47 38 d0 12 \tvinserti32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}",},
797{{0x62, 0x03, 0xb5, 0x47, 0x38, 0xd0, 0x12, }, 7, 0, "", "",
798"62 03 b5 47 38 d0 12 \tvinserti64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}",},
799{{0xc4, 0xe3, 0x7d, 0x39, 0xe6, 0x05, }, 6, 0, "", "",
800"c4 e3 7d 39 e6 05 \tvextracti128 $0x5,%ymm4,%xmm6",},
801{{0x62, 0x03, 0x7d, 0x4f, 0x39, 0xca, 0x12, }, 7, 0, "", "",
802"62 03 7d 4f 39 ca 12 \tvextracti32x4 $0x12,%zmm25,%xmm26{%k7}",},
803{{0x62, 0x03, 0xfd, 0x4f, 0x39, 0xca, 0x12, }, 7, 0, "", "",
804"62 03 fd 4f 39 ca 12 \tvextracti64x2 $0x12,%zmm25,%xmm26{%k7}",},
805{{0x62, 0x03, 0x15, 0x47, 0x3a, 0xf4, 0x12, }, 7, 0, "", "",
806"62 03 15 47 3a f4 12 \tvinserti32x8 $0x12,%ymm28,%zmm29,%zmm30{%k7}",},
807{{0x62, 0x03, 0xad, 0x47, 0x3a, 0xd9, 0x12, }, 7, 0, "", "",
808"62 03 ad 47 3a d9 12 \tvinserti64x4 $0x12,%ymm25,%zmm26,%zmm27{%k7}",},
809{{0x62, 0x03, 0x7d, 0x4f, 0x3b, 0xee, 0x12, }, 7, 0, "", "",
810"62 03 7d 4f 3b ee 12 \tvextracti32x8 $0x12,%zmm29,%ymm30{%k7}",},
811{{0x62, 0x03, 0xfd, 0x4f, 0x3b, 0xd3, 0x12, }, 7, 0, "", "",
812"62 03 fd 4f 3b d3 12 \tvextracti64x4 $0x12,%zmm26,%ymm27{%k7}",},
813{{0x62, 0x93, 0x0d, 0x40, 0x3e, 0xed, 0x12, }, 7, 0, "", "",
814"62 93 0d 40 3e ed 12 \tvpcmpub $0x12,%zmm29,%zmm30,%k5",},
815{{0x62, 0x93, 0xa5, 0x40, 0x3e, 0xea, 0x12, }, 7, 0, "", "",
816"62 93 a5 40 3e ea 12 \tvpcmpuw $0x12,%zmm26,%zmm27,%k5",},
817{{0x62, 0x93, 0x0d, 0x40, 0x3f, 0xed, 0x12, }, 7, 0, "", "",
818"62 93 0d 40 3f ed 12 \tvpcmpb $0x12,%zmm29,%zmm30,%k5",},
819{{0x62, 0x93, 0xa5, 0x40, 0x3f, 0xea, 0x12, }, 7, 0, "", "",
820"62 93 a5 40 3f ea 12 \tvpcmpw $0x12,%zmm26,%zmm27,%k5",},
821{{0xc4, 0xe3, 0x4d, 0x42, 0xd4, 0x05, }, 6, 0, "", "",
822"c4 e3 4d 42 d4 05 \tvmpsadbw $0x5,%ymm4,%ymm6,%ymm2",},
823{{0x62, 0xf3, 0x55, 0x48, 0x42, 0xf4, 0x12, }, 7, 0, "", "",
824"62 f3 55 48 42 f4 12 \tvdbpsadbw $0x12,%zmm4,%zmm5,%zmm6",},
825{{0x62, 0x03, 0x2d, 0x40, 0x43, 0xd9, 0x12, }, 7, 0, "", "",
826"62 03 2d 40 43 d9 12 \tvshufi32x4 $0x12,%zmm25,%zmm26,%zmm27",},
827{{0x62, 0x03, 0x95, 0x40, 0x43, 0xf4, 0x12, }, 7, 0, "", "",
828"62 03 95 40 43 f4 12 \tvshufi64x2 $0x12,%zmm28,%zmm29,%zmm30",},
829{{0x62, 0x03, 0x2d, 0x40, 0x50, 0xd9, 0x12, }, 7, 0, "", "",
830"62 03 2d 40 50 d9 12 \tvrangeps $0x12,%zmm25,%zmm26,%zmm27",},
831{{0x62, 0x03, 0x95, 0x40, 0x50, 0xf4, 0x12, }, 7, 0, "", "",
832"62 03 95 40 50 f4 12 \tvrangepd $0x12,%zmm28,%zmm29,%zmm30",},
833{{0x62, 0x03, 0x2d, 0x00, 0x51, 0xd9, 0x12, }, 7, 0, "", "",
834"62 03 2d 00 51 d9 12 \tvrangess $0x12,%xmm25,%xmm26,%xmm27",},
835{{0x62, 0x03, 0x95, 0x00, 0x51, 0xf4, 0x12, }, 7, 0, "", "",
836"62 03 95 00 51 f4 12 \tvrangesd $0x12,%xmm28,%xmm29,%xmm30",},
837{{0x62, 0x03, 0x15, 0x40, 0x54, 0xf4, 0x12, }, 7, 0, "", "",
838"62 03 15 40 54 f4 12 \tvfixupimmps $0x12,%zmm28,%zmm29,%zmm30",},
839{{0x62, 0x03, 0xad, 0x40, 0x54, 0xd9, 0x12, }, 7, 0, "", "",
840"62 03 ad 40 54 d9 12 \tvfixupimmpd $0x12,%zmm25,%zmm26,%zmm27",},
841{{0x62, 0x03, 0x15, 0x07, 0x55, 0xf4, 0x12, }, 7, 0, "", "",
842"62 03 15 07 55 f4 12 \tvfixupimmss $0x12,%xmm28,%xmm29,%xmm30{%k7}",},
843{{0x62, 0x03, 0xad, 0x07, 0x55, 0xd9, 0x12, }, 7, 0, "", "",
844"62 03 ad 07 55 d9 12 \tvfixupimmsd $0x12,%xmm25,%xmm26,%xmm27{%k7}",},
845{{0x62, 0x03, 0x7d, 0x48, 0x56, 0xda, 0x12, }, 7, 0, "", "",
846"62 03 7d 48 56 da 12 \tvreduceps $0x12,%zmm26,%zmm27",},
847{{0x62, 0x03, 0xfd, 0x48, 0x56, 0xf5, 0x12, }, 7, 0, "", "",
848"62 03 fd 48 56 f5 12 \tvreducepd $0x12,%zmm29,%zmm30",},
849{{0x62, 0x03, 0x2d, 0x00, 0x57, 0xd9, 0x12, }, 7, 0, "", "",
850"62 03 2d 00 57 d9 12 \tvreducess $0x12,%xmm25,%xmm26,%xmm27",},
851{{0x62, 0x03, 0x95, 0x00, 0x57, 0xf4, 0x12, }, 7, 0, "", "",
852"62 03 95 00 57 f4 12 \tvreducesd $0x12,%xmm28,%xmm29,%xmm30",},
853{{0x62, 0x93, 0x7d, 0x48, 0x66, 0xeb, 0x12, }, 7, 0, "", "",
854"62 93 7d 48 66 eb 12 \tvfpclassps $0x12,%zmm27,%k5",},
855{{0x62, 0x93, 0xfd, 0x48, 0x66, 0xee, 0x12, }, 7, 0, "", "",
856"62 93 fd 48 66 ee 12 \tvfpclasspd $0x12,%zmm30,%k5",},
857{{0x62, 0x93, 0x7d, 0x08, 0x67, 0xeb, 0x12, }, 7, 0, "", "",
858"62 93 7d 08 67 eb 12 \tvfpclassss $0x12,%xmm27,%k5",},
859{{0x62, 0x93, 0xfd, 0x08, 0x67, 0xee, 0x12, }, 7, 0, "", "",
860"62 93 fd 08 67 ee 12 \tvfpclasssd $0x12,%xmm30,%k5",},
861{{0x62, 0x91, 0x2d, 0x40, 0x72, 0xc1, 0x12, }, 7, 0, "", "",
862"62 91 2d 40 72 c1 12 \tvprord $0x12,%zmm25,%zmm26",},
863{{0x62, 0x91, 0xad, 0x40, 0x72, 0xc1, 0x12, }, 7, 0, "", "",
864"62 91 ad 40 72 c1 12 \tvprorq $0x12,%zmm25,%zmm26",},
865{{0x62, 0x91, 0x0d, 0x40, 0x72, 0xcd, 0x12, }, 7, 0, "", "",
866"62 91 0d 40 72 cd 12 \tvprold $0x12,%zmm29,%zmm30",},
867{{0x62, 0x91, 0x8d, 0x40, 0x72, 0xcd, 0x12, }, 7, 0, "", "",
868"62 91 8d 40 72 cd 12 \tvprolq $0x12,%zmm29,%zmm30",},
869{{0x0f, 0x72, 0xe6, 0x02, }, 4, 0, "", "",
870"0f 72 e6 02 \tpsrad $0x2,%mm6",},
871{{0xc5, 0xed, 0x72, 0xe6, 0x05, }, 5, 0, "", "",
872"c5 ed 72 e6 05 \tvpsrad $0x5,%ymm6,%ymm2",},
873{{0x62, 0x91, 0x4d, 0x40, 0x72, 0xe2, 0x05, }, 7, 0, "", "",
874"62 91 4d 40 72 e2 05 \tvpsrad $0x5,%zmm26,%zmm22",},
875{{0x62, 0x91, 0xcd, 0x40, 0x72, 0xe2, 0x05, }, 7, 0, "", "",
876"62 91 cd 40 72 e2 05 \tvpsraq $0x5,%zmm26,%zmm22",},
877{{0x62, 0x92, 0x7d, 0x41, 0xc6, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
878"62 92 7d 41 c6 8c fe 7b 00 00 00 \tvgatherpf0dps 0x7b(%r14,%zmm31,8){%k1}",},
879{{0x62, 0x92, 0xfd, 0x41, 0xc6, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
880"62 92 fd 41 c6 8c fe 7b 00 00 00 \tvgatherpf0dpd 0x7b(%r14,%ymm31,8){%k1}",},
881{{0x62, 0x92, 0x7d, 0x41, 0xc6, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
882"62 92 7d 41 c6 94 fe 7b 00 00 00 \tvgatherpf1dps 0x7b(%r14,%zmm31,8){%k1}",},
883{{0x62, 0x92, 0xfd, 0x41, 0xc6, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
884"62 92 fd 41 c6 94 fe 7b 00 00 00 \tvgatherpf1dpd 0x7b(%r14,%ymm31,8){%k1}",},
885{{0x62, 0x92, 0x7d, 0x41, 0xc6, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
886"62 92 7d 41 c6 ac fe 7b 00 00 00 \tvscatterpf0dps 0x7b(%r14,%zmm31,8){%k1}",},
887{{0x62, 0x92, 0xfd, 0x41, 0xc6, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
888"62 92 fd 41 c6 ac fe 7b 00 00 00 \tvscatterpf0dpd 0x7b(%r14,%ymm31,8){%k1}",},
889{{0x62, 0x92, 0x7d, 0x41, 0xc6, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
890"62 92 7d 41 c6 b4 fe 7b 00 00 00 \tvscatterpf1dps 0x7b(%r14,%zmm31,8){%k1}",},
891{{0x62, 0x92, 0xfd, 0x41, 0xc6, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
892"62 92 fd 41 c6 b4 fe 7b 00 00 00 \tvscatterpf1dpd 0x7b(%r14,%ymm31,8){%k1}",},
893{{0x62, 0x92, 0x7d, 0x41, 0xc7, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
894"62 92 7d 41 c7 8c fe 7b 00 00 00 \tvgatherpf0qps 0x7b(%r14,%zmm31,8){%k1}",},
895{{0x62, 0x92, 0xfd, 0x41, 0xc7, 0x8c, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
896"62 92 fd 41 c7 8c fe 7b 00 00 00 \tvgatherpf0qpd 0x7b(%r14,%zmm31,8){%k1}",},
897{{0x62, 0x92, 0x7d, 0x41, 0xc7, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
898"62 92 7d 41 c7 94 fe 7b 00 00 00 \tvgatherpf1qps 0x7b(%r14,%zmm31,8){%k1}",},
899{{0x62, 0x92, 0xfd, 0x41, 0xc7, 0x94, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
900"62 92 fd 41 c7 94 fe 7b 00 00 00 \tvgatherpf1qpd 0x7b(%r14,%zmm31,8){%k1}",},
901{{0x62, 0x92, 0x7d, 0x41, 0xc7, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
902"62 92 7d 41 c7 ac fe 7b 00 00 00 \tvscatterpf0qps 0x7b(%r14,%zmm31,8){%k1}",},
903{{0x62, 0x92, 0xfd, 0x41, 0xc7, 0xac, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
904"62 92 fd 41 c7 ac fe 7b 00 00 00 \tvscatterpf0qpd 0x7b(%r14,%zmm31,8){%k1}",},
905{{0x62, 0x92, 0x7d, 0x41, 0xc7, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
906"62 92 7d 41 c7 b4 fe 7b 00 00 00 \tvscatterpf1qps 0x7b(%r14,%zmm31,8){%k1}",},
907{{0x62, 0x92, 0xfd, 0x41, 0xc7, 0xb4, 0xfe, 0x7b, 0x00, 0x00, 0x00, }, 11, 0, "", "",
908"62 92 fd 41 c7 b4 fe 7b 00 00 00 \tvscatterpf1qpd 0x7b(%r14,%zmm31,8){%k1}",},
909{{0x62, 0x01, 0x95, 0x40, 0x58, 0xf4, }, 6, 0, "", "",
910"62 01 95 40 58 f4 \tvaddpd %zmm28,%zmm29,%zmm30",},
911{{0x62, 0x01, 0x95, 0x47, 0x58, 0xf4, }, 6, 0, "", "",
912"62 01 95 47 58 f4 \tvaddpd %zmm28,%zmm29,%zmm30{%k7}",},
913{{0x62, 0x01, 0x95, 0xc7, 0x58, 0xf4, }, 6, 0, "", "",
914"62 01 95 c7 58 f4 \tvaddpd %zmm28,%zmm29,%zmm30{%k7}{z}",},
915{{0x62, 0x01, 0x95, 0x10, 0x58, 0xf4, }, 6, 0, "", "",
916"62 01 95 10 58 f4 \tvaddpd {rn-sae},%zmm28,%zmm29,%zmm30",},
917{{0x62, 0x01, 0x95, 0x50, 0x58, 0xf4, }, 6, 0, "", "",
918"62 01 95 50 58 f4 \tvaddpd {ru-sae},%zmm28,%zmm29,%zmm30",},
919{{0x62, 0x01, 0x95, 0x30, 0x58, 0xf4, }, 6, 0, "", "",
920"62 01 95 30 58 f4 \tvaddpd {rd-sae},%zmm28,%zmm29,%zmm30",},
921{{0x62, 0x01, 0x95, 0x70, 0x58, 0xf4, }, 6, 0, "", "",
922"62 01 95 70 58 f4 \tvaddpd {rz-sae},%zmm28,%zmm29,%zmm30",},
923{{0x62, 0x61, 0x95, 0x40, 0x58, 0x31, }, 6, 0, "", "",
924"62 61 95 40 58 31 \tvaddpd (%rcx),%zmm29,%zmm30",},
925{{0x62, 0x21, 0x95, 0x40, 0x58, 0xb4, 0xf0, 0x23, 0x01, 0x00, 0x00, }, 11, 0, "", "",
926"62 21 95 40 58 b4 f0 23 01 00 00 \tvaddpd 0x123(%rax,%r14,8),%zmm29,%zmm30",},
927{{0x62, 0x61, 0x95, 0x50, 0x58, 0x31, }, 6, 0, "", "",
928"62 61 95 50 58 31 \tvaddpd (%rcx){1to8},%zmm29,%zmm30",},
929{{0x62, 0x61, 0x95, 0x40, 0x58, 0x72, 0x7f, }, 7, 0, "", "",
930"62 61 95 40 58 72 7f \tvaddpd 0x1fc0(%rdx),%zmm29,%zmm30",},
931{{0x62, 0x61, 0x95, 0x50, 0x58, 0x72, 0x7f, }, 7, 0, "", "",
932"62 61 95 50 58 72 7f \tvaddpd 0x3f8(%rdx){1to8},%zmm29,%zmm30",},
933{{0x62, 0xf1, 0x0c, 0x50, 0xc2, 0x6a, 0x7f, 0x08, }, 8, 0, "", "",
934"62 f1 0c 50 c2 6a 7f 08 \tvcmpeq_uqps 0x1fc(%rdx){1to16},%zmm30,%k5",},
935{{0x62, 0xb1, 0x97, 0x07, 0xc2, 0xac, 0xf0, 0x23, 0x01, 0x00, 0x00, 0x01, }, 12, 0, "", "",
936"62 b1 97 07 c2 ac f0 23 01 00 00 01 \tvcmpltsd 0x123(%rax,%r14,8),%xmm29,%k5{%k7}",},
937{{0x62, 0x91, 0x97, 0x17, 0xc2, 0xec, 0x02, }, 7, 0, "", "",
938"62 91 97 17 c2 ec 02 \tvcmplesd {sae},%xmm28,%xmm29,%k5{%k7}",},
939{{0x62, 0x23, 0x15, 0x07, 0x27, 0xb4, 0xf0, 0x23, 0x01, 0x00, 0x00, 0x5b, }, 12, 0, "", "",
940"62 23 15 07 27 b4 f0 23 01 00 00 5b \tvgetmantss $0x5b,0x123(%rax,%r14,8),%xmm29,%xmm30{%k7}",},
9{{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "", 941{{0xf3, 0x0f, 0x1b, 0x00, }, 4, 0, "", "",
10"f3 0f 1b 00 \tbndmk (%rax),%bnd0",}, 942"f3 0f 1b 00 \tbndmk (%rax),%bnd0",},
11{{0xf3, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "", 943{{0xf3, 0x41, 0x0f, 0x1b, 0x00, }, 5, 0, "", "",
@@ -325,19 +1257,19 @@
325{{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "", 1257{{0x0f, 0x1b, 0x84, 0x08, 0x78, 0x56, 0x34, 0x12, }, 8, 0, "", "",
326"0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%rax,%rcx,1)",}, 1258"0f 1b 84 08 78 56 34 12 \tbndstx %bnd0,0x12345678(%rax,%rcx,1)",},
327{{0xf2, 0xe8, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "call", "unconditional", 1259{{0xf2, 0xe8, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "call", "unconditional",
328"f2 e8 00 00 00 00 \tbnd callq 3f6 <main+0x3f6>",}, 1260"f2 e8 00 00 00 00 \tbnd callq f22 <main+0xf22>",},
329{{0x67, 0xf2, 0xff, 0x10, }, 4, 0, "call", "indirect", 1261{{0x67, 0xf2, 0xff, 0x10, }, 4, 0, "call", "indirect",
330"67 f2 ff 10 \tbnd callq *(%eax)",}, 1262"67 f2 ff 10 \tbnd callq *(%eax)",},
331{{0xf2, 0xc3, }, 2, 0, "ret", "indirect", 1263{{0xf2, 0xc3, }, 2, 0, "ret", "indirect",
332"f2 c3 \tbnd retq ",}, 1264"f2 c3 \tbnd retq ",},
333{{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", 1265{{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional",
334"f2 e9 00 00 00 00 \tbnd jmpq 402 <main+0x402>",}, 1266"f2 e9 00 00 00 00 \tbnd jmpq f2e <main+0xf2e>",},
335{{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional", 1267{{0xf2, 0xe9, 0x00, 0x00, 0x00, 0x00, }, 6, 0, "jmp", "unconditional",
336"f2 e9 00 00 00 00 \tbnd jmpq 408 <main+0x408>",}, 1268"f2 e9 00 00 00 00 \tbnd jmpq f34 <main+0xf34>",},
337{{0x67, 0xf2, 0xff, 0x21, }, 4, 0, "jmp", "indirect", 1269{{0x67, 0xf2, 0xff, 0x21, }, 4, 0, "jmp", "indirect",
338"67 f2 ff 21 \tbnd jmpq *(%ecx)",}, 1270"67 f2 ff 21 \tbnd jmpq *(%ecx)",},
339{{0xf2, 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, }, 7, 0, "jcc", "conditional", 1271{{0xf2, 0x0f, 0x85, 0x00, 0x00, 0x00, 0x00, }, 7, 0, "jcc", "conditional",
340"f2 0f 85 00 00 00 00 \tbnd jne 413 <main+0x413>",}, 1272"f2 0f 85 00 00 00 00 \tbnd jne f3f <main+0xf3f>",},
341{{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "", 1273{{0x0f, 0x3a, 0xcc, 0xc1, 0x00, }, 5, 0, "", "",
342"0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",}, 1274"0f 3a cc c1 00 \tsha1rnds4 $0x0,%xmm1,%xmm0",},
343{{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "", 1275{{0x0f, 0x3a, 0xcc, 0xd7, 0x91, }, 5, 0, "", "",
@@ -764,5 +1696,3 @@
764"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",}, 1696"0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%rax,%rcx,8)",},
765{{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "", 1697{{0x41, 0x0f, 0xc7, 0x9c, 0xc8, 0x78, 0x56, 0x34, 0x12, }, 9, 0, "", "",
766"41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",}, 1698"41 0f c7 9c c8 78 56 34 12 \txrstors 0x12345678(%r8,%rcx,8)",},
767{{0x66, 0x0f, 0xae, 0xf8, }, 4, 0, "", "",
768"66 0f ae f8 \tpcommit ",},
diff --git a/tools/perf/arch/x86/tests/insn-x86-dat-src.c b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
index 41b1b1c62660..979487dae8d4 100644
--- a/tools/perf/arch/x86/tests/insn-x86-dat-src.c
+++ b/tools/perf/arch/x86/tests/insn-x86-dat-src.c
@@ -19,8 +19,882 @@ int main(void)
19 /* Following line is a marker for the awk script - do not change */ 19 /* Following line is a marker for the awk script - do not change */
20 asm volatile("rdtsc"); /* Start here */ 20 asm volatile("rdtsc"); /* Start here */
21 21
22 /* Test fix for vcvtph2ps in x86-opcode-map.txt */
23
24 asm volatile("vcvtph2ps %xmm3,%ymm5");
25
22#ifdef __x86_64__ 26#ifdef __x86_64__
23 27
28 /* AVX-512: Instructions with the same op codes as Mask Instructions */
29
30 asm volatile("cmovno %rax,%rbx");
31 asm volatile("cmovno 0x12345678(%rax),%rcx");
32 asm volatile("cmovno 0x12345678(%rax),%cx");
33
34 asm volatile("cmove %rax,%rbx");
35 asm volatile("cmove 0x12345678(%rax),%rcx");
36 asm volatile("cmove 0x12345678(%rax),%cx");
37
38 asm volatile("seto 0x12345678(%rax)");
39 asm volatile("setno 0x12345678(%rax)");
40 asm volatile("setb 0x12345678(%rax)");
41 asm volatile("setc 0x12345678(%rax)");
42 asm volatile("setnae 0x12345678(%rax)");
43 asm volatile("setae 0x12345678(%rax)");
44 asm volatile("setnb 0x12345678(%rax)");
45 asm volatile("setnc 0x12345678(%rax)");
46 asm volatile("sets 0x12345678(%rax)");
47 asm volatile("setns 0x12345678(%rax)");
48
49 /* AVX-512: Mask Instructions */
50
51 asm volatile("kandw %k7,%k6,%k5");
52 asm volatile("kandq %k7,%k6,%k5");
53 asm volatile("kandb %k7,%k6,%k5");
54 asm volatile("kandd %k7,%k6,%k5");
55
56 asm volatile("kandnw %k7,%k6,%k5");
57 asm volatile("kandnq %k7,%k6,%k5");
58 asm volatile("kandnb %k7,%k6,%k5");
59 asm volatile("kandnd %k7,%k6,%k5");
60
61 asm volatile("knotw %k7,%k6");
62 asm volatile("knotq %k7,%k6");
63 asm volatile("knotb %k7,%k6");
64 asm volatile("knotd %k7,%k6");
65
66 asm volatile("korw %k7,%k6,%k5");
67 asm volatile("korq %k7,%k6,%k5");
68 asm volatile("korb %k7,%k6,%k5");
69 asm volatile("kord %k7,%k6,%k5");
70
71 asm volatile("kxnorw %k7,%k6,%k5");
72 asm volatile("kxnorq %k7,%k6,%k5");
73 asm volatile("kxnorb %k7,%k6,%k5");
74 asm volatile("kxnord %k7,%k6,%k5");
75
76 asm volatile("kxorw %k7,%k6,%k5");
77 asm volatile("kxorq %k7,%k6,%k5");
78 asm volatile("kxorb %k7,%k6,%k5");
79 asm volatile("kxord %k7,%k6,%k5");
80
81 asm volatile("kaddw %k7,%k6,%k5");
82 asm volatile("kaddq %k7,%k6,%k5");
83 asm volatile("kaddb %k7,%k6,%k5");
84 asm volatile("kaddd %k7,%k6,%k5");
85
86 asm volatile("kunpckbw %k7,%k6,%k5");
87 asm volatile("kunpckwd %k7,%k6,%k5");
88 asm volatile("kunpckdq %k7,%k6,%k5");
89
90 asm volatile("kmovw %k6,%k5");
91 asm volatile("kmovw (%rcx),%k5");
92 asm volatile("kmovw 0x123(%rax,%r14,8),%k5");
93 asm volatile("kmovw %k5,(%rcx)");
94 asm volatile("kmovw %k5,0x123(%rax,%r14,8)");
95 asm volatile("kmovw %eax,%k5");
96 asm volatile("kmovw %ebp,%k5");
97 asm volatile("kmovw %r13d,%k5");
98 asm volatile("kmovw %k5,%eax");
99 asm volatile("kmovw %k5,%ebp");
100 asm volatile("kmovw %k5,%r13d");
101
102 asm volatile("kmovq %k6,%k5");
103 asm volatile("kmovq (%rcx),%k5");
104 asm volatile("kmovq 0x123(%rax,%r14,8),%k5");
105 asm volatile("kmovq %k5,(%rcx)");
106 asm volatile("kmovq %k5,0x123(%rax,%r14,8)");
107 asm volatile("kmovq %rax,%k5");
108 asm volatile("kmovq %rbp,%k5");
109 asm volatile("kmovq %r13,%k5");
110 asm volatile("kmovq %k5,%rax");
111 asm volatile("kmovq %k5,%rbp");
112 asm volatile("kmovq %k5,%r13");
113
114 asm volatile("kmovb %k6,%k5");
115 asm volatile("kmovb (%rcx),%k5");
116 asm volatile("kmovb 0x123(%rax,%r14,8),%k5");
117 asm volatile("kmovb %k5,(%rcx)");
118 asm volatile("kmovb %k5,0x123(%rax,%r14,8)");
119 asm volatile("kmovb %eax,%k5");
120 asm volatile("kmovb %ebp,%k5");
121 asm volatile("kmovb %r13d,%k5");
122 asm volatile("kmovb %k5,%eax");
123 asm volatile("kmovb %k5,%ebp");
124 asm volatile("kmovb %k5,%r13d");
125
126 asm volatile("kmovd %k6,%k5");
127 asm volatile("kmovd (%rcx),%k5");
128 asm volatile("kmovd 0x123(%rax,%r14,8),%k5");
129 asm volatile("kmovd %k5,(%rcx)");
130 asm volatile("kmovd %k5,0x123(%rax,%r14,8)");
131 asm volatile("kmovd %eax,%k5");
132 asm volatile("kmovd %ebp,%k5");
133 asm volatile("kmovd %r13d,%k5");
134 asm volatile("kmovd %k5,%eax");
135 asm volatile("kmovd %k5,%ebp");
136 asm volatile("kmovd %k5,%r13d");
137
138 asm volatile("kortestw %k6,%k5");
139 asm volatile("kortestq %k6,%k5");
140 asm volatile("kortestb %k6,%k5");
141 asm volatile("kortestd %k6,%k5");
142
143 asm volatile("ktestw %k6,%k5");
144 asm volatile("ktestq %k6,%k5");
145 asm volatile("ktestb %k6,%k5");
146 asm volatile("ktestd %k6,%k5");
147
148 asm volatile("kshiftrw $0x12,%k6,%k5");
149 asm volatile("kshiftrq $0x5b,%k6,%k5");
150 asm volatile("kshiftlw $0x12,%k6,%k5");
151 asm volatile("kshiftlq $0x5b,%k6,%k5");
152
153 /* AVX-512: Op code 0f 5b */
154 asm volatile("vcvtdq2ps %xmm5,%xmm6");
155 asm volatile("vcvtqq2ps %zmm29,%ymm6{%k7}");
156 asm volatile("vcvtps2dq %xmm5,%xmm6");
157 asm volatile("vcvttps2dq %xmm5,%xmm6");
158
159 /* AVX-512: Op code 0f 6f */
160
161 asm volatile("movq %mm0,%mm4");
162 asm volatile("vmovdqa %ymm4,%ymm6");
163 asm volatile("vmovdqa32 %zmm25,%zmm26");
164 asm volatile("vmovdqa64 %zmm25,%zmm26");
165 asm volatile("vmovdqu %ymm4,%ymm6");
166 asm volatile("vmovdqu32 %zmm29,%zmm30");
167 asm volatile("vmovdqu64 %zmm25,%zmm26");
168 asm volatile("vmovdqu8 %zmm29,%zmm30");
169 asm volatile("vmovdqu16 %zmm25,%zmm26");
170
171 /* AVX-512: Op code 0f 78 */
172
173 asm volatile("vmread %rax,%rbx");
174 asm volatile("vcvttps2udq %zmm25,%zmm26");
175 asm volatile("vcvttpd2udq %zmm29,%ymm6{%k7}");
176 asm volatile("vcvttsd2usi %xmm6,%rax");
177 asm volatile("vcvttss2usi %xmm6,%rax");
178 asm volatile("vcvttps2uqq %ymm5,%zmm26{%k7}");
179 asm volatile("vcvttpd2uqq %zmm29,%zmm30");
180
181 /* AVX-512: Op code 0f 79 */
182
183 asm volatile("vmwrite %rax,%rbx");
184 asm volatile("vcvtps2udq %zmm25,%zmm26");
185 asm volatile("vcvtpd2udq %zmm29,%ymm6{%k7}");
186 asm volatile("vcvtsd2usi %xmm6,%rax");
187 asm volatile("vcvtss2usi %xmm6,%rax");
188 asm volatile("vcvtps2uqq %ymm5,%zmm26{%k7}");
189 asm volatile("vcvtpd2uqq %zmm29,%zmm30");
190
191 /* AVX-512: Op code 0f 7a */
192
193 asm volatile("vcvtudq2pd %ymm5,%zmm29{%k7}");
194 asm volatile("vcvtuqq2pd %zmm25,%zmm26");
195 asm volatile("vcvtudq2ps %zmm29,%zmm30");
196 asm volatile("vcvtuqq2ps %zmm25,%ymm26{%k7}");
197 asm volatile("vcvttps2qq %ymm25,%zmm26{%k7}");
198 asm volatile("vcvttpd2qq %zmm29,%zmm30");
199
200 /* AVX-512: Op code 0f 7b */
201
202 asm volatile("vcvtusi2sd %eax,%xmm5,%xmm6");
203 asm volatile("vcvtusi2ss %eax,%xmm5,%xmm6");
204 asm volatile("vcvtps2qq %ymm5,%zmm26{%k7}");
205 asm volatile("vcvtpd2qq %zmm29,%zmm30");
206
207 /* AVX-512: Op code 0f 7f */
208
209 asm volatile("movq.s %mm0,%mm4");
210 asm volatile("vmovdqa %ymm8,%ymm6");
211 asm volatile("vmovdqa32.s %zmm25,%zmm26");
212 asm volatile("vmovdqa64.s %zmm25,%zmm26");
213 asm volatile("vmovdqu %ymm8,%ymm6");
214 asm volatile("vmovdqu32.s %zmm25,%zmm26");
215 asm volatile("vmovdqu64.s %zmm25,%zmm26");
216 asm volatile("vmovdqu8.s %zmm30,(%rcx)");
217 asm volatile("vmovdqu16.s %zmm25,%zmm26");
218
219 /* AVX-512: Op code 0f db */
220
221 asm volatile("pand %mm1,%mm2");
222 asm volatile("pand %xmm1,%xmm2");
223 asm volatile("vpand %ymm4,%ymm6,%ymm2");
224 asm volatile("vpandd %zmm24,%zmm25,%zmm26");
225 asm volatile("vpandq %zmm24,%zmm25,%zmm26");
226
227 /* AVX-512: Op code 0f df */
228
229 asm volatile("pandn %mm1,%mm2");
230 asm volatile("pandn %xmm1,%xmm2");
231 asm volatile("vpandn %ymm4,%ymm6,%ymm2");
232 asm volatile("vpandnd %zmm24,%zmm25,%zmm26");
233 asm volatile("vpandnq %zmm24,%zmm25,%zmm26");
234
235 /* AVX-512: Op code 0f e6 */
236
237 asm volatile("vcvttpd2dq %xmm1,%xmm2");
238 asm volatile("vcvtdq2pd %xmm5,%xmm6");
239 asm volatile("vcvtdq2pd %ymm5,%zmm26{%k7}");
240 asm volatile("vcvtqq2pd %zmm25,%zmm26");
241 asm volatile("vcvtpd2dq %xmm1,%xmm2");
242
243 /* AVX-512: Op code 0f eb */
244
245 asm volatile("por %mm4,%mm6");
246 asm volatile("vpor %ymm4,%ymm6,%ymm2");
247 asm volatile("vpord %zmm24,%zmm25,%zmm26");
248 asm volatile("vporq %zmm24,%zmm25,%zmm26");
249
250 /* AVX-512: Op code 0f ef */
251
252 asm volatile("pxor %mm4,%mm6");
253 asm volatile("vpxor %ymm4,%ymm6,%ymm2");
254 asm volatile("vpxord %zmm24,%zmm25,%zmm26");
255 asm volatile("vpxorq %zmm24,%zmm25,%zmm26");
256
257 /* AVX-512: Op code 0f 38 10 */
258
259 asm volatile("pblendvb %xmm1,%xmm0");
260 asm volatile("vpsrlvw %zmm27,%zmm28,%zmm29");
261 asm volatile("vpmovuswb %zmm28,%ymm6{%k7}");
262
263 /* AVX-512: Op code 0f 38 11 */
264
265 asm volatile("vpmovusdb %zmm28,%xmm6{%k7}");
266 asm volatile("vpsravw %zmm27,%zmm28,%zmm29");
267
268 /* AVX-512: Op code 0f 38 12 */
269
270 asm volatile("vpmovusqb %zmm27,%xmm6{%k7}");
271 asm volatile("vpsllvw %zmm27,%zmm28,%zmm29");
272
273 /* AVX-512: Op code 0f 38 13 */
274
275 asm volatile("vcvtph2ps %xmm3,%ymm5");
276 asm volatile("vcvtph2ps %ymm5,%zmm27{%k7}");
277 asm volatile("vpmovusdw %zmm27,%ymm6{%k7}");
278
279 /* AVX-512: Op code 0f 38 14 */
280
281 asm volatile("blendvps %xmm1,%xmm0");
282 asm volatile("vpmovusqw %zmm27,%xmm6{%k7}");
283 asm volatile("vprorvd %zmm27,%zmm28,%zmm29");
284 asm volatile("vprorvq %zmm27,%zmm28,%zmm29");
285
286 /* AVX-512: Op code 0f 38 15 */
287
288 asm volatile("blendvpd %xmm1,%xmm0");
289 asm volatile("vpmovusqd %zmm27,%ymm6{%k7}");
290 asm volatile("vprolvd %zmm27,%zmm28,%zmm29");
291 asm volatile("vprolvq %zmm27,%zmm28,%zmm29");
292
293 /* AVX-512: Op code 0f 38 16 */
294
295 asm volatile("vpermps %ymm4,%ymm6,%ymm2");
296 asm volatile("vpermps %ymm24,%ymm26,%ymm22{%k7}");
297 asm volatile("vpermpd %ymm24,%ymm26,%ymm22{%k7}");
298
299 /* AVX-512: Op code 0f 38 19 */
300
301 asm volatile("vbroadcastsd %xmm4,%ymm6");
302 asm volatile("vbroadcastf32x2 %xmm27,%zmm26");
303
304 /* AVX-512: Op code 0f 38 1a */
305
306 asm volatile("vbroadcastf128 (%rcx),%ymm4");
307 asm volatile("vbroadcastf32x4 (%rcx),%zmm26");
308 asm volatile("vbroadcastf64x2 (%rcx),%zmm26");
309
310 /* AVX-512: Op code 0f 38 1b */
311
312 asm volatile("vbroadcastf32x8 (%rcx),%zmm27");
313 asm volatile("vbroadcastf64x4 (%rcx),%zmm26");
314
315 /* AVX-512: Op code 0f 38 1f */
316
317 asm volatile("vpabsq %zmm27,%zmm28");
318
319 /* AVX-512: Op code 0f 38 20 */
320
321 asm volatile("vpmovsxbw %xmm4,%xmm5");
322 asm volatile("vpmovswb %zmm27,%ymm6{%k7}");
323
324 /* AVX-512: Op code 0f 38 21 */
325
326 asm volatile("vpmovsxbd %xmm4,%ymm6");
327 asm volatile("vpmovsdb %zmm27,%xmm6{%k7}");
328
329 /* AVX-512: Op code 0f 38 22 */
330
331 asm volatile("vpmovsxbq %xmm4,%ymm4");
332 asm volatile("vpmovsqb %zmm27,%xmm6{%k7}");
333
334 /* AVX-512: Op code 0f 38 23 */
335
336 asm volatile("vpmovsxwd %xmm4,%ymm4");
337 asm volatile("vpmovsdw %zmm27,%ymm6{%k7}");
338
339 /* AVX-512: Op code 0f 38 24 */
340
341 asm volatile("vpmovsxwq %xmm4,%ymm6");
342 asm volatile("vpmovsqw %zmm27,%xmm6{%k7}");
343
344 /* AVX-512: Op code 0f 38 25 */
345
346 asm volatile("vpmovsxdq %xmm4,%ymm4");
347 asm volatile("vpmovsqd %zmm27,%ymm6{%k7}");
348
349 /* AVX-512: Op code 0f 38 26 */
350
351 asm volatile("vptestmb %zmm27,%zmm28,%k5");
352 asm volatile("vptestmw %zmm27,%zmm28,%k5");
353 asm volatile("vptestnmb %zmm26,%zmm27,%k5");
354 asm volatile("vptestnmw %zmm26,%zmm27,%k5");
355
356 /* AVX-512: Op code 0f 38 27 */
357
358 asm volatile("vptestmd %zmm27,%zmm28,%k5");
359 asm volatile("vptestmq %zmm27,%zmm28,%k5");
360 asm volatile("vptestnmd %zmm26,%zmm27,%k5");
361 asm volatile("vptestnmq %zmm26,%zmm27,%k5");
362
363 /* AVX-512: Op code 0f 38 28 */
364
365 asm volatile("vpmuldq %ymm4,%ymm6,%ymm2");
366 asm volatile("vpmovm2b %k5,%zmm28");
367 asm volatile("vpmovm2w %k5,%zmm28");
368
369 /* AVX-512: Op code 0f 38 29 */
370
371 asm volatile("vpcmpeqq %ymm4,%ymm6,%ymm2");
372 asm volatile("vpmovb2m %zmm28,%k5");
373 asm volatile("vpmovw2m %zmm28,%k5");
374
375 /* AVX-512: Op code 0f 38 2a */
376
377 asm volatile("vmovntdqa (%rcx),%ymm4");
378 asm volatile("vpbroadcastmb2q %k6,%zmm30");
379
380 /* AVX-512: Op code 0f 38 2c */
381
382 asm volatile("vmaskmovps (%rcx),%ymm4,%ymm6");
383 asm volatile("vscalefps %zmm24,%zmm25,%zmm26");
384 asm volatile("vscalefpd %zmm24,%zmm25,%zmm26");
385
386 /* AVX-512: Op code 0f 38 2d */
387
388 asm volatile("vmaskmovpd (%rcx),%ymm4,%ymm6");
389 asm volatile("vscalefss %xmm24,%xmm25,%xmm26{%k7}");
390 asm volatile("vscalefsd %xmm24,%xmm25,%xmm26{%k7}");
391
392 /* AVX-512: Op code 0f 38 30 */
393
394 asm volatile("vpmovzxbw %xmm4,%ymm4");
395 asm volatile("vpmovwb %zmm27,%ymm6{%k7}");
396
397 /* AVX-512: Op code 0f 38 31 */
398
399 asm volatile("vpmovzxbd %xmm4,%ymm6");
400 asm volatile("vpmovdb %zmm27,%xmm6{%k7}");
401
402 /* AVX-512: Op code 0f 38 32 */
403
404 asm volatile("vpmovzxbq %xmm4,%ymm4");
405 asm volatile("vpmovqb %zmm27,%xmm6{%k7}");
406
407 /* AVX-512: Op code 0f 38 33 */
408
409 asm volatile("vpmovzxwd %xmm4,%ymm4");
410 asm volatile("vpmovdw %zmm27,%ymm6{%k7}");
411
412 /* AVX-512: Op code 0f 38 34 */
413
414 asm volatile("vpmovzxwq %xmm4,%ymm6");
415 asm volatile("vpmovqw %zmm27,%xmm6{%k7}");
416
417 /* AVX-512: Op code 0f 38 35 */
418
419 asm volatile("vpmovzxdq %xmm4,%ymm4");
420 asm volatile("vpmovqd %zmm27,%ymm6{%k7}");
421
422 /* AVX-512: Op code 0f 38 38 */
423
424 asm volatile("vpermd %ymm4,%ymm6,%ymm2");
425 asm volatile("vpermd %ymm24,%ymm26,%ymm22{%k7}");
426 asm volatile("vpermq %ymm24,%ymm26,%ymm22{%k7}");
427
428 /* AVX-512: Op code 0f 38 38 */
429
430 asm volatile("vpminsb %ymm4,%ymm6,%ymm2");
431 asm volatile("vpmovm2d %k5,%zmm28");
432 asm volatile("vpmovm2q %k5,%zmm28");
433
434 /* AVX-512: Op code 0f 38 39 */
435
436 asm volatile("vpminsd %xmm1,%xmm2,%xmm3");
437 asm volatile("vpminsd %zmm24,%zmm25,%zmm26");
438 asm volatile("vpminsq %zmm24,%zmm25,%zmm26");
439 asm volatile("vpmovd2m %zmm28,%k5");
440 asm volatile("vpmovq2m %zmm28,%k5");
441
442 /* AVX-512: Op code 0f 38 3a */
443
444 asm volatile("vpminuw %ymm4,%ymm6,%ymm2");
445 asm volatile("vpbroadcastmw2d %k6,%zmm28");
446
447 /* AVX-512: Op code 0f 38 3b */
448
449 asm volatile("vpminud %ymm4,%ymm6,%ymm2");
450 asm volatile("vpminud %zmm24,%zmm25,%zmm26");
451 asm volatile("vpminuq %zmm24,%zmm25,%zmm26");
452
453 /* AVX-512: Op code 0f 38 3d */
454
455 asm volatile("vpmaxsd %ymm4,%ymm6,%ymm2");
456 asm volatile("vpmaxsd %zmm24,%zmm25,%zmm26");
457 asm volatile("vpmaxsq %zmm24,%zmm25,%zmm26");
458
459 /* AVX-512: Op code 0f 38 3f */
460
461 asm volatile("vpmaxud %ymm4,%ymm6,%ymm2");
462 asm volatile("vpmaxud %zmm24,%zmm25,%zmm26");
463 asm volatile("vpmaxuq %zmm24,%zmm25,%zmm26");
464
465 /* AVX-512: Op code 0f 38 42 */
466
467 asm volatile("vpmulld %ymm4,%ymm6,%ymm2");
468 asm volatile("vpmulld %zmm24,%zmm25,%zmm26");
469 asm volatile("vpmullq %zmm24,%zmm25,%zmm26");
470
471 /* AVX-512: Op code 0f 38 42 */
472
473 asm volatile("vgetexpps %zmm25,%zmm26");
474 asm volatile("vgetexppd %zmm27,%zmm28");
475
476 /* AVX-512: Op code 0f 38 43 */
477
478 asm volatile("vgetexpss %xmm24,%xmm25,%xmm26{%k7}");
479 asm volatile("vgetexpsd %xmm28,%xmm29,%xmm30{%k7}");
480
481 /* AVX-512: Op code 0f 38 44 */
482
483 asm volatile("vplzcntd %zmm27,%zmm28");
484 asm volatile("vplzcntq %zmm27,%zmm28");
485
486 /* AVX-512: Op code 0f 38 46 */
487
488 asm volatile("vpsravd %ymm4,%ymm6,%ymm2");
489 asm volatile("vpsravd %zmm24,%zmm25,%zmm26");
490 asm volatile("vpsravq %zmm24,%zmm25,%zmm26");
491
492 /* AVX-512: Op code 0f 38 4c */
493
494 asm volatile("vrcp14ps %zmm25,%zmm26");
495 asm volatile("vrcp14pd %zmm27,%zmm28");
496
497 /* AVX-512: Op code 0f 38 4d */
498
499 asm volatile("vrcp14ss %xmm24,%xmm25,%xmm26{%k7}");
500 asm volatile("vrcp14sd %xmm24,%xmm25,%xmm26{%k7}");
501
502 /* AVX-512: Op code 0f 38 4e */
503
504 asm volatile("vrsqrt14ps %zmm25,%zmm26");
505 asm volatile("vrsqrt14pd %zmm27,%zmm28");
506
507 /* AVX-512: Op code 0f 38 4f */
508
509 asm volatile("vrsqrt14ss %xmm24,%xmm25,%xmm26{%k7}");
510 asm volatile("vrsqrt14sd %xmm24,%xmm25,%xmm26{%k7}");
511
512 /* AVX-512: Op code 0f 38 59 */
513
514 asm volatile("vpbroadcastq %xmm4,%xmm6");
515 asm volatile("vbroadcasti32x2 %xmm27,%zmm26");
516
517 /* AVX-512: Op code 0f 38 5a */
518
519 asm volatile("vbroadcasti128 (%rcx),%ymm4");
520 asm volatile("vbroadcasti32x4 (%rcx),%zmm26");
521 asm volatile("vbroadcasti64x2 (%rcx),%zmm26");
522
523 /* AVX-512: Op code 0f 38 5b */
524
525 asm volatile("vbroadcasti32x8 (%rcx),%zmm28");
526 asm volatile("vbroadcasti64x4 (%rcx),%zmm26");
527
528 /* AVX-512: Op code 0f 38 64 */
529
530 asm volatile("vpblendmd %zmm26,%zmm27,%zmm28");
531 asm volatile("vpblendmq %zmm26,%zmm27,%zmm28");
532
533 /* AVX-512: Op code 0f 38 65 */
534
535 asm volatile("vblendmps %zmm24,%zmm25,%zmm26");
536 asm volatile("vblendmpd %zmm26,%zmm27,%zmm28");
537
538 /* AVX-512: Op code 0f 38 66 */
539
540 asm volatile("vpblendmb %zmm26,%zmm27,%zmm28");
541 asm volatile("vpblendmw %zmm26,%zmm27,%zmm28");
542
543 /* AVX-512: Op code 0f 38 75 */
544
545 asm volatile("vpermi2b %zmm24,%zmm25,%zmm26");
546 asm volatile("vpermi2w %zmm26,%zmm27,%zmm28");
547
548 /* AVX-512: Op code 0f 38 76 */
549
550 asm volatile("vpermi2d %zmm26,%zmm27,%zmm28");
551 asm volatile("vpermi2q %zmm26,%zmm27,%zmm28");
552
553 /* AVX-512: Op code 0f 38 77 */
554
555 asm volatile("vpermi2ps %zmm26,%zmm27,%zmm28");
556 asm volatile("vpermi2pd %zmm26,%zmm27,%zmm28");
557
558 /* AVX-512: Op code 0f 38 7a */
559
560 asm volatile("vpbroadcastb %eax,%xmm30");
561
562 /* AVX-512: Op code 0f 38 7b */
563
564 asm volatile("vpbroadcastw %eax,%xmm30");
565
566 /* AVX-512: Op code 0f 38 7c */
567
568 asm volatile("vpbroadcastd %eax,%xmm30");
569 asm volatile("vpbroadcastq %rax,%zmm30");
570
571 /* AVX-512: Op code 0f 38 7d */
572
573 asm volatile("vpermt2b %zmm26,%zmm27,%zmm28");
574 asm volatile("vpermt2w %zmm26,%zmm27,%zmm28");
575
576 /* AVX-512: Op code 0f 38 7e */
577
578 asm volatile("vpermt2d %zmm26,%zmm27,%zmm28");
579 asm volatile("vpermt2q %zmm26,%zmm27,%zmm28");
580
581 /* AVX-512: Op code 0f 38 7f */
582
583 asm volatile("vpermt2ps %zmm26,%zmm27,%zmm28");
584 asm volatile("vpermt2pd %zmm26,%zmm27,%zmm28");
585
586 /* AVX-512: Op code 0f 38 83 */
587
588 asm volatile("vpmultishiftqb %zmm26,%zmm27,%zmm28");
589
590 /* AVX-512: Op code 0f 38 88 */
591
592 asm volatile("vexpandps (%rcx),%zmm26");
593 asm volatile("vexpandpd (%rcx),%zmm28");
594
595 /* AVX-512: Op code 0f 38 89 */
596
597 asm volatile("vpexpandd (%rcx),%zmm28");
598 asm volatile("vpexpandq (%rcx),%zmm26");
599
600 /* AVX-512: Op code 0f 38 8a */
601
602 asm volatile("vcompressps %zmm28,(%rcx)");
603 asm volatile("vcompresspd %zmm28,(%rcx)");
604
605 /* AVX-512: Op code 0f 38 8b */
606
607 asm volatile("vpcompressd %zmm28,(%rcx)");
608 asm volatile("vpcompressq %zmm26,(%rcx)");
609
610 /* AVX-512: Op code 0f 38 8d */
611
612 asm volatile("vpermb %zmm26,%zmm27,%zmm28");
613 asm volatile("vpermw %zmm26,%zmm27,%zmm28");
614
615 /* AVX-512: Op code 0f 38 90 */
616
617 asm volatile("vpgatherdd %xmm2,0x02(%rbp,%xmm7,2),%xmm1");
618 asm volatile("vpgatherdq %xmm2,0x04(%rbp,%xmm7,2),%xmm1");
619 asm volatile("vpgatherdd 0x7b(%rbp,%zmm27,8),%zmm26{%k1}");
620 asm volatile("vpgatherdq 0x7b(%rbp,%ymm27,8),%zmm26{%k1}");
621
622 /* AVX-512: Op code 0f 38 91 */
623
624 asm volatile("vpgatherqd %xmm2,0x02(%rbp,%xmm7,2),%xmm1");
625 asm volatile("vpgatherqq %xmm2,0x02(%rbp,%xmm7,2),%xmm1");
626 asm volatile("vpgatherqd 0x7b(%rbp,%zmm27,8),%ymm26{%k1}");
627 asm volatile("vpgatherqq 0x7b(%rbp,%zmm27,8),%zmm26{%k1}");
628
629 /* AVX-512: Op code 0f 38 a0 */
630
631 asm volatile("vpscatterdd %zmm28,0x7b(%rbp,%zmm29,8){%k1}");
632 asm volatile("vpscatterdq %zmm26,0x7b(%rbp,%ymm27,8){%k1}");
633
634 /* AVX-512: Op code 0f 38 a1 */
635
636 asm volatile("vpscatterqd %ymm6,0x7b(%rbp,%zmm29,8){%k1}");
637 asm volatile("vpscatterqq %ymm6,0x7b(%rbp,%ymm27,8){%k1}");
638
639 /* AVX-512: Op code 0f 38 a2 */
640
641 asm volatile("vscatterdps %zmm28,0x7b(%rbp,%zmm29,8){%k1}");
642 asm volatile("vscatterdpd %zmm28,0x7b(%rbp,%ymm27,8){%k1}");
643
644 /* AVX-512: Op code 0f 38 a3 */
645
646 asm volatile("vscatterqps %ymm6,0x7b(%rbp,%zmm29,8){%k1}");
647 asm volatile("vscatterqpd %zmm28,0x7b(%rbp,%zmm29,8){%k1}");
648
649 /* AVX-512: Op code 0f 38 b4 */
650
651 asm volatile("vpmadd52luq %zmm26,%zmm27,%zmm28");
652
653 /* AVX-512: Op code 0f 38 b5 */
654
655 asm volatile("vpmadd52huq %zmm26,%zmm27,%zmm28");
656
657 /* AVX-512: Op code 0f 38 c4 */
658
659 asm volatile("vpconflictd %zmm26,%zmm27");
660 asm volatile("vpconflictq %zmm26,%zmm27");
661
662 /* AVX-512: Op code 0f 38 c8 */
663
664 asm volatile("vexp2ps %zmm29,%zmm30");
665 asm volatile("vexp2pd %zmm26,%zmm27");
666
667 /* AVX-512: Op code 0f 38 ca */
668
669 asm volatile("vrcp28ps %zmm29,%zmm30");
670 asm volatile("vrcp28pd %zmm26,%zmm27");
671
672 /* AVX-512: Op code 0f 38 cb */
673
674 asm volatile("vrcp28ss %xmm28,%xmm29,%xmm30{%k7}");
675 asm volatile("vrcp28sd %xmm25,%xmm26,%xmm27{%k7}");
676
677 /* AVX-512: Op code 0f 38 cc */
678
679 asm volatile("vrsqrt28ps %zmm29,%zmm30");
680 asm volatile("vrsqrt28pd %zmm26,%zmm27");
681
682 /* AVX-512: Op code 0f 38 cd */
683
684 asm volatile("vrsqrt28ss %xmm28,%xmm29,%xmm30{%k7}");
685 asm volatile("vrsqrt28sd %xmm25,%xmm26,%xmm27{%k7}");
686
687 /* AVX-512: Op code 0f 3a 03 */
688
689 asm volatile("valignd $0x12,%zmm28,%zmm29,%zmm30");
690 asm volatile("valignq $0x12,%zmm25,%zmm26,%zmm27");
691
692 /* AVX-512: Op code 0f 3a 08 */
693
694 asm volatile("vroundps $0x5,%ymm6,%ymm2");
695 asm volatile("vrndscaleps $0x12,%zmm25,%zmm26");
696
697 /* AVX-512: Op code 0f 3a 09 */
698
699 asm volatile("vroundpd $0x5,%ymm6,%ymm2");
700 asm volatile("vrndscalepd $0x12,%zmm25,%zmm26");
701
702 /* AVX-512: Op code 0f 3a 1a */
703
704 asm volatile("vroundss $0x5,%xmm4,%xmm6,%xmm2");
705 asm volatile("vrndscaless $0x12,%xmm24,%xmm25,%xmm26{%k7}");
706
707 /* AVX-512: Op code 0f 3a 0b */
708
709 asm volatile("vroundsd $0x5,%xmm4,%xmm6,%xmm2");
710 asm volatile("vrndscalesd $0x12,%xmm24,%xmm25,%xmm26{%k7}");
711
712 /* AVX-512: Op code 0f 3a 18 */
713
714 asm volatile("vinsertf128 $0x5,%xmm4,%ymm4,%ymm6");
715 asm volatile("vinsertf32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}");
716 asm volatile("vinsertf64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}");
717
718 /* AVX-512: Op code 0f 3a 19 */
719
720 asm volatile("vextractf128 $0x5,%ymm4,%xmm4");
721 asm volatile("vextractf32x4 $0x12,%zmm25,%xmm26{%k7}");
722 asm volatile("vextractf64x2 $0x12,%zmm25,%xmm26{%k7}");
723
724 /* AVX-512: Op code 0f 3a 1a */
725
726 asm volatile("vinsertf32x8 $0x12,%ymm25,%zmm26,%zmm27{%k7}");
727 asm volatile("vinsertf64x4 $0x12,%ymm28,%zmm29,%zmm30{%k7}");
728
729 /* AVX-512: Op code 0f 3a 1b */
730
731 asm volatile("vextractf32x8 $0x12,%zmm29,%ymm30{%k7}");
732 asm volatile("vextractf64x4 $0x12,%zmm26,%ymm27{%k7}");
733
734 /* AVX-512: Op code 0f 3a 1e */
735
736 asm volatile("vpcmpud $0x12,%zmm29,%zmm30,%k5");
737 asm volatile("vpcmpuq $0x12,%zmm26,%zmm27,%k5");
738
739 /* AVX-512: Op code 0f 3a 1f */
740
741 asm volatile("vpcmpd $0x12,%zmm29,%zmm30,%k5");
742 asm volatile("vpcmpq $0x12,%zmm26,%zmm27,%k5");
743
744 /* AVX-512: Op code 0f 3a 23 */
745
746 asm volatile("vshuff32x4 $0x12,%zmm28,%zmm29,%zmm30");
747 asm volatile("vshuff64x2 $0x12,%zmm25,%zmm26,%zmm27");
748
749 /* AVX-512: Op code 0f 3a 25 */
750
751 asm volatile("vpternlogd $0x12,%zmm28,%zmm29,%zmm30");
752 asm volatile("vpternlogq $0x12,%zmm28,%zmm29,%zmm30");
753
754 /* AVX-512: Op code 0f 3a 26 */
755
756 asm volatile("vgetmantps $0x12,%zmm26,%zmm27");
757 asm volatile("vgetmantpd $0x12,%zmm29,%zmm30");
758
759 /* AVX-512: Op code 0f 3a 27 */
760
761 asm volatile("vgetmantss $0x12,%xmm25,%xmm26,%xmm27{%k7}");
762 asm volatile("vgetmantsd $0x12,%xmm28,%xmm29,%xmm30{%k7}");
763
764 /* AVX-512: Op code 0f 3a 38 */
765
766 asm volatile("vinserti128 $0x5,%xmm4,%ymm4,%ymm6");
767 asm volatile("vinserti32x4 $0x12,%xmm24,%zmm25,%zmm26{%k7}");
768 asm volatile("vinserti64x2 $0x12,%xmm24,%zmm25,%zmm26{%k7}");
769
770 /* AVX-512: Op code 0f 3a 39 */
771
772 asm volatile("vextracti128 $0x5,%ymm4,%xmm6");
773 asm volatile("vextracti32x4 $0x12,%zmm25,%xmm26{%k7}");
774 asm volatile("vextracti64x2 $0x12,%zmm25,%xmm26{%k7}");
775
776 /* AVX-512: Op code 0f 3a 3a */
777
778 asm volatile("vinserti32x8 $0x12,%ymm28,%zmm29,%zmm30{%k7}");
779 asm volatile("vinserti64x4 $0x12,%ymm25,%zmm26,%zmm27{%k7}");
780
781 /* AVX-512: Op code 0f 3a 3b */
782
783 asm volatile("vextracti32x8 $0x12,%zmm29,%ymm30{%k7}");
784 asm volatile("vextracti64x4 $0x12,%zmm26,%ymm27{%k7}");
785
786 /* AVX-512: Op code 0f 3a 3e */
787
788 asm volatile("vpcmpub $0x12,%zmm29,%zmm30,%k5");
789 asm volatile("vpcmpuw $0x12,%zmm26,%zmm27,%k5");
790
791 /* AVX-512: Op code 0f 3a 3f */
792
793 asm volatile("vpcmpb $0x12,%zmm29,%zmm30,%k5");
794 asm volatile("vpcmpw $0x12,%zmm26,%zmm27,%k5");
795
796 /* AVX-512: Op code 0f 3a 43 */
797
798 asm volatile("vmpsadbw $0x5,%ymm4,%ymm6,%ymm2");
799 asm volatile("vdbpsadbw $0x12,%zmm4,%zmm5,%zmm6");
800
801 /* AVX-512: Op code 0f 3a 43 */
802
803 asm volatile("vshufi32x4 $0x12,%zmm25,%zmm26,%zmm27");
804 asm volatile("vshufi64x2 $0x12,%zmm28,%zmm29,%zmm30");
805
806 /* AVX-512: Op code 0f 3a 50 */
807
808 asm volatile("vrangeps $0x12,%zmm25,%zmm26,%zmm27");
809 asm volatile("vrangepd $0x12,%zmm28,%zmm29,%zmm30");
810
811 /* AVX-512: Op code 0f 3a 51 */
812
813 asm volatile("vrangess $0x12,%xmm25,%xmm26,%xmm27");
814 asm volatile("vrangesd $0x12,%xmm28,%xmm29,%xmm30");
815
816 /* AVX-512: Op code 0f 3a 54 */
817
818 asm volatile("vfixupimmps $0x12,%zmm28,%zmm29,%zmm30");
819 asm volatile("vfixupimmpd $0x12,%zmm25,%zmm26,%zmm27");
820
821 /* AVX-512: Op code 0f 3a 55 */
822
823 asm volatile("vfixupimmss $0x12,%xmm28,%xmm29,%xmm30{%k7}");
824 asm volatile("vfixupimmsd $0x12,%xmm25,%xmm26,%xmm27{%k7}");
825
826 /* AVX-512: Op code 0f 3a 56 */
827
828 asm volatile("vreduceps $0x12,%zmm26,%zmm27");
829 asm volatile("vreducepd $0x12,%zmm29,%zmm30");
830
831 /* AVX-512: Op code 0f 3a 57 */
832
833 asm volatile("vreducess $0x12,%xmm25,%xmm26,%xmm27");
834 asm volatile("vreducesd $0x12,%xmm28,%xmm29,%xmm30");
835
836 /* AVX-512: Op code 0f 3a 66 */
837
838 asm volatile("vfpclassps $0x12,%zmm27,%k5");
839 asm volatile("vfpclasspd $0x12,%zmm30,%k5");
840
841 /* AVX-512: Op code 0f 3a 67 */
842
843 asm volatile("vfpclassss $0x12,%xmm27,%k5");
844 asm volatile("vfpclasssd $0x12,%xmm30,%k5");
845
846 /* AVX-512: Op code 0f 72 (Grp13) */
847
848 asm volatile("vprord $0x12,%zmm25,%zmm26");
849 asm volatile("vprorq $0x12,%zmm25,%zmm26");
850 asm volatile("vprold $0x12,%zmm29,%zmm30");
851 asm volatile("vprolq $0x12,%zmm29,%zmm30");
852 asm volatile("psrad $0x2,%mm6");
853 asm volatile("vpsrad $0x5,%ymm6,%ymm2");
854 asm volatile("vpsrad $0x5,%zmm26,%zmm22");
855 asm volatile("vpsraq $0x5,%zmm26,%zmm22");
856
857 /* AVX-512: Op code 0f 38 c6 (Grp18) */
858
859 asm volatile("vgatherpf0dps 0x7b(%r14,%zmm31,8){%k1}");
860 asm volatile("vgatherpf0dpd 0x7b(%r14,%ymm31,8){%k1}");
861 asm volatile("vgatherpf1dps 0x7b(%r14,%zmm31,8){%k1}");
862 asm volatile("vgatherpf1dpd 0x7b(%r14,%ymm31,8){%k1}");
863 asm volatile("vscatterpf0dps 0x7b(%r14,%zmm31,8){%k1}");
864 asm volatile("vscatterpf0dpd 0x7b(%r14,%ymm31,8){%k1}");
865 asm volatile("vscatterpf1dps 0x7b(%r14,%zmm31,8){%k1}");
866 asm volatile("vscatterpf1dpd 0x7b(%r14,%ymm31,8){%k1}");
867
868 /* AVX-512: Op code 0f 38 c7 (Grp19) */
869
870 asm volatile("vgatherpf0qps 0x7b(%r14,%zmm31,8){%k1}");
871 asm volatile("vgatherpf0qpd 0x7b(%r14,%zmm31,8){%k1}");
872 asm volatile("vgatherpf1qps 0x7b(%r14,%zmm31,8){%k1}");
873 asm volatile("vgatherpf1qpd 0x7b(%r14,%zmm31,8){%k1}");
874 asm volatile("vscatterpf0qps 0x7b(%r14,%zmm31,8){%k1}");
875 asm volatile("vscatterpf0qpd 0x7b(%r14,%zmm31,8){%k1}");
876 asm volatile("vscatterpf1qps 0x7b(%r14,%zmm31,8){%k1}");
877 asm volatile("vscatterpf1qpd 0x7b(%r14,%zmm31,8){%k1}");
878
879 /* AVX-512: Examples */
880
881 asm volatile("vaddpd %zmm28,%zmm29,%zmm30");
882 asm volatile("vaddpd %zmm28,%zmm29,%zmm30{%k7}");
883 asm volatile("vaddpd %zmm28,%zmm29,%zmm30{%k7}{z}");
884 asm volatile("vaddpd {rn-sae},%zmm28,%zmm29,%zmm30");
885 asm volatile("vaddpd {ru-sae},%zmm28,%zmm29,%zmm30");
886 asm volatile("vaddpd {rd-sae},%zmm28,%zmm29,%zmm30");
887 asm volatile("vaddpd {rz-sae},%zmm28,%zmm29,%zmm30");
888 asm volatile("vaddpd (%rcx),%zmm29,%zmm30");
889 asm volatile("vaddpd 0x123(%rax,%r14,8),%zmm29,%zmm30");
890 asm volatile("vaddpd (%rcx){1to8},%zmm29,%zmm30");
891 asm volatile("vaddpd 0x1fc0(%rdx),%zmm29,%zmm30");
892 asm volatile("vaddpd 0x3f8(%rdx){1to8},%zmm29,%zmm30");
893 asm volatile("vcmpeq_uqps 0x1fc(%rdx){1to16},%zmm30,%k5");
894 asm volatile("vcmpltsd 0x123(%rax,%r14,8),%xmm29,%k5{%k7}");
895 asm volatile("vcmplesd {sae},%xmm28,%xmm29,%k5{%k7}");
896 asm volatile("vgetmantss $0x5b,0x123(%rax,%r14,8),%xmm29,%xmm30{%k7}");
897
24 /* bndmk m64, bnd */ 898 /* bndmk m64, bnd */
25 899
26 asm volatile("bndmk (%rax), %bnd0"); 900 asm volatile("bndmk (%rax), %bnd0");
@@ -471,6 +1345,921 @@ int main(void)
471 1345
472#else /* #ifdef __x86_64__ */ 1346#else /* #ifdef __x86_64__ */
473 1347
1348 /* bound r32, mem (same op code as EVEX prefix) */
1349
1350 asm volatile("bound %eax, 0x12345678(%ecx)");
1351 asm volatile("bound %ecx, 0x12345678(%eax)");
1352 asm volatile("bound %edx, 0x12345678(%eax)");
1353 asm volatile("bound %ebx, 0x12345678(%eax)");
1354 asm volatile("bound %esp, 0x12345678(%eax)");
1355 asm volatile("bound %ebp, 0x12345678(%eax)");
1356 asm volatile("bound %esi, 0x12345678(%eax)");
1357 asm volatile("bound %edi, 0x12345678(%eax)");
1358 asm volatile("bound %ecx, (%eax)");
1359 asm volatile("bound %eax, (0x12345678)");
1360 asm volatile("bound %edx, (%ecx,%eax,1)");
1361 asm volatile("bound %edx, 0x12345678(,%eax,1)");
1362 asm volatile("bound %edx, (%eax,%ecx,1)");
1363 asm volatile("bound %edx, (%eax,%ecx,8)");
1364 asm volatile("bound %edx, 0x12(%eax)");
1365 asm volatile("bound %edx, 0x12(%ebp)");
1366 asm volatile("bound %edx, 0x12(%ecx,%eax,1)");
1367 asm volatile("bound %edx, 0x12(%ebp,%eax,1)");
1368 asm volatile("bound %edx, 0x12(%eax,%ecx,1)");
1369 asm volatile("bound %edx, 0x12(%eax,%ecx,8)");
1370 asm volatile("bound %edx, 0x12345678(%eax)");
1371 asm volatile("bound %edx, 0x12345678(%ebp)");
1372 asm volatile("bound %edx, 0x12345678(%ecx,%eax,1)");
1373 asm volatile("bound %edx, 0x12345678(%ebp,%eax,1)");
1374 asm volatile("bound %edx, 0x12345678(%eax,%ecx,1)");
1375 asm volatile("bound %edx, 0x12345678(%eax,%ecx,8)");
1376
1377 /* bound r16, mem (same op code as EVEX prefix) */
1378
1379 asm volatile("bound %ax, 0x12345678(%ecx)");
1380 asm volatile("bound %cx, 0x12345678(%eax)");
1381 asm volatile("bound %dx, 0x12345678(%eax)");
1382 asm volatile("bound %bx, 0x12345678(%eax)");
1383 asm volatile("bound %sp, 0x12345678(%eax)");
1384 asm volatile("bound %bp, 0x12345678(%eax)");
1385 asm volatile("bound %si, 0x12345678(%eax)");
1386 asm volatile("bound %di, 0x12345678(%eax)");
1387 asm volatile("bound %cx, (%eax)");
1388 asm volatile("bound %ax, (0x12345678)");
1389 asm volatile("bound %dx, (%ecx,%eax,1)");
1390 asm volatile("bound %dx, 0x12345678(,%eax,1)");
1391 asm volatile("bound %dx, (%eax,%ecx,1)");
1392 asm volatile("bound %dx, (%eax,%ecx,8)");
1393 asm volatile("bound %dx, 0x12(%eax)");
1394 asm volatile("bound %dx, 0x12(%ebp)");
1395 asm volatile("bound %dx, 0x12(%ecx,%eax,1)");
1396 asm volatile("bound %dx, 0x12(%ebp,%eax,1)");
1397 asm volatile("bound %dx, 0x12(%eax,%ecx,1)");
1398 asm volatile("bound %dx, 0x12(%eax,%ecx,8)");
1399 asm volatile("bound %dx, 0x12345678(%eax)");
1400 asm volatile("bound %dx, 0x12345678(%ebp)");
1401 asm volatile("bound %dx, 0x12345678(%ecx,%eax,1)");
1402 asm volatile("bound %dx, 0x12345678(%ebp,%eax,1)");
1403 asm volatile("bound %dx, 0x12345678(%eax,%ecx,1)");
1404 asm volatile("bound %dx, 0x12345678(%eax,%ecx,8)");
1405
1406 /* AVX-512: Instructions with the same op codes as Mask Instructions */
1407
1408 asm volatile("cmovno %eax,%ebx");
1409 asm volatile("cmovno 0x12345678(%eax),%ecx");
1410 asm volatile("cmovno 0x12345678(%eax),%cx");
1411
1412 asm volatile("cmove %eax,%ebx");
1413 asm volatile("cmove 0x12345678(%eax),%ecx");
1414 asm volatile("cmove 0x12345678(%eax),%cx");
1415
1416 asm volatile("seto 0x12345678(%eax)");
1417 asm volatile("setno 0x12345678(%eax)");
1418 asm volatile("setb 0x12345678(%eax)");
1419 asm volatile("setc 0x12345678(%eax)");
1420 asm volatile("setnae 0x12345678(%eax)");
1421 asm volatile("setae 0x12345678(%eax)");
1422 asm volatile("setnb 0x12345678(%eax)");
1423 asm volatile("setnc 0x12345678(%eax)");
1424 asm volatile("sets 0x12345678(%eax)");
1425 asm volatile("setns 0x12345678(%eax)");
1426
1427 /* AVX-512: Mask Instructions */
1428
1429 asm volatile("kandw %k7,%k6,%k5");
1430 asm volatile("kandq %k7,%k6,%k5");
1431 asm volatile("kandb %k7,%k6,%k5");
1432 asm volatile("kandd %k7,%k6,%k5");
1433
1434 asm volatile("kandnw %k7,%k6,%k5");
1435 asm volatile("kandnq %k7,%k6,%k5");
1436 asm volatile("kandnb %k7,%k6,%k5");
1437 asm volatile("kandnd %k7,%k6,%k5");
1438
1439 asm volatile("knotw %k7,%k6");
1440 asm volatile("knotq %k7,%k6");
1441 asm volatile("knotb %k7,%k6");
1442 asm volatile("knotd %k7,%k6");
1443
1444 asm volatile("korw %k7,%k6,%k5");
1445 asm volatile("korq %k7,%k6,%k5");
1446 asm volatile("korb %k7,%k6,%k5");
1447 asm volatile("kord %k7,%k6,%k5");
1448
1449 asm volatile("kxnorw %k7,%k6,%k5");
1450 asm volatile("kxnorq %k7,%k6,%k5");
1451 asm volatile("kxnorb %k7,%k6,%k5");
1452 asm volatile("kxnord %k7,%k6,%k5");
1453
1454 asm volatile("kxorw %k7,%k6,%k5");
1455 asm volatile("kxorq %k7,%k6,%k5");
1456 asm volatile("kxorb %k7,%k6,%k5");
1457 asm volatile("kxord %k7,%k6,%k5");
1458
1459 asm volatile("kaddw %k7,%k6,%k5");
1460 asm volatile("kaddq %k7,%k6,%k5");
1461 asm volatile("kaddb %k7,%k6,%k5");
1462 asm volatile("kaddd %k7,%k6,%k5");
1463
1464 asm volatile("kunpckbw %k7,%k6,%k5");
1465 asm volatile("kunpckwd %k7,%k6,%k5");
1466 asm volatile("kunpckdq %k7,%k6,%k5");
1467
1468 asm volatile("kmovw %k6,%k5");
1469 asm volatile("kmovw (%ecx),%k5");
1470 asm volatile("kmovw 0x123(%eax,%ecx,8),%k5");
1471 asm volatile("kmovw %k5,(%ecx)");
1472 asm volatile("kmovw %k5,0x123(%eax,%ecx,8)");
1473 asm volatile("kmovw %eax,%k5");
1474 asm volatile("kmovw %ebp,%k5");
1475 asm volatile("kmovw %k5,%eax");
1476 asm volatile("kmovw %k5,%ebp");
1477
1478 asm volatile("kmovq %k6,%k5");
1479 asm volatile("kmovq (%ecx),%k5");
1480 asm volatile("kmovq 0x123(%eax,%ecx,8),%k5");
1481 asm volatile("kmovq %k5,(%ecx)");
1482 asm volatile("kmovq %k5,0x123(%eax,%ecx,8)");
1483
1484 asm volatile("kmovb %k6,%k5");
1485 asm volatile("kmovb (%ecx),%k5");
1486 asm volatile("kmovb 0x123(%eax,%ecx,8),%k5");
1487 asm volatile("kmovb %k5,(%ecx)");
1488 asm volatile("kmovb %k5,0x123(%eax,%ecx,8)");
1489 asm volatile("kmovb %eax,%k5");
1490 asm volatile("kmovb %ebp,%k5");
1491 asm volatile("kmovb %k5,%eax");
1492 asm volatile("kmovb %k5,%ebp");
1493
1494 asm volatile("kmovd %k6,%k5");
1495 asm volatile("kmovd (%ecx),%k5");
1496 asm volatile("kmovd 0x123(%eax,%ecx,8),%k5");
1497 asm volatile("kmovd %k5,(%ecx)");
1498 asm volatile("kmovd %k5,0x123(%eax,%ecx,8)");
1499 asm volatile("kmovd %eax,%k5");
1500 asm volatile("kmovd %ebp,%k5");
1501 asm volatile("kmovd %k5,%eax");
1502 asm volatile("kmovd %k5,%ebp");
1503
1504 asm volatile("kortestw %k6,%k5");
1505 asm volatile("kortestq %k6,%k5");
1506 asm volatile("kortestb %k6,%k5");
1507 asm volatile("kortestd %k6,%k5");
1508
1509 asm volatile("ktestw %k6,%k5");
1510 asm volatile("ktestq %k6,%k5");
1511 asm volatile("ktestb %k6,%k5");
1512 asm volatile("ktestd %k6,%k5");
1513
1514 asm volatile("kshiftrw $0x12,%k6,%k5");
1515 asm volatile("kshiftrq $0x5b,%k6,%k5");
1516 asm volatile("kshiftlw $0x12,%k6,%k5");
1517 asm volatile("kshiftlq $0x5b,%k6,%k5");
1518
1519 /* AVX-512: Op code 0f 5b */
1520 asm volatile("vcvtdq2ps %xmm5,%xmm6");
1521 asm volatile("vcvtqq2ps %zmm5,%ymm6{%k7}");
1522 asm volatile("vcvtps2dq %xmm5,%xmm6");
1523 asm volatile("vcvttps2dq %xmm5,%xmm6");
1524
1525 /* AVX-512: Op code 0f 6f */
1526
1527 asm volatile("movq %mm0,%mm4");
1528 asm volatile("vmovdqa %ymm4,%ymm6");
1529 asm volatile("vmovdqa32 %zmm5,%zmm6");
1530 asm volatile("vmovdqa64 %zmm5,%zmm6");
1531 asm volatile("vmovdqu %ymm4,%ymm6");
1532 asm volatile("vmovdqu32 %zmm5,%zmm6");
1533 asm volatile("vmovdqu64 %zmm5,%zmm6");
1534 asm volatile("vmovdqu8 %zmm5,%zmm6");
1535 asm volatile("vmovdqu16 %zmm5,%zmm6");
1536
1537 /* AVX-512: Op code 0f 78 */
1538
1539 asm volatile("vmread %eax,%ebx");
1540 asm volatile("vcvttps2udq %zmm5,%zmm6");
1541 asm volatile("vcvttpd2udq %zmm5,%ymm6{%k7}");
1542 asm volatile("vcvttsd2usi %xmm6,%eax");
1543 asm volatile("vcvttss2usi %xmm6,%eax");
1544 asm volatile("vcvttps2uqq %ymm5,%zmm6{%k7}");
1545 asm volatile("vcvttpd2uqq %zmm5,%zmm6");
1546
1547 /* AVX-512: Op code 0f 79 */
1548
1549 asm volatile("vmwrite %eax,%ebx");
1550 asm volatile("vcvtps2udq %zmm5,%zmm6");
1551 asm volatile("vcvtpd2udq %zmm5,%ymm6{%k7}");
1552 asm volatile("vcvtsd2usi %xmm6,%eax");
1553 asm volatile("vcvtss2usi %xmm6,%eax");
1554 asm volatile("vcvtps2uqq %ymm5,%zmm6{%k7}");
1555 asm volatile("vcvtpd2uqq %zmm5,%zmm6");
1556
1557 /* AVX-512: Op code 0f 7a */
1558
1559 asm volatile("vcvtudq2pd %ymm5,%zmm6{%k7}");
1560 asm volatile("vcvtuqq2pd %zmm5,%zmm6");
1561 asm volatile("vcvtudq2ps %zmm5,%zmm6");
1562 asm volatile("vcvtuqq2ps %zmm5,%ymm6{%k7}");
1563 asm volatile("vcvttps2qq %ymm5,%zmm6{%k7}");
1564 asm volatile("vcvttpd2qq %zmm5,%zmm6");
1565
1566 /* AVX-512: Op code 0f 7b */
1567
1568 asm volatile("vcvtusi2sd %eax,%xmm5,%xmm6");
1569 asm volatile("vcvtusi2ss %eax,%xmm5,%xmm6");
1570 asm volatile("vcvtps2qq %ymm5,%zmm6{%k7}");
1571 asm volatile("vcvtpd2qq %zmm5,%zmm6");
1572
1573 /* AVX-512: Op code 0f 7f */
1574
1575 asm volatile("movq.s %mm0,%mm4");
1576 asm volatile("vmovdqa.s %ymm5,%ymm6");
1577 asm volatile("vmovdqa32.s %zmm5,%zmm6");
1578 asm volatile("vmovdqa64.s %zmm5,%zmm6");
1579 asm volatile("vmovdqu.s %ymm5,%ymm6");
1580 asm volatile("vmovdqu32.s %zmm5,%zmm6");
1581 asm volatile("vmovdqu64.s %zmm5,%zmm6");
1582 asm volatile("vmovdqu8.s %zmm5,%zmm6");
1583 asm volatile("vmovdqu16.s %zmm5,%zmm6");
1584
1585 /* AVX-512: Op code 0f db */
1586
1587 asm volatile("pand %mm1,%mm2");
1588 asm volatile("pand %xmm1,%xmm2");
1589 asm volatile("vpand %ymm4,%ymm6,%ymm2");
1590 asm volatile("vpandd %zmm4,%zmm5,%zmm6");
1591 asm volatile("vpandq %zmm4,%zmm5,%zmm6");
1592
1593 /* AVX-512: Op code 0f df */
1594
1595 asm volatile("pandn %mm1,%mm2");
1596 asm volatile("pandn %xmm1,%xmm2");
1597 asm volatile("vpandn %ymm4,%ymm6,%ymm2");
1598 asm volatile("vpandnd %zmm4,%zmm5,%zmm6");
1599 asm volatile("vpandnq %zmm4,%zmm5,%zmm6");
1600
1601 /* AVX-512: Op code 0f e6 */
1602
1603 asm volatile("vcvttpd2dq %xmm1,%xmm2");
1604 asm volatile("vcvtdq2pd %xmm5,%xmm6");
1605 asm volatile("vcvtdq2pd %ymm5,%zmm6{%k7}");
1606 asm volatile("vcvtqq2pd %zmm5,%zmm6");
1607 asm volatile("vcvtpd2dq %xmm1,%xmm2");
1608
1609 /* AVX-512: Op code 0f eb */
1610
1611 asm volatile("por %mm4,%mm6");
1612 asm volatile("vpor %ymm4,%ymm6,%ymm2");
1613 asm volatile("vpord %zmm4,%zmm5,%zmm6");
1614 asm volatile("vporq %zmm4,%zmm5,%zmm6");
1615
1616 /* AVX-512: Op code 0f ef */
1617
1618 asm volatile("pxor %mm4,%mm6");
1619 asm volatile("vpxor %ymm4,%ymm6,%ymm2");
1620 asm volatile("vpxord %zmm4,%zmm5,%zmm6");
1621 asm volatile("vpxorq %zmm4,%zmm5,%zmm6");
1622
1623 /* AVX-512: Op code 0f 38 10 */
1624
1625 asm volatile("pblendvb %xmm1,%xmm0");
1626 asm volatile("vpsrlvw %zmm4,%zmm5,%zmm6");
1627 asm volatile("vpmovuswb %zmm5,%ymm6{%k7}");
1628
1629 /* AVX-512: Op code 0f 38 11 */
1630
1631 asm volatile("vpmovusdb %zmm5,%xmm6{%k7}");
1632 asm volatile("vpsravw %zmm4,%zmm5,%zmm6");
1633
1634 /* AVX-512: Op code 0f 38 12 */
1635
1636 asm volatile("vpmovusqb %zmm5,%xmm6{%k7}");
1637 asm volatile("vpsllvw %zmm4,%zmm5,%zmm6");
1638
1639 /* AVX-512: Op code 0f 38 13 */
1640
1641 asm volatile("vcvtph2ps %xmm3,%ymm5");
1642 asm volatile("vcvtph2ps %ymm5,%zmm6{%k7}");
1643 asm volatile("vpmovusdw %zmm5,%ymm6{%k7}");
1644
1645 /* AVX-512: Op code 0f 38 14 */
1646
1647 asm volatile("blendvps %xmm1,%xmm0");
1648 asm volatile("vpmovusqw %zmm5,%xmm6{%k7}");
1649 asm volatile("vprorvd %zmm4,%zmm5,%zmm6");
1650 asm volatile("vprorvq %zmm4,%zmm5,%zmm6");
1651
1652 /* AVX-512: Op code 0f 38 15 */
1653
1654 asm volatile("blendvpd %xmm1,%xmm0");
1655 asm volatile("vpmovusqd %zmm5,%ymm6{%k7}");
1656 asm volatile("vprolvd %zmm4,%zmm5,%zmm6");
1657 asm volatile("vprolvq %zmm4,%zmm5,%zmm6");
1658
1659 /* AVX-512: Op code 0f 38 16 */
1660
1661 asm volatile("vpermps %ymm4,%ymm6,%ymm2");
1662 asm volatile("vpermps %ymm4,%ymm6,%ymm2{%k7}");
1663 asm volatile("vpermpd %ymm4,%ymm6,%ymm2{%k7}");
1664
1665 /* AVX-512: Op code 0f 38 19 */
1666
1667 asm volatile("vbroadcastsd %xmm4,%ymm6");
1668 asm volatile("vbroadcastf32x2 %xmm7,%zmm6");
1669
1670 /* AVX-512: Op code 0f 38 1a */
1671
1672 asm volatile("vbroadcastf128 (%ecx),%ymm4");
1673 asm volatile("vbroadcastf32x4 (%ecx),%zmm6");
1674 asm volatile("vbroadcastf64x2 (%ecx),%zmm6");
1675
1676 /* AVX-512: Op code 0f 38 1b */
1677
1678 asm volatile("vbroadcastf32x8 (%ecx),%zmm6");
1679 asm volatile("vbroadcastf64x4 (%ecx),%zmm6");
1680
1681 /* AVX-512: Op code 0f 38 1f */
1682
1683 asm volatile("vpabsq %zmm4,%zmm6");
1684
1685 /* AVX-512: Op code 0f 38 20 */
1686
1687 asm volatile("vpmovsxbw %xmm4,%xmm5");
1688 asm volatile("vpmovswb %zmm5,%ymm6{%k7}");
1689
1690 /* AVX-512: Op code 0f 38 21 */
1691
1692 asm volatile("vpmovsxbd %xmm4,%ymm6");
1693 asm volatile("vpmovsdb %zmm5,%xmm6{%k7}");
1694
1695 /* AVX-512: Op code 0f 38 22 */
1696
1697 asm volatile("vpmovsxbq %xmm4,%ymm4");
1698 asm volatile("vpmovsqb %zmm5,%xmm6{%k7}");
1699
1700 /* AVX-512: Op code 0f 38 23 */
1701
1702 asm volatile("vpmovsxwd %xmm4,%ymm4");
1703 asm volatile("vpmovsdw %zmm5,%ymm6{%k7}");
1704
1705 /* AVX-512: Op code 0f 38 24 */
1706
1707 asm volatile("vpmovsxwq %xmm4,%ymm6");
1708 asm volatile("vpmovsqw %zmm5,%xmm6{%k7}");
1709
1710 /* AVX-512: Op code 0f 38 25 */
1711
1712 asm volatile("vpmovsxdq %xmm4,%ymm4");
1713 asm volatile("vpmovsqd %zmm5,%ymm6{%k7}");
1714
1715 /* AVX-512: Op code 0f 38 26 */
1716
1717 asm volatile("vptestmb %zmm5,%zmm6,%k5");
1718 asm volatile("vptestmw %zmm5,%zmm6,%k5");
1719 asm volatile("vptestnmb %zmm4,%zmm5,%k5");
1720 asm volatile("vptestnmw %zmm4,%zmm5,%k5");
1721
1722 /* AVX-512: Op code 0f 38 27 */
1723
1724 asm volatile("vptestmd %zmm5,%zmm6,%k5");
1725 asm volatile("vptestmq %zmm5,%zmm6,%k5");
1726 asm volatile("vptestnmd %zmm4,%zmm5,%k5");
1727 asm volatile("vptestnmq %zmm4,%zmm5,%k5");
1728
1729 /* AVX-512: Op code 0f 38 28 */
1730
1731 asm volatile("vpmuldq %ymm4,%ymm6,%ymm2");
1732 asm volatile("vpmovm2b %k5,%zmm6");
1733 asm volatile("vpmovm2w %k5,%zmm6");
1734
1735 /* AVX-512: Op code 0f 38 29 */
1736
1737 asm volatile("vpcmpeqq %ymm4,%ymm6,%ymm2");
1738 asm volatile("vpmovb2m %zmm6,%k5");
1739 asm volatile("vpmovw2m %zmm6,%k5");
1740
1741 /* AVX-512: Op code 0f 38 2a */
1742
1743 asm volatile("vmovntdqa (%ecx),%ymm4");
1744 asm volatile("vpbroadcastmb2q %k6,%zmm1");
1745
1746 /* AVX-512: Op code 0f 38 2c */
1747
1748 asm volatile("vmaskmovps (%ecx),%ymm4,%ymm6");
1749 asm volatile("vscalefps %zmm4,%zmm5,%zmm6");
1750 asm volatile("vscalefpd %zmm4,%zmm5,%zmm6");
1751
1752 /* AVX-512: Op code 0f 38 2d */
1753
1754 asm volatile("vmaskmovpd (%ecx),%ymm4,%ymm6");
1755 asm volatile("vscalefss %xmm4,%xmm5,%xmm6{%k7}");
1756 asm volatile("vscalefsd %xmm4,%xmm5,%xmm6{%k7}");
1757
1758 /* AVX-512: Op code 0f 38 30 */
1759
1760 asm volatile("vpmovzxbw %xmm4,%ymm4");
1761 asm volatile("vpmovwb %zmm5,%ymm6{%k7}");
1762
1763 /* AVX-512: Op code 0f 38 31 */
1764
1765 asm volatile("vpmovzxbd %xmm4,%ymm6");
1766 asm volatile("vpmovdb %zmm5,%xmm6{%k7}");
1767
1768 /* AVX-512: Op code 0f 38 32 */
1769
1770 asm volatile("vpmovzxbq %xmm4,%ymm4");
1771 asm volatile("vpmovqb %zmm5,%xmm6{%k7}");
1772
1773 /* AVX-512: Op code 0f 38 33 */
1774
1775 asm volatile("vpmovzxwd %xmm4,%ymm4");
1776 asm volatile("vpmovdw %zmm5,%ymm6{%k7}");
1777
1778 /* AVX-512: Op code 0f 38 34 */
1779
1780 asm volatile("vpmovzxwq %xmm4,%ymm6");
1781 asm volatile("vpmovqw %zmm5,%xmm6{%k7}");
1782
1783 /* AVX-512: Op code 0f 38 35 */
1784
1785 asm volatile("vpmovzxdq %xmm4,%ymm4");
1786 asm volatile("vpmovqd %zmm5,%ymm6{%k7}");
1787
1788 /* AVX-512: Op code 0f 38 36 */
1789
1790 asm volatile("vpermd %ymm4,%ymm6,%ymm2");
1791 asm volatile("vpermd %ymm4,%ymm6,%ymm2{%k7}");
1792 asm volatile("vpermq %ymm4,%ymm6,%ymm2{%k7}");
1793
1794 /* AVX-512: Op code 0f 38 38 */
1795
1796 asm volatile("vpminsb %ymm4,%ymm6,%ymm2");
1797 asm volatile("vpmovm2d %k5,%zmm6");
1798 asm volatile("vpmovm2q %k5,%zmm6");
1799
1800 /* AVX-512: Op code 0f 38 39 */
1801
1802 asm volatile("vpminsd %xmm1,%xmm2,%xmm3");
1803 asm volatile("vpminsd %zmm4,%zmm5,%zmm6");
1804 asm volatile("vpminsq %zmm4,%zmm5,%zmm6");
1805 asm volatile("vpmovd2m %zmm6,%k5");
1806 asm volatile("vpmovq2m %zmm6,%k5");
1807
1808 /* AVX-512: Op code 0f 38 3a */
1809
1810 asm volatile("vpminuw %ymm4,%ymm6,%ymm2");
1811 asm volatile("vpbroadcastmw2d %k6,%zmm6");
1812
1813 /* AVX-512: Op code 0f 38 3b */
1814
1815 asm volatile("vpminud %ymm4,%ymm6,%ymm2");
1816 asm volatile("vpminud %zmm4,%zmm5,%zmm6");
1817 asm volatile("vpminuq %zmm4,%zmm5,%zmm6");
1818
1819 /* AVX-512: Op code 0f 38 3d */
1820
1821 asm volatile("vpmaxsd %ymm4,%ymm6,%ymm2");
1822 asm volatile("vpmaxsd %zmm4,%zmm5,%zmm6");
1823 asm volatile("vpmaxsq %zmm4,%zmm5,%zmm6");
1824
1825 /* AVX-512: Op code 0f 38 3f */
1826
1827 asm volatile("vpmaxud %ymm4,%ymm6,%ymm2");
1828 asm volatile("vpmaxud %zmm4,%zmm5,%zmm6");
1829 asm volatile("vpmaxuq %zmm4,%zmm5,%zmm6");
1830
1831 /* AVX-512: Op code 0f 38 40 */
1832
1833 asm volatile("vpmulld %ymm4,%ymm6,%ymm2");
1834 asm volatile("vpmulld %zmm4,%zmm5,%zmm6");
1835 asm volatile("vpmullq %zmm4,%zmm5,%zmm6");
1836
1837 /* AVX-512: Op code 0f 38 42 */
1838
1839 asm volatile("vgetexpps %zmm5,%zmm6");
1840 asm volatile("vgetexppd %zmm5,%zmm6");
1841
1842 /* AVX-512: Op code 0f 38 43 */
1843
1844 asm volatile("vgetexpss %xmm4,%xmm5,%xmm6{%k7}");
1845 asm volatile("vgetexpsd %xmm2,%xmm3,%xmm4{%k7}");
1846
1847 /* AVX-512: Op code 0f 38 44 */
1848
1849 asm volatile("vplzcntd %zmm5,%zmm6");
1850 asm volatile("vplzcntq %zmm5,%zmm6");
1851
1852 /* AVX-512: Op code 0f 38 46 */
1853
1854 asm volatile("vpsravd %ymm4,%ymm6,%ymm2");
1855 asm volatile("vpsravd %zmm4,%zmm5,%zmm6");
1856 asm volatile("vpsravq %zmm4,%zmm5,%zmm6");
1857
1858 /* AVX-512: Op code 0f 38 4c */
1859
1860 asm volatile("vrcp14ps %zmm5,%zmm6");
1861 asm volatile("vrcp14pd %zmm5,%zmm6");
1862
1863 /* AVX-512: Op code 0f 38 4d */
1864
1865 asm volatile("vrcp14ss %xmm4,%xmm5,%xmm6{%k7}");
1866 asm volatile("vrcp14sd %xmm4,%xmm5,%xmm6{%k7}");
1867
1868 /* AVX-512: Op code 0f 38 4e */
1869
1870 asm volatile("vrsqrt14ps %zmm5,%zmm6");
1871 asm volatile("vrsqrt14pd %zmm5,%zmm6");
1872
1873 /* AVX-512: Op code 0f 38 4f */
1874
1875 asm volatile("vrsqrt14ss %xmm4,%xmm5,%xmm6{%k7}");
1876 asm volatile("vrsqrt14sd %xmm4,%xmm5,%xmm6{%k7}");
1877
1878 /* AVX-512: Op code 0f 38 59 */
1879
1880 asm volatile("vpbroadcastq %xmm4,%xmm6");
1881 asm volatile("vbroadcasti32x2 %xmm7,%zmm6");
1882
1883 /* AVX-512: Op code 0f 38 5a */
1884
1885 asm volatile("vbroadcasti128 (%ecx),%ymm4");
1886 asm volatile("vbroadcasti32x4 (%ecx),%zmm6");
1887 asm volatile("vbroadcasti64x2 (%ecx),%zmm6");
1888
1889 /* AVX-512: Op code 0f 38 5b */
1890
1891 asm volatile("vbroadcasti32x8 (%ecx),%zmm6");
1892 asm volatile("vbroadcasti64x4 (%ecx),%zmm6");
1893
1894 /* AVX-512: Op code 0f 38 64 */
1895
1896 asm volatile("vpblendmd %zmm4,%zmm5,%zmm6");
1897 asm volatile("vpblendmq %zmm4,%zmm5,%zmm6");
1898
1899 /* AVX-512: Op code 0f 38 65 */
1900
1901 asm volatile("vblendmps %zmm4,%zmm5,%zmm6");
1902 asm volatile("vblendmpd %zmm4,%zmm5,%zmm6");
1903
1904 /* AVX-512: Op code 0f 38 66 */
1905
1906 asm volatile("vpblendmb %zmm4,%zmm5,%zmm6");
1907 asm volatile("vpblendmw %zmm4,%zmm5,%zmm6");
1908
1909 /* AVX-512: Op code 0f 38 75 */
1910
1911 asm volatile("vpermi2b %zmm4,%zmm5,%zmm6");
1912 asm volatile("vpermi2w %zmm4,%zmm5,%zmm6");
1913
1914 /* AVX-512: Op code 0f 38 76 */
1915
1916 asm volatile("vpermi2d %zmm4,%zmm5,%zmm6");
1917 asm volatile("vpermi2q %zmm4,%zmm5,%zmm6");
1918
1919 /* AVX-512: Op code 0f 38 77 */
1920
1921 asm volatile("vpermi2ps %zmm4,%zmm5,%zmm6");
1922 asm volatile("vpermi2pd %zmm4,%zmm5,%zmm6");
1923
1924 /* AVX-512: Op code 0f 38 7a */
1925
1926 asm volatile("vpbroadcastb %eax,%xmm3");
1927
1928 /* AVX-512: Op code 0f 38 7b */
1929
1930 asm volatile("vpbroadcastw %eax,%xmm3");
1931
1932 /* AVX-512: Op code 0f 38 7c */
1933
1934 asm volatile("vpbroadcastd %eax,%xmm3");
1935
1936 /* AVX-512: Op code 0f 38 7d */
1937
1938 asm volatile("vpermt2b %zmm4,%zmm5,%zmm6");
1939 asm volatile("vpermt2w %zmm4,%zmm5,%zmm6");
1940
1941 /* AVX-512: Op code 0f 38 7e */
1942
1943 asm volatile("vpermt2d %zmm4,%zmm5,%zmm6");
1944 asm volatile("vpermt2q %zmm4,%zmm5,%zmm6");
1945
1946 /* AVX-512: Op code 0f 38 7f */
1947
1948 asm volatile("vpermt2ps %zmm4,%zmm5,%zmm6");
1949 asm volatile("vpermt2pd %zmm4,%zmm5,%zmm6");
1950
1951 /* AVX-512: Op code 0f 38 83 */
1952
1953 asm volatile("vpmultishiftqb %zmm4,%zmm5,%zmm6");
1954
1955 /* AVX-512: Op code 0f 38 88 */
1956
1957 asm volatile("vexpandps (%ecx),%zmm6");
1958 asm volatile("vexpandpd (%ecx),%zmm6");
1959
1960 /* AVX-512: Op code 0f 38 89 */
1961
1962 asm volatile("vpexpandd (%ecx),%zmm6");
1963 asm volatile("vpexpandq (%ecx),%zmm6");
1964
1965 /* AVX-512: Op code 0f 38 8a */
1966
1967 asm volatile("vcompressps %zmm6,(%ecx)");
1968 asm volatile("vcompresspd %zmm6,(%ecx)");
1969
1970 /* AVX-512: Op code 0f 38 8b */
1971
1972 asm volatile("vpcompressd %zmm6,(%ecx)");
1973 asm volatile("vpcompressq %zmm6,(%ecx)");
1974
1975 /* AVX-512: Op code 0f 38 8d */
1976
1977 asm volatile("vpermb %zmm4,%zmm5,%zmm6");
1978 asm volatile("vpermw %zmm4,%zmm5,%zmm6");
1979
1980 /* AVX-512: Op code 0f 38 90 */
1981
1982 asm volatile("vpgatherdd %xmm2,0x02(%ebp,%xmm7,2),%xmm1");
1983 asm volatile("vpgatherdq %xmm2,0x04(%ebp,%xmm7,2),%xmm1");
1984 asm volatile("vpgatherdd 0x7b(%ebp,%zmm7,8),%zmm6{%k1}");
1985 asm volatile("vpgatherdq 0x7b(%ebp,%ymm7,8),%zmm6{%k1}");
1986
1987 /* AVX-512: Op code 0f 38 91 */
1988
1989 asm volatile("vpgatherqd %xmm2,0x02(%ebp,%xmm7,2),%xmm1");
1990 asm volatile("vpgatherqq %xmm2,0x02(%ebp,%xmm7,2),%xmm1");
1991 asm volatile("vpgatherqd 0x7b(%ebp,%zmm7,8),%ymm6{%k1}");
1992 asm volatile("vpgatherqq 0x7b(%ebp,%zmm7,8),%zmm6{%k1}");
1993
1994 /* AVX-512: Op code 0f 38 a0 */
1995
1996 asm volatile("vpscatterdd %zmm6,0x7b(%ebp,%zmm7,8){%k1}");
1997 asm volatile("vpscatterdq %zmm6,0x7b(%ebp,%ymm7,8){%k1}");
1998
1999 /* AVX-512: Op code 0f 38 a1 */
2000
2001 asm volatile("vpscatterqd %ymm6,0x7b(%ebp,%zmm7,8){%k1}");
2002 asm volatile("vpscatterqq %ymm6,0x7b(%ebp,%ymm7,8){%k1}");
2003
2004 /* AVX-512: Op code 0f 38 a2 */
2005
2006 asm volatile("vscatterdps %zmm6,0x7b(%ebp,%zmm7,8){%k1}");
2007 asm volatile("vscatterdpd %zmm6,0x7b(%ebp,%ymm7,8){%k1}");
2008
2009 /* AVX-512: Op code 0f 38 a3 */
2010
2011 asm volatile("vscatterqps %ymm6,0x7b(%ebp,%zmm7,8){%k1}");
2012 asm volatile("vscatterqpd %zmm6,0x7b(%ebp,%zmm7,8){%k1}");
2013
2014 /* AVX-512: Op code 0f 38 b4 */
2015
2016 asm volatile("vpmadd52luq %zmm4,%zmm5,%zmm6");
2017
2018 /* AVX-512: Op code 0f 38 b5 */
2019
2020 asm volatile("vpmadd52huq %zmm4,%zmm5,%zmm6");
2021
2022 /* AVX-512: Op code 0f 38 c4 */
2023
2024 asm volatile("vpconflictd %zmm5,%zmm6");
2025 asm volatile("vpconflictq %zmm5,%zmm6");
2026
2027 /* AVX-512: Op code 0f 38 c8 */
2028
2029 asm volatile("vexp2ps %zmm6,%zmm7");
2030 asm volatile("vexp2pd %zmm6,%zmm7");
2031
2032 /* AVX-512: Op code 0f 38 ca */
2033
2034 asm volatile("vrcp28ps %zmm6,%zmm7");
2035 asm volatile("vrcp28pd %zmm6,%zmm7");
2036
2037 /* AVX-512: Op code 0f 38 cb */
2038
2039 asm volatile("vrcp28ss %xmm5,%xmm6,%xmm7{%k7}");
2040 asm volatile("vrcp28sd %xmm5,%xmm6,%xmm7{%k7}");
2041
2042 /* AVX-512: Op code 0f 38 cc */
2043
2044 asm volatile("vrsqrt28ps %zmm6,%zmm7");
2045 asm volatile("vrsqrt28pd %zmm6,%zmm7");
2046
2047 /* AVX-512: Op code 0f 38 cd */
2048
2049 asm volatile("vrsqrt28ss %xmm5,%xmm6,%xmm7{%k7}");
2050 asm volatile("vrsqrt28sd %xmm5,%xmm6,%xmm7{%k7}");
2051
2052 /* AVX-512: Op code 0f 3a 03 */
2053
2054 asm volatile("valignd $0x12,%zmm5,%zmm6,%zmm7");
2055 asm volatile("valignq $0x12,%zmm5,%zmm6,%zmm7");
2056
2057 /* AVX-512: Op code 0f 3a 08 */
2058
2059 asm volatile("vroundps $0x5,%ymm6,%ymm2");
2060 asm volatile("vrndscaleps $0x12,%zmm5,%zmm6");
2061
2062 /* AVX-512: Op code 0f 3a 09 */
2063
2064 asm volatile("vroundpd $0x5,%ymm6,%ymm2");
2065 asm volatile("vrndscalepd $0x12,%zmm5,%zmm6");
2066
2067 /* AVX-512: Op code 0f 3a 0a */
2068
2069 asm volatile("vroundss $0x5,%xmm4,%xmm6,%xmm2");
2070 asm volatile("vrndscaless $0x12,%xmm4,%xmm5,%xmm6{%k7}");
2071
2072 /* AVX-512: Op code 0f 3a 0b */
2073
2074 asm volatile("vroundsd $0x5,%xmm4,%xmm6,%xmm2");
2075 asm volatile("vrndscalesd $0x12,%xmm4,%xmm5,%xmm6{%k7}");
2076
2077 /* AVX-512: Op code 0f 3a 18 */
2078
2079 asm volatile("vinsertf128 $0x5,%xmm4,%ymm4,%ymm6");
2080 asm volatile("vinsertf32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}");
2081 asm volatile("vinsertf64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}");
2082
2083 /* AVX-512: Op code 0f 3a 19 */
2084
2085 asm volatile("vextractf128 $0x5,%ymm4,%xmm4");
2086 asm volatile("vextractf32x4 $0x12,%zmm5,%xmm6{%k7}");
2087 asm volatile("vextractf64x2 $0x12,%zmm5,%xmm6{%k7}");
2088
2089 /* AVX-512: Op code 0f 3a 1a */
2090
2091 asm volatile("vinsertf32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}");
2092 asm volatile("vinsertf64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}");
2093
2094 /* AVX-512: Op code 0f 3a 1b */
2095
2096 asm volatile("vextractf32x8 $0x12,%zmm6,%ymm7{%k7}");
2097 asm volatile("vextractf64x4 $0x12,%zmm6,%ymm7{%k7}");
2098
2099 /* AVX-512: Op code 0f 3a 1e */
2100
2101 asm volatile("vpcmpud $0x12,%zmm6,%zmm7,%k5");
2102 asm volatile("vpcmpuq $0x12,%zmm6,%zmm7,%k5");
2103
2104 /* AVX-512: Op code 0f 3a 1f */
2105
2106 asm volatile("vpcmpd $0x12,%zmm6,%zmm7,%k5");
2107 asm volatile("vpcmpq $0x12,%zmm6,%zmm7,%k5");
2108
2109 /* AVX-512: Op code 0f 3a 23 */
2110
2111 asm volatile("vshuff32x4 $0x12,%zmm5,%zmm6,%zmm7");
2112 asm volatile("vshuff64x2 $0x12,%zmm5,%zmm6,%zmm7");
2113
2114 /* AVX-512: Op code 0f 3a 25 */
2115
2116 asm volatile("vpternlogd $0x12,%zmm5,%zmm6,%zmm7");
2117 asm volatile("vpternlogq $0x12,%zmm5,%zmm6,%zmm7");
2118
2119 /* AVX-512: Op code 0f 3a 26 */
2120
2121 asm volatile("vgetmantps $0x12,%zmm6,%zmm7");
2122 asm volatile("vgetmantpd $0x12,%zmm6,%zmm7");
2123
2124 /* AVX-512: Op code 0f 3a 27 */
2125
2126 asm volatile("vgetmantss $0x12,%xmm5,%xmm6,%xmm7{%k7}");
2127 asm volatile("vgetmantsd $0x12,%xmm5,%xmm6,%xmm7{%k7}");
2128
2129 /* AVX-512: Op code 0f 3a 38 */
2130
2131 asm volatile("vinserti128 $0x5,%xmm4,%ymm4,%ymm6");
2132 asm volatile("vinserti32x4 $0x12,%xmm4,%zmm5,%zmm6{%k7}");
2133 asm volatile("vinserti64x2 $0x12,%xmm4,%zmm5,%zmm6{%k7}");
2134
2135 /* AVX-512: Op code 0f 3a 39 */
2136
2137 asm volatile("vextracti128 $0x5,%ymm4,%xmm6");
2138 asm volatile("vextracti32x4 $0x12,%zmm5,%xmm6{%k7}");
2139 asm volatile("vextracti64x2 $0x12,%zmm5,%xmm6{%k7}");
2140
2141 /* AVX-512: Op code 0f 3a 3a */
2142
2143 asm volatile("vinserti32x8 $0x12,%ymm5,%zmm6,%zmm7{%k7}");
2144 asm volatile("vinserti64x4 $0x12,%ymm5,%zmm6,%zmm7{%k7}");
2145
2146 /* AVX-512: Op code 0f 3a 3b */
2147
2148 asm volatile("vextracti32x8 $0x12,%zmm6,%ymm7{%k7}");
2149 asm volatile("vextracti64x4 $0x12,%zmm6,%ymm7{%k7}");
2150
2151 /* AVX-512: Op code 0f 3a 3e */
2152
2153 asm volatile("vpcmpub $0x12,%zmm6,%zmm7,%k5");
2154 asm volatile("vpcmpuw $0x12,%zmm6,%zmm7,%k5");
2155
2156 /* AVX-512: Op code 0f 3a 3f */
2157
2158 asm volatile("vpcmpb $0x12,%zmm6,%zmm7,%k5");
2159 asm volatile("vpcmpw $0x12,%zmm6,%zmm7,%k5");
2160
2161 /* AVX-512: Op code 0f 3a 42 */
2162
2163 asm volatile("vmpsadbw $0x5,%ymm4,%ymm6,%ymm2");
2164 asm volatile("vdbpsadbw $0x12,%zmm4,%zmm5,%zmm6");
2165
2166 /* AVX-512: Op code 0f 3a 43 */
2167
2168 asm volatile("vshufi32x4 $0x12,%zmm5,%zmm6,%zmm7");
2169 asm volatile("vshufi64x2 $0x12,%zmm5,%zmm6,%zmm7");
2170
2171 /* AVX-512: Op code 0f 3a 50 */
2172
2173 asm volatile("vrangeps $0x12,%zmm5,%zmm6,%zmm7");
2174 asm volatile("vrangepd $0x12,%zmm5,%zmm6,%zmm7");
2175
2176 /* AVX-512: Op code 0f 3a 51 */
2177
2178 asm volatile("vrangess $0x12,%xmm5,%xmm6,%xmm7");
2179 asm volatile("vrangesd $0x12,%xmm5,%xmm6,%xmm7");
2180
2181 /* AVX-512: Op code 0f 3a 54 */
2182
2183 asm volatile("vfixupimmps $0x12,%zmm5,%zmm6,%zmm7");
2184 asm volatile("vfixupimmpd $0x12,%zmm5,%zmm6,%zmm7");
2185
2186 /* AVX-512: Op code 0f 3a 55 */
2187
2188 asm volatile("vfixupimmss $0x12,%xmm5,%xmm6,%xmm7{%k7}");
2189 asm volatile("vfixupimmsd $0x12,%xmm5,%xmm6,%xmm7{%k7}");
2190
2191 /* AVX-512: Op code 0f 3a 56 */
2192
2193 asm volatile("vreduceps $0x12,%zmm6,%zmm7");
2194 asm volatile("vreducepd $0x12,%zmm6,%zmm7");
2195
2196 /* AVX-512: Op code 0f 3a 57 */
2197
2198 asm volatile("vreducess $0x12,%xmm5,%xmm6,%xmm7");
2199 asm volatile("vreducesd $0x12,%xmm5,%xmm6,%xmm7");
2200
2201 /* AVX-512: Op code 0f 3a 66 */
2202
2203 asm volatile("vfpclassps $0x12,%zmm7,%k5");
2204 asm volatile("vfpclasspd $0x12,%zmm7,%k5");
2205
2206 /* AVX-512: Op code 0f 3a 67 */
2207
2208 asm volatile("vfpclassss $0x12,%xmm7,%k5");
2209 asm volatile("vfpclasssd $0x12,%xmm7,%k5");
2210
2211 /* AVX-512: Op code 0f 72 (Grp13) */
2212
2213 asm volatile("vprord $0x12,%zmm5,%zmm6");
2214 asm volatile("vprorq $0x12,%zmm5,%zmm6");
2215 asm volatile("vprold $0x12,%zmm5,%zmm6");
2216 asm volatile("vprolq $0x12,%zmm5,%zmm6");
2217 asm volatile("psrad $0x2,%mm6");
2218 asm volatile("vpsrad $0x5,%ymm6,%ymm2");
2219 asm volatile("vpsrad $0x5,%zmm6,%zmm2");
2220 asm volatile("vpsraq $0x5,%zmm6,%zmm2");
2221
2222 /* AVX-512: Op code 0f 38 c6 (Grp18) */
2223
2224 asm volatile("vgatherpf0dps 0x7b(%ebp,%zmm7,8){%k1}");
2225 asm volatile("vgatherpf0dpd 0x7b(%ebp,%ymm7,8){%k1}");
2226 asm volatile("vgatherpf1dps 0x7b(%ebp,%zmm7,8){%k1}");
2227 asm volatile("vgatherpf1dpd 0x7b(%ebp,%ymm7,8){%k1}");
2228 asm volatile("vscatterpf0dps 0x7b(%ebp,%zmm7,8){%k1}");
2229 asm volatile("vscatterpf0dpd 0x7b(%ebp,%ymm7,8){%k1}");
2230 asm volatile("vscatterpf1dps 0x7b(%ebp,%zmm7,8){%k1}");
2231 asm volatile("vscatterpf1dpd 0x7b(%ebp,%ymm7,8){%k1}");
2232
2233 /* AVX-512: Op code 0f 38 c7 (Grp19) */
2234
2235 asm volatile("vgatherpf0qps 0x7b(%ebp,%zmm7,8){%k1}");
2236 asm volatile("vgatherpf0qpd 0x7b(%ebp,%zmm7,8){%k1}");
2237 asm volatile("vgatherpf1qps 0x7b(%ebp,%zmm7,8){%k1}");
2238 asm volatile("vgatherpf1qpd 0x7b(%ebp,%zmm7,8){%k1}");
2239 asm volatile("vscatterpf0qps 0x7b(%ebp,%zmm7,8){%k1}");
2240 asm volatile("vscatterpf0qpd 0x7b(%ebp,%zmm7,8){%k1}");
2241 asm volatile("vscatterpf1qps 0x7b(%ebp,%zmm7,8){%k1}");
2242 asm volatile("vscatterpf1qpd 0x7b(%ebp,%zmm7,8){%k1}");
2243
2244 /* AVX-512: Examples */
2245
2246 asm volatile("vaddpd %zmm4,%zmm5,%zmm6");
2247 asm volatile("vaddpd %zmm4,%zmm5,%zmm6{%k7}");
2248 asm volatile("vaddpd %zmm4,%zmm5,%zmm6{%k7}{z}");
2249 asm volatile("vaddpd {rn-sae},%zmm4,%zmm5,%zmm6");
2250 asm volatile("vaddpd {ru-sae},%zmm4,%zmm5,%zmm6");
2251 asm volatile("vaddpd {rd-sae},%zmm4,%zmm5,%zmm6");
2252 asm volatile("vaddpd {rz-sae},%zmm4,%zmm5,%zmm6");
2253 asm volatile("vaddpd (%ecx),%zmm5,%zmm6");
2254 asm volatile("vaddpd 0x123(%eax,%ecx,8),%zmm5,%zmm6");
2255 asm volatile("vaddpd (%ecx){1to8},%zmm5,%zmm6");
2256 asm volatile("vaddpd 0x1fc0(%edx),%zmm5,%zmm6");
2257 asm volatile("vaddpd 0x3f8(%edx){1to8},%zmm5,%zmm6");
2258 asm volatile("vcmpeq_uqps 0x1fc(%edx){1to16},%zmm6,%k5");
2259 asm volatile("vcmpltsd 0x123(%eax,%ecx,8),%xmm3,%k5{%k7}");
2260 asm volatile("vcmplesd {sae},%xmm4,%xmm5,%k5{%k7}");
2261 asm volatile("vgetmantss $0x5b,0x123(%eax,%ecx,8),%xmm4,%xmm5{%k7}");
2262
474 /* bndmk m32, bnd */ 2263 /* bndmk m32, bnd */
475 2264
476 asm volatile("bndmk (%eax), %bnd0"); 2265 asm volatile("bndmk (%eax), %bnd0");
@@ -866,10 +2655,6 @@ int main(void)
866 2655
867#endif /* #ifndef __x86_64__ */ 2656#endif /* #ifndef __x86_64__ */
868 2657
869 /* pcommit */
870
871 asm volatile("pcommit");
872
873 /* Following line is a marker for the awk script - do not change */ 2658 /* Following line is a marker for the awk script - do not change */
874 asm volatile("rdtsc"); /* Stop here */ 2659 asm volatile("rdtsc"); /* Stop here */
875 2660
diff --git a/tools/perf/arch/x86/tests/perf-time-to-tsc.c b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
index 9d29ee283ac5..5c76cc83186a 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -71,7 +71,7 @@ int test__perf_time_to_tsc(int subtest __maybe_unused)
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
@@ -154,10 +154,6 @@ next_event:
154 err = 0; 154 err = 0;
155 155
156out_err: 156out_err:
157 if (evlist) { 157 perf_evlist__delete(evlist);
158 perf_evlist__disable(evlist);
159 perf_evlist__delete(evlist);
160 }
161
162 return err; 158 return err;
163} 159}
diff --git a/tools/perf/arch/x86/tests/rdpmc.c b/tools/perf/arch/x86/tests/rdpmc.c
index 72193f19d6d7..500cf96db979 100644
--- a/tools/perf/arch/x86/tests/rdpmc.c
+++ b/tools/perf/arch/x86/tests/rdpmc.c
@@ -1,12 +1,16 @@
1#include <errno.h>
1#include <unistd.h> 2#include <unistd.h>
2#include <stdlib.h> 3#include <stdlib.h>
3#include <signal.h> 4#include <signal.h>
4#include <sys/mman.h> 5#include <sys/mman.h>
6#include <sys/types.h>
7#include <sys/wait.h>
5#include <linux/types.h> 8#include <linux/types.h>
6#include "perf.h" 9#include "perf.h"
7#include "debug.h" 10#include "debug.h"
8#include "tests/tests.h" 11#include "tests/tests.h"
9#include "cloexec.h" 12#include "cloexec.h"
13#include "util.h"
10#include "arch-tests.h" 14#include "arch-tests.h"
11 15
12static u64 rdpmc(unsigned int counter) 16static u64 rdpmc(unsigned int counter)
@@ -111,14 +115,14 @@ static int __test__rdpmc(void)
111 if (fd < 0) { 115 if (fd < 0) {
112 pr_err("Error: sys_perf_event_open() syscall returned " 116 pr_err("Error: sys_perf_event_open() syscall returned "
113 "with %d (%s)\n", fd, 117 "with %d (%s)\n", fd,
114 strerror_r(errno, sbuf, sizeof(sbuf))); 118 str_error_r(errno, sbuf, sizeof(sbuf)));
115 return -1; 119 return -1;
116 } 120 }
117 121
118 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0); 122 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
119 if (addr == (void *)(-1)) { 123 if (addr == (void *)(-1)) {
120 pr_err("Error: mmap() syscall returned with (%s)\n", 124 pr_err("Error: mmap() syscall returned with (%s)\n",
121 strerror_r(errno, sbuf, sizeof(sbuf))); 125 str_error_r(errno, sbuf, sizeof(sbuf)));
122 goto out_close; 126 goto out_close;
123 } 127 }
124 128
diff --git a/tools/perf/arch/x86/util/Build b/tools/perf/arch/x86/util/Build
index 465970370f3e..f95e6f46ef0d 100644
--- a/tools/perf/arch/x86/util/Build
+++ b/tools/perf/arch/x86/util/Build
@@ -3,11 +3,12 @@ libperf-y += tsc.o
3libperf-y += pmu.o 3libperf-y += pmu.o
4libperf-y += kvm-stat.o 4libperf-y += kvm-stat.o
5libperf-y += perf_regs.o 5libperf-y += perf_regs.o
6libperf-y += group.o
6 7
7libperf-$(CONFIG_DWARF) += dwarf-regs.o 8libperf-$(CONFIG_DWARF) += dwarf-regs.o
8libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o 9libperf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o
9 10
10libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 11libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind.o
11libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 12libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
12 13
13libperf-$(CONFIG_AUXTRACE) += auxtrace.o 14libperf-$(CONFIG_AUXTRACE) += auxtrace.o
diff --git a/tools/perf/arch/x86/util/auxtrace.c b/tools/perf/arch/x86/util/auxtrace.c
index 7a7805583e3f..cc1d865e31f1 100644
--- a/tools/perf/arch/x86/util/auxtrace.c
+++ b/tools/perf/arch/x86/util/auxtrace.c
@@ -37,7 +37,7 @@ struct auxtrace_record *auxtrace_record__init_intel(struct perf_evlist *evlist,
37 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME); 37 intel_bts_pmu = perf_pmu__find(INTEL_BTS_PMU_NAME);
38 38
39 if (evlist) { 39 if (evlist) {
40 evlist__for_each(evlist, evsel) { 40 evlist__for_each_entry(evlist, evsel) {
41 if (intel_pt_pmu && 41 if (intel_pt_pmu &&
42 evsel->attr.type == intel_pt_pmu->type) 42 evsel->attr.type == intel_pt_pmu->type)
43 found_pt = true; 43 found_pt = true;
diff --git a/tools/perf/arch/x86/util/group.c b/tools/perf/arch/x86/util/group.c
new file mode 100644
index 000000000000..37f92aa39a5d
--- /dev/null
+++ b/tools/perf/arch/x86/util/group.c
@@ -0,0 +1,27 @@
1#include <stdio.h>
2#include "api/fs/fs.h"
3#include "util/group.h"
4
5/*
6 * Check whether we can use a group for top down.
7 * Without a group may get bad results due to multiplexing.
8 */
9bool arch_topdown_check_group(bool *warn)
10{
11 int n;
12
13 if (sysctl__read_int("kernel/nmi_watchdog", &n) < 0)
14 return false;
15 if (n > 0) {
16 *warn = true;
17 return false;
18 }
19 return true;
20}
21
22void arch_topdown_group_warn(void)
23{
24 fprintf(stderr,
25 "nmi_watchdog enabled with topdown. May give wrong results.\n"
26 "Disable with echo 0 > /proc/sys/kernel/nmi_watchdog\n");
27}
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index d66f9ad4df2e..5132775a044f 100644
--- a/tools/perf/arch/x86/util/intel-bts.c
+++ b/tools/perf/arch/x86/util/intel-bts.c
@@ -124,7 +124,7 @@ static int intel_bts_recording_options(struct auxtrace_record *itr,
124 btsr->evlist = evlist; 124 btsr->evlist = evlist;
125 btsr->snapshot_mode = opts->auxtrace_snapshot_mode; 125 btsr->snapshot_mode = opts->auxtrace_snapshot_mode;
126 126
127 evlist__for_each(evlist, evsel) { 127 evlist__for_each_entry(evlist, evsel) {
128 if (evsel->attr.type == intel_bts_pmu->type) { 128 if (evsel->attr.type == intel_bts_pmu->type) {
129 if (intel_bts_evsel) { 129 if (intel_bts_evsel) {
130 pr_err("There may be only one " INTEL_BTS_PMU_NAME " event\n"); 130 pr_err("There may be only one " INTEL_BTS_PMU_NAME " event\n");
@@ -327,7 +327,7 @@ static int intel_bts_snapshot_start(struct auxtrace_record *itr)
327 container_of(itr, struct intel_bts_recording, itr); 327 container_of(itr, struct intel_bts_recording, itr);
328 struct perf_evsel *evsel; 328 struct perf_evsel *evsel;
329 329
330 evlist__for_each(btsr->evlist, evsel) { 330 evlist__for_each_entry(btsr->evlist, evsel) {
331 if (evsel->attr.type == btsr->intel_bts_pmu->type) 331 if (evsel->attr.type == btsr->intel_bts_pmu->type)
332 return perf_evsel__disable(evsel); 332 return perf_evsel__disable(evsel);
333 } 333 }
@@ -340,7 +340,7 @@ static int intel_bts_snapshot_finish(struct auxtrace_record *itr)
340 container_of(itr, struct intel_bts_recording, itr); 340 container_of(itr, struct intel_bts_recording, itr);
341 struct perf_evsel *evsel; 341 struct perf_evsel *evsel;
342 342
343 evlist__for_each(btsr->evlist, evsel) { 343 evlist__for_each_entry(btsr->evlist, evsel) {
344 if (evsel->attr.type == btsr->intel_bts_pmu->type) 344 if (evsel->attr.type == btsr->intel_bts_pmu->type)
345 return perf_evsel__enable(evsel); 345 return perf_evsel__enable(evsel);
346 } 346 }
@@ -422,7 +422,7 @@ static int intel_bts_read_finish(struct auxtrace_record *itr, int idx)
422 container_of(itr, struct intel_bts_recording, itr); 422 container_of(itr, struct intel_bts_recording, itr);
423 struct perf_evsel *evsel; 423 struct perf_evsel *evsel;
424 424
425 evlist__for_each(btsr->evlist, evsel) { 425 evlist__for_each_entry(btsr->evlist, evsel) {
426 if (evsel->attr.type == btsr->intel_bts_pmu->type) 426 if (evsel->attr.type == btsr->intel_bts_pmu->type)
427 return perf_evlist__enable_event_idx(btsr->evlist, 427 return perf_evlist__enable_event_idx(btsr->evlist,
428 evsel, idx); 428 evsel, idx);
@@ -438,6 +438,11 @@ struct auxtrace_record *intel_bts_recording_init(int *err)
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;
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index a3395179c9ee..a2412e9d883b 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -131,7 +131,7 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str,
131 if (!mask) 131 if (!mask)
132 return -EINVAL; 132 return -EINVAL;
133 133
134 evlist__for_each(evlist, evsel) { 134 evlist__for_each_entry(evlist, evsel) {
135 if (evsel->attr.type == intel_pt_pmu->type) { 135 if (evsel->attr.type == intel_pt_pmu->type) {
136 *res = intel_pt_masked_bits(mask, evsel->attr.config); 136 *res = intel_pt_masked_bits(mask, evsel->attr.config);
137 return 0; 137 return 0;
@@ -501,7 +501,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
501 struct intel_pt_recording *ptr = 501 struct intel_pt_recording *ptr =
502 container_of(itr, struct intel_pt_recording, itr); 502 container_of(itr, struct intel_pt_recording, itr);
503 struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu; 503 struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu;
504 bool have_timing_info; 504 bool have_timing_info, need_immediate = false;
505 struct perf_evsel *evsel, *intel_pt_evsel = NULL; 505 struct perf_evsel *evsel, *intel_pt_evsel = NULL;
506 const struct cpu_map *cpus = evlist->cpus; 506 const struct cpu_map *cpus = evlist->cpus;
507 bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; 507 bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
@@ -511,7 +511,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
511 ptr->evlist = evlist; 511 ptr->evlist = evlist;
512 ptr->snapshot_mode = opts->auxtrace_snapshot_mode; 512 ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
513 513
514 evlist__for_each(evlist, evsel) { 514 evlist__for_each_entry(evlist, evsel) {
515 if (evsel->attr.type == intel_pt_pmu->type) { 515 if (evsel->attr.type == intel_pt_pmu->type) {
516 if (intel_pt_evsel) { 516 if (intel_pt_evsel) {
517 pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n"); 517 pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n");
@@ -655,6 +655,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
655 ptr->have_sched_switch = 3; 655 ptr->have_sched_switch = 3;
656 } else { 656 } else {
657 opts->record_switch_events = true; 657 opts->record_switch_events = true;
658 need_immediate = true;
658 if (cpu_wide) 659 if (cpu_wide)
659 ptr->have_sched_switch = 3; 660 ptr->have_sched_switch = 3;
660 else 661 else
@@ -700,6 +701,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
700 tracking_evsel->attr.freq = 0; 701 tracking_evsel->attr.freq = 0;
701 tracking_evsel->attr.sample_period = 1; 702 tracking_evsel->attr.sample_period = 1;
702 703
704 if (need_immediate)
705 tracking_evsel->immediate = true;
706
703 /* In per-cpu case, always need the time of mmap events etc */ 707 /* In per-cpu case, always need the time of mmap events etc */
704 if (!cpu_map__empty(cpus)) { 708 if (!cpu_map__empty(cpus)) {
705 perf_evsel__set_sample_bit(tracking_evsel, TIME); 709 perf_evsel__set_sample_bit(tracking_evsel, TIME);
@@ -725,7 +729,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr)
725 container_of(itr, struct intel_pt_recording, itr); 729 container_of(itr, struct intel_pt_recording, itr);
726 struct perf_evsel *evsel; 730 struct perf_evsel *evsel;
727 731
728 evlist__for_each(ptr->evlist, evsel) { 732 evlist__for_each_entry(ptr->evlist, evsel) {
729 if (evsel->attr.type == ptr->intel_pt_pmu->type) 733 if (evsel->attr.type == ptr->intel_pt_pmu->type)
730 return perf_evsel__disable(evsel); 734 return perf_evsel__disable(evsel);
731 } 735 }
@@ -738,7 +742,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
738 container_of(itr, struct intel_pt_recording, itr); 742 container_of(itr, struct intel_pt_recording, itr);
739 struct perf_evsel *evsel; 743 struct perf_evsel *evsel;
740 744
741 evlist__for_each(ptr->evlist, evsel) { 745 evlist__for_each_entry(ptr->evlist, evsel) {
742 if (evsel->attr.type == ptr->intel_pt_pmu->type) 746 if (evsel->attr.type == ptr->intel_pt_pmu->type)
743 return perf_evsel__enable(evsel); 747 return perf_evsel__enable(evsel);
744 } 748 }
@@ -1011,7 +1015,7 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
1011 container_of(itr, struct intel_pt_recording, itr); 1015 container_of(itr, struct intel_pt_recording, itr);
1012 struct perf_evsel *evsel; 1016 struct perf_evsel *evsel;
1013 1017
1014 evlist__for_each(ptr->evlist, evsel) { 1018 evlist__for_each_entry(ptr->evlist, evsel) {
1015 if (evsel->attr.type == ptr->intel_pt_pmu->type) 1019 if (evsel->attr.type == ptr->intel_pt_pmu->type)
1016 return perf_evlist__enable_event_idx(ptr->evlist, evsel, 1020 return perf_evlist__enable_event_idx(ptr->evlist, evsel,
1017 idx); 1021 idx);
@@ -1027,6 +1031,11 @@ struct auxtrace_record *intel_pt_recording_init(int *err)
1027 if (!intel_pt_pmu) 1031 if (!intel_pt_pmu)
1028 return NULL; 1032 return NULL;
1029 1033
1034 if (setenv("JITDUMP_USE_ARCH_TIMESTAMP", "1", 1)) {
1035 *err = -errno;
1036 return NULL;
1037 }
1038
1030 ptr = zalloc(sizeof(struct intel_pt_recording)); 1039 ptr = zalloc(sizeof(struct intel_pt_recording));
1031 if (!ptr) { 1040 if (!ptr) {
1032 *err = -ENOMEM; 1041 *err = -ENOMEM;
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index fd2868490d00..2e5567c94e09 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -7,7 +7,6 @@
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,36 @@ u64 rdtsc(void)
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 if (!pc)
66 return 0;
67 err = perf_read_tsc_conversion(pc, &tc);
68 if (err == -EOPNOTSUPP)
69 return 0;
70 if (err)
71 return err;
72
73 pr_debug2("Synthesizing TSC conversion information\n");
74
75 event.time_conv.time_mult = tc.time_mult;
76 event.time_conv.time_shift = tc.time_shift;
77 event.time_conv.time_zero = tc.time_zero;
78
79 return process(tool, &event, NULL, machine);
80}
diff --git a/tools/perf/arch/x86/util/tsc.h b/tools/perf/arch/x86/util/tsc.h
deleted file mode 100644
index 2edc4d31065c..000000000000
--- a/tools/perf/arch/x86/util/tsc.h
+++ /dev/null
@@ -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__ */
diff --git a/tools/perf/arch/x86/util/unwind-libunwind.c b/tools/perf/arch/x86/util/unwind-libunwind.c
index db25e93d989c..4f16661cbdbb 100644
--- a/tools/perf/arch/x86/util/unwind-libunwind.c
+++ b/tools/perf/arch/x86/util/unwind-libunwind.c
@@ -1,12 +1,14 @@
1 1
2#ifndef REMOTE_UNWIND_LIBUNWIND
2#include <errno.h> 3#include <errno.h>
3#include <libunwind.h> 4#include <libunwind.h>
4#include "perf_regs.h" 5#include "perf_regs.h"
5#include "../../util/unwind.h" 6#include "../../util/unwind.h"
6#include "../../util/debug.h" 7#include "../../util/debug.h"
8#endif
7 9
8#ifdef HAVE_ARCH_X86_64_SUPPORT 10#ifdef HAVE_ARCH_X86_64_SUPPORT
9int libunwind__arch_reg_id(int regnum) 11int LIBUNWIND__ARCH_REG_ID(int regnum)
10{ 12{
11 int id; 13 int id;
12 14
@@ -70,7 +72,7 @@ int libunwind__arch_reg_id(int regnum)
70 return id; 72 return id;
71} 73}
72#else 74#else
73int libunwind__arch_reg_id(int regnum) 75int LIBUNWIND__ARCH_REG_ID(int regnum)
74{ 76{
75 int id; 77 int id;
76 78
diff --git a/tools/perf/bench/futex-hash.c b/tools/perf/bench/futex-hash.c
index 0999ac536d86..8024cd5febd2 100644
--- a/tools/perf/bench/futex-hash.c
+++ b/tools/perf/bench/futex-hash.c
@@ -8,18 +8,23 @@
8 * many threads and futexes as possible. 8 * many threads and futexes as possible.
9 */ 9 */
10 10
11#include "../perf.h" 11/* For the CLR_() macros */
12#include "../util/util.h" 12#include <pthread.h>
13
14#include <errno.h>
15#include <signal.h>
16#include <stdlib.h>
17#include <linux/compiler.h>
18#include <linux/kernel.h>
19#include <sys/time.h>
20
13#include "../util/stat.h" 21#include "../util/stat.h"
14#include <subcmd/parse-options.h> 22#include <subcmd/parse-options.h>
15#include "../util/header.h"
16#include "bench.h" 23#include "bench.h"
17#include "futex.h" 24#include "futex.h"
18 25
19#include <err.h> 26#include <err.h>
20#include <stdlib.h>
21#include <sys/time.h> 27#include <sys/time.h>
22#include <pthread.h>
23 28
24static unsigned int nthreads = 0; 29static unsigned int nthreads = 0;
25static unsigned int nsecs = 10; 30static unsigned int nsecs = 10;
diff --git a/tools/perf/bench/futex-lock-pi.c b/tools/perf/bench/futex-lock-pi.c
index 6a18ce21f865..936d89d30483 100644
--- a/tools/perf/bench/futex-lock-pi.c
+++ b/tools/perf/bench/futex-lock-pi.c
@@ -2,18 +2,21 @@
2 * Copyright (C) 2015 Davidlohr Bueso. 2 * Copyright (C) 2015 Davidlohr Bueso.
3 */ 3 */
4 4
5#include "../perf.h" 5/* For the CLR_() macros */
6#include "../util/util.h" 6#include <pthread.h>
7
8#include <signal.h>
7#include "../util/stat.h" 9#include "../util/stat.h"
8#include <subcmd/parse-options.h> 10#include <subcmd/parse-options.h>
9#include "../util/header.h" 11#include <linux/compiler.h>
12#include <linux/kernel.h>
13#include <errno.h>
10#include "bench.h" 14#include "bench.h"
11#include "futex.h" 15#include "futex.h"
12 16
13#include <err.h> 17#include <err.h>
14#include <stdlib.h> 18#include <stdlib.h>
15#include <sys/time.h> 19#include <sys/time.h>
16#include <pthread.h>
17 20
18struct worker { 21struct worker {
19 int tid; 22 int tid;
@@ -83,7 +86,7 @@ static void *workerfn(void *arg)
83 do { 86 do {
84 int ret; 87 int ret;
85 again: 88 again:
86 ret = futex_lock_pi(w->futex, NULL, 0, futex_flag); 89 ret = futex_lock_pi(w->futex, NULL, futex_flag);
87 90
88 if (ret) { /* handle lock acquisition */ 91 if (ret) { /* handle lock acquisition */
89 if (!silent) 92 if (!silent)
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 718238683013..f96e22ed9f87 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -8,18 +8,21 @@
8 * requeues without waking up any tasks -- thus mimicking a regular futex_wait. 8 * requeues without waking up any tasks -- thus mimicking a regular futex_wait.
9 */ 9 */
10 10
11#include "../perf.h" 11/* For the CLR_() macros */
12#include "../util/util.h" 12#include <pthread.h>
13
14#include <signal.h>
13#include "../util/stat.h" 15#include "../util/stat.h"
14#include <subcmd/parse-options.h> 16#include <subcmd/parse-options.h>
15#include "../util/header.h" 17#include <linux/compiler.h>
18#include <linux/kernel.h>
19#include <errno.h>
16#include "bench.h" 20#include "bench.h"
17#include "futex.h" 21#include "futex.h"
18 22
19#include <err.h> 23#include <err.h>
20#include <stdlib.h> 24#include <stdlib.h>
21#include <sys/time.h> 25#include <sys/time.h>
22#include <pthread.h>
23 26
24static u_int32_t futex1 = 0, futex2 = 0; 27static u_int32_t futex1 = 0, futex2 = 0;
25 28
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 91aaf2a1fa90..4a2ecd7438ca 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -7,18 +7,21 @@
7 * it can be used to measure futex_wake() changes. 7 * it can be used to measure futex_wake() changes.
8 */ 8 */
9 9
10#include "../perf.h" 10/* For the CLR_() macros */
11#include "../util/util.h" 11#include <pthread.h>
12
13#include <signal.h>
12#include "../util/stat.h" 14#include "../util/stat.h"
13#include <subcmd/parse-options.h> 15#include <subcmd/parse-options.h>
14#include "../util/header.h" 16#include <linux/compiler.h>
17#include <linux/kernel.h>
18#include <errno.h>
15#include "bench.h" 19#include "bench.h"
16#include "futex.h" 20#include "futex.h"
17 21
18#include <err.h> 22#include <err.h>
19#include <stdlib.h> 23#include <stdlib.h>
20#include <sys/time.h> 24#include <sys/time.h>
21#include <pthread.h>
22 25
23struct thread_data { 26struct thread_data {
24 pthread_t worker; 27 pthread_t worker;
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index f416bd705f66..87d8f4f292d9 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -8,18 +8,21 @@
8 * one or more tasks, and thus the waitqueue is never empty. 8 * one or more tasks, and thus the waitqueue is never empty.
9 */ 9 */
10 10
11#include "../perf.h" 11/* For the CLR_() macros */
12#include "../util/util.h" 12#include <pthread.h>
13
14#include <signal.h>
13#include "../util/stat.h" 15#include "../util/stat.h"
14#include <subcmd/parse-options.h> 16#include <subcmd/parse-options.h>
15#include "../util/header.h" 17#include <linux/compiler.h>
18#include <linux/kernel.h>
19#include <errno.h>
16#include "bench.h" 20#include "bench.h"
17#include "futex.h" 21#include "futex.h"
18 22
19#include <err.h> 23#include <err.h>
20#include <stdlib.h> 24#include <stdlib.h>
21#include <sys/time.h> 25#include <sys/time.h>
22#include <pthread.h>
23 26
24/* all threads will block on the same futex */ 27/* all threads will block on the same futex */
25static u_int32_t futex1 = 0; 28static u_int32_t futex1 = 0;
diff --git a/tools/perf/bench/futex.h b/tools/perf/bench/futex.h
index d44de9f44281..b2e06d1190d0 100644
--- a/tools/perf/bench/futex.h
+++ b/tools/perf/bench/futex.h
@@ -57,13 +57,11 @@ futex_wake(u_int32_t *uaddr, int nr_wake, int opflags)
57 57
58/** 58/**
59 * futex_lock_pi() - block on uaddr as a PI mutex 59 * 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 int 61static 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/**
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index a91aa85d80ff..2b54d0f2672a 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -6,6 +6,7 @@
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 = {
63 .config = PERF_COUNT_HW_CPU_CYCLES 64 .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 else 73 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 *
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;
diff --git a/tools/perf/bench/mem-memcpy-x86-64-asm.S b/tools/perf/bench/mem-memcpy-x86-64-asm.S
index 5c3cce082cb8..f700369bb0f6 100644
--- a/tools/perf/bench/mem-memcpy-x86-64-asm.S
+++ b/tools/perf/bench/mem-memcpy-x86-64-asm.S
@@ -6,7 +6,7 @@
6#define globl p2align 4; .globl 6#define globl p2align 4; .globl
7#define _ASM_EXTABLE_FAULT(x, y) 7#define _ASM_EXTABLE_FAULT(x, y)
8 8
9#include "../../../arch/x86/lib/memcpy_64.S" 9#include "../../arch/x86/lib/memcpy_64.S"
10/* 10/*
11 * We need to provide note.GNU-stack section, saying that we want 11 * We need to provide note.GNU-stack section, saying that we want
12 * NOT executable stack. Otherwise the final linking will assume that 12 * NOT executable stack. Otherwise the final linking will assume that
diff --git a/tools/perf/bench/mem-memset-x86-64-asm.S b/tools/perf/bench/mem-memset-x86-64-asm.S
index de278784c866..58407aa24c1b 100644
--- a/tools/perf/bench/mem-memset-x86-64-asm.S
+++ b/tools/perf/bench/mem-memset-x86-64-asm.S
@@ -1,7 +1,7 @@
1#define memset MEMSET /* don't hide glibc's memset() */ 1#define memset MEMSET /* don't hide glibc's memset() */
2#define altinstr_replacement text 2#define altinstr_replacement text
3#define globl p2align 4; .globl 3#define globl p2align 4; .globl
4#include "../../../arch/x86/lib/memset_64.S" 4#include "../../arch/x86/lib/memset_64.S"
5 5
6/* 6/*
7 * We need to provide note.GNU-stack section, saying that we want 7 * We need to provide note.GNU-stack section, saying that we want
diff --git a/tools/perf/bench/numa.c b/tools/perf/bench/numa.c
index 7500d959d7eb..f7f530081aa9 100644
--- a/tools/perf/bench/numa.c
+++ b/tools/perf/bench/numa.c
@@ -4,6 +4,9 @@
4 * numa: Simulate NUMA-sensitive workload and measure their NUMA performance 4 * numa: Simulate NUMA-sensitive workload and measure their NUMA performance
5 */ 5 */
6 6
7/* For the CLR_() macros */
8#include <pthread.h>
9
7#include "../perf.h" 10#include "../perf.h"
8#include "../builtin.h" 11#include "../builtin.h"
9#include "../util/util.h" 12#include "../util/util.h"
@@ -21,7 +24,6 @@
21#include <stdlib.h> 24#include <stdlib.h>
22#include <string.h> 25#include <string.h>
23#include <unistd.h> 26#include <unistd.h>
24#include <pthread.h>
25#include <sys/mman.h> 27#include <sys/mman.h>
26#include <sys/time.h> 28#include <sys/time.h>
27#include <sys/resource.h> 29#include <sys/resource.h>
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 814158393656..9c1034d81b4f 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -75,7 +75,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
75 sample->period = 1; 75 sample->period = 1;
76 sample->weight = 1; 76 sample->weight = 1;
77 77
78 he = __hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 78 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
79 if (he == NULL) 79 if (he == NULL)
80 return -ENOMEM; 80 return -ENOMEM;
81 81
@@ -236,7 +236,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
236 perf_session__fprintf_dsos(session, stdout); 236 perf_session__fprintf_dsos(session, stdout);
237 237
238 total_nr_samples = 0; 238 total_nr_samples = 0;
239 evlist__for_each(session->evlist, pos) { 239 evlist__for_each_entry(session->evlist, pos) {
240 struct hists *hists = evsel__hists(pos); 240 struct hists *hists = evsel__hists(pos);
241 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 241 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
242 242
@@ -324,8 +324,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
324 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing, 324 OPT_BOOLEAN(0, "skip-missing", &annotate.skip_missing,
325 "Skip symbols that cannot be annotated"), 325 "Skip symbols that cannot be annotated"),
326 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"), 326 OPT_STRING('C', "cpu", &annotate.cpu_list, "cpu", "list of cpus to profile"),
327 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 327 OPT_CALLBACK(0, "symfs", NULL, "directory",
328 "Look for files with symbols relative to this directory"), 328 "Look for files with symbols relative to this directory",
329 symbol__config_symfs),
329 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src, 330 OPT_BOOLEAN(0, "source", &symbol_conf.annotate_src,
330 "Interleave source code with assembly code (default)"), 331 "Interleave source code with assembly code (default)"),
331 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw, 332 OPT_BOOLEAN(0, "asm-raw", &symbol_conf.annotate_asm_raw,
@@ -338,6 +339,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
338 "Show event group information together"), 339 "Show event group information together"),
339 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 340 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
340 "Show a column with the sum of periods"), 341 "Show a column with the sum of periods"),
342 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
343 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
344 stdio__config_color, "always"),
341 OPT_END() 345 OPT_END()
342 }; 346 };
343 int ret = hists__init(); 347 int ret = hists__init();
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index 632efc6b79a0..30e2b2cb2421 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -119,8 +119,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
119 if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0) 119 if (build_id_cache__kcore_buildid(from_dir, sbuildid) < 0)
120 return -1; 120 return -1;
121 121
122 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s", 122 scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s",
123 buildid_dir, sbuildid); 123 buildid_dir, DSO__NAME_KCORE, sbuildid);
124 124
125 if (!force && 125 if (!force &&
126 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) { 126 !build_id_cache__kcore_existing(from_dir, to_dir, sizeof(to_dir))) {
@@ -131,8 +131,8 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
131 if (build_id_cache__kcore_dir(dir, sizeof(dir))) 131 if (build_id_cache__kcore_dir(dir, sizeof(dir)))
132 return -1; 132 return -1;
133 133
134 scnprintf(to_dir, sizeof(to_dir), "%s/[kernel.kcore]/%s/%s", 134 scnprintf(to_dir, sizeof(to_dir), "%s/%s/%s/%s",
135 buildid_dir, sbuildid, dir); 135 buildid_dir, DSO__NAME_KCORE, sbuildid, dir);
136 136
137 if (mkdir_p(to_dir, 0755)) 137 if (mkdir_p(to_dir, 0755))
138 return -1; 138 return -1;
@@ -209,7 +209,7 @@ static int build_id_cache__purge_path(const char *pathname)
209 if (err) 209 if (err)
210 goto out; 210 goto out;
211 211
212 strlist__for_each(pos, list) { 212 strlist__for_each_entry(pos, list) {
213 err = build_id_cache__remove_s(pos->s); 213 err = build_id_cache__remove_s(pos->s);
214 pr_debug("Removing %s %s: %s\n", pos->s, pathname, 214 pr_debug("Removing %s %s: %s\n", pos->s, pathname,
215 err ? "FAIL" : "Ok"); 215 err ? "FAIL" : "Ok");
@@ -343,7 +343,7 @@ int cmd_buildid_cache(int argc, const char **argv,
343 if (add_name_list_str) { 343 if (add_name_list_str) {
344 list = strlist__new(add_name_list_str, NULL); 344 list = strlist__new(add_name_list_str, NULL);
345 if (list) { 345 if (list) {
346 strlist__for_each(pos, list) 346 strlist__for_each_entry(pos, list)
347 if (build_id_cache__add_file(pos->s)) { 347 if (build_id_cache__add_file(pos->s)) {
348 if (errno == EEXIST) { 348 if (errno == EEXIST) {
349 pr_debug("%s already in the cache\n", 349 pr_debug("%s already in the cache\n",
@@ -351,7 +351,7 @@ int cmd_buildid_cache(int argc, const char **argv,
351 continue; 351 continue;
352 } 352 }
353 pr_warning("Couldn't add %s: %s\n", 353 pr_warning("Couldn't add %s: %s\n",
354 pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); 354 pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
355 } 355 }
356 356
357 strlist__delete(list); 357 strlist__delete(list);
@@ -361,7 +361,7 @@ int cmd_buildid_cache(int argc, const char **argv,
361 if (remove_name_list_str) { 361 if (remove_name_list_str) {
362 list = strlist__new(remove_name_list_str, NULL); 362 list = strlist__new(remove_name_list_str, NULL);
363 if (list) { 363 if (list) {
364 strlist__for_each(pos, list) 364 strlist__for_each_entry(pos, list)
365 if (build_id_cache__remove_file(pos->s)) { 365 if (build_id_cache__remove_file(pos->s)) {
366 if (errno == ENOENT) { 366 if (errno == ENOENT) {
367 pr_debug("%s wasn't in the cache\n", 367 pr_debug("%s wasn't in the cache\n",
@@ -369,7 +369,7 @@ int cmd_buildid_cache(int argc, const char **argv,
369 continue; 369 continue;
370 } 370 }
371 pr_warning("Couldn't remove %s: %s\n", 371 pr_warning("Couldn't remove %s: %s\n",
372 pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); 372 pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
373 } 373 }
374 374
375 strlist__delete(list); 375 strlist__delete(list);
@@ -379,7 +379,7 @@ int cmd_buildid_cache(int argc, const char **argv,
379 if (purge_name_list_str) { 379 if (purge_name_list_str) {
380 list = strlist__new(purge_name_list_str, NULL); 380 list = strlist__new(purge_name_list_str, NULL);
381 if (list) { 381 if (list) {
382 strlist__for_each(pos, list) 382 strlist__for_each_entry(pos, list)
383 if (build_id_cache__purge_path(pos->s)) { 383 if (build_id_cache__purge_path(pos->s)) {
384 if (errno == ENOENT) { 384 if (errno == ENOENT) {
385 pr_debug("%s wasn't in the cache\n", 385 pr_debug("%s wasn't in the cache\n",
@@ -387,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv,
387 continue; 387 continue;
388 } 388 }
389 pr_warning("Couldn't remove %s: %s\n", 389 pr_warning("Couldn't remove %s: %s\n",
390 pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); 390 pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
391 } 391 }
392 392
393 strlist__delete(list); 393 strlist__delete(list);
@@ -400,7 +400,7 @@ int cmd_buildid_cache(int argc, const char **argv,
400 if (update_name_list_str) { 400 if (update_name_list_str) {
401 list = strlist__new(update_name_list_str, NULL); 401 list = strlist__new(update_name_list_str, NULL);
402 if (list) { 402 if (list) {
403 strlist__for_each(pos, list) 403 strlist__for_each_entry(pos, list)
404 if (build_id_cache__update_file(pos->s)) { 404 if (build_id_cache__update_file(pos->s)) {
405 if (errno == ENOENT) { 405 if (errno == ENOENT) {
406 pr_debug("%s wasn't in the cache\n", 406 pr_debug("%s wasn't in the cache\n",
@@ -408,7 +408,7 @@ int cmd_buildid_cache(int argc, const char **argv,
408 continue; 408 continue;
409 } 409 }
410 pr_warning("Couldn't update %s: %s\n", 410 pr_warning("Couldn't update %s: %s\n",
411 pos->s, strerror_r(errno, sbuf, sizeof(sbuf))); 411 pos->s, str_error_r(errno, sbuf, sizeof(sbuf)));
412 } 412 }
413 413
414 strlist__delete(list); 414 strlist__delete(list);
@@ -419,8 +419,7 @@ int cmd_buildid_cache(int argc, const char **argv,
419 pr_warning("Couldn't add %s\n", kcore_filename); 419 pr_warning("Couldn't add %s\n", kcore_filename);
420 420
421out: 421out:
422 if (session) 422 perf_session__delete(session);
423 perf_session__delete(session);
424 423
425 return ret; 424 return ret;
426} 425}
diff --git a/tools/perf/builtin-config.c b/tools/perf/builtin-config.c
index c42448ed5dfe..e4207a23b52c 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -12,6 +12,7 @@
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,21 @@ static struct option config_options[] = {
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 else 40
41 printf("%s\n", key); 41 if (set == NULL)
42 return -1;
43
44 perf_config_set__for_each_entry(set, section, item) {
45 char *value = item->value;
46
47 if (value)
48 printf("%s.%s=%s\n", section->name,
49 item->name, value);
50 }
42 51
43 return 0; 52 return 0;
44} 53}
@@ -46,6 +55,7 @@ static int show_config(const char *key, const char *value,
46int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused) 55int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
47{ 56{
48 int ret = 0; 57 int ret = 0;
58 struct perf_config_set *set;
49 char *user_config = mkpath("%s/.perfconfig", getenv("HOME")); 59 char *user_config = mkpath("%s/.perfconfig", getenv("HOME"));
50 60
51 argc = parse_options(argc, argv, config_options, config_usage, 61 argc = parse_options(argc, argv, config_options, config_usage,
@@ -63,13 +73,23 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
63 else if (use_user_config) 73 else if (use_user_config)
64 config_exclusive_filename = user_config; 74 config_exclusive_filename = user_config;
65 75
76 /*
77 * At only 'config' sub-command, individually use the config set
78 * because of reinitializing with options config file location.
79 */
80 set = perf_config_set__new();
81 if (!set) {
82 ret = -1;
83 goto out_err;
84 }
85
66 switch (actions) { 86 switch (actions) {
67 case ACTION_LIST: 87 case ACTION_LIST:
68 if (argc) { 88 if (argc) {
69 pr_err("Error: takes no arguments\n"); 89 pr_err("Error: takes no arguments\n");
70 parse_options_usage(config_usage, config_options, "l", 1); 90 parse_options_usage(config_usage, config_options, "l", 1);
71 } else { 91 } else {
72 ret = perf_config(show_config, NULL); 92 ret = show_config(set);
73 if (ret < 0) { 93 if (ret < 0) {
74 const char * config_filename = config_exclusive_filename; 94 const char * config_filename = config_exclusive_filename;
75 if (!config_exclusive_filename) 95 if (!config_exclusive_filename)
@@ -83,5 +103,7 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
83 usage_with_options(config_usage, config_options); 103 usage_with_options(config_usage, config_options);
84 } 104 }
85 105
106 perf_config_set__delete(set);
107out_err:
86 return ret; 108 return ret;
87} 109}
diff --git a/tools/perf/builtin-data.c b/tools/perf/builtin-data.c
index b97bc1518b44..7ad6e17ac6b3 100644
--- a/tools/perf/builtin-data.c
+++ b/tools/perf/builtin-data.c
@@ -3,6 +3,7 @@
3#include "perf.h" 3#include "perf.h"
4#include "debug.h" 4#include "debug.h"
5#include <subcmd/parse-options.h> 5#include <subcmd/parse-options.h>
6#include "data-convert.h"
6#include "data-convert-bt.h" 7#include "data-convert-bt.h"
7 8
8typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix); 9typedef int (*data_cmd_fn_t)(int argc, const char **argv, const char *prefix);
@@ -53,14 +54,18 @@ static int cmd_data_convert(int argc, const char **argv,
53 const char *prefix __maybe_unused) 54 const char *prefix __maybe_unused)
54{ 55{
55 const char *to_ctf = NULL; 56 const char *to_ctf = NULL;
56 bool force = false; 57 struct perf_data_convert_opts opts = {
58 .force = false,
59 .all = false,
60 };
57 const struct option options[] = { 61 const struct option options[] = {
58 OPT_INCR('v', "verbose", &verbose, "be more verbose"), 62 OPT_INCR('v', "verbose", &verbose, "be more verbose"),
59 OPT_STRING('i', "input", &input_name, "file", "input file name"), 63 OPT_STRING('i', "input", &input_name, "file", "input file name"),
60#ifdef HAVE_LIBBABELTRACE_SUPPORT 64#ifdef HAVE_LIBBABELTRACE_SUPPORT
61 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"), 65 OPT_STRING(0, "to-ctf", &to_ctf, NULL, "Convert to CTF format"),
62#endif 66#endif
63 OPT_BOOLEAN('f', "force", &force, "don't complain, do it"), 67 OPT_BOOLEAN('f', "force", &opts.force, "don't complain, do it"),
68 OPT_BOOLEAN(0, "all", &opts.all, "Convert all events"),
64 OPT_END() 69 OPT_END()
65 }; 70 };
66 71
@@ -78,7 +83,7 @@ static int cmd_data_convert(int argc, const char **argv,
78 83
79 if (to_ctf) { 84 if (to_ctf) {
80#ifdef HAVE_LIBBABELTRACE_SUPPORT 85#ifdef HAVE_LIBBABELTRACE_SUPPORT
81 return bt_convert__perf2ctf(input_name, to_ctf, force); 86 return bt_convert__perf2ctf(input_name, to_ctf, &opts);
82#else 87#else
83 pr_err("The libbabeltrace support is not compiled in.\n"); 88 pr_err("The libbabeltrace support is not compiled in.\n");
84 return -1; 89 return -1;
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c
index 8053a8ceefda..21ee753211ad 100644
--- a/tools/perf/builtin-diff.c
+++ b/tools/perf/builtin-diff.c
@@ -310,16 +310,6 @@ static int formula_fprintf(struct hist_entry *he, struct hist_entry *pair,
310 return -1; 310 return -1;
311} 311}
312 312
313static int hists__add_entry(struct hists *hists,
314 struct addr_location *al,
315 struct perf_sample *sample)
316{
317 if (__hists__add_entry(hists, al, NULL, NULL, NULL,
318 sample, true) != NULL)
319 return 0;
320 return -ENOMEM;
321}
322
323static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, 313static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
324 union perf_event *event, 314 union perf_event *event,
325 struct perf_sample *sample, 315 struct perf_sample *sample,
@@ -336,7 +326,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused,
336 return -1; 326 return -1;
337 } 327 }
338 328
339 if (hists__add_entry(hists, &al, sample)) { 329 if (!hists__add_entry(hists, &al, NULL, NULL, NULL, sample, true)) {
340 pr_warning("problem incrementing symbol period, skipping event\n"); 330 pr_warning("problem incrementing symbol period, skipping event\n");
341 goto out_put; 331 goto out_put;
342 } 332 }
@@ -373,7 +363,7 @@ static struct perf_evsel *evsel_match(struct perf_evsel *evsel,
373{ 363{
374 struct perf_evsel *e; 364 struct perf_evsel *e;
375 365
376 evlist__for_each(evlist, e) { 366 evlist__for_each_entry(evlist, e) {
377 if (perf_evsel__match2(evsel, e)) 367 if (perf_evsel__match2(evsel, e))
378 return e; 368 return e;
379 } 369 }
@@ -385,7 +375,7 @@ static void perf_evlist__collapse_resort(struct perf_evlist *evlist)
385{ 375{
386 struct perf_evsel *evsel; 376 struct perf_evsel *evsel;
387 377
388 evlist__for_each(evlist, evsel) { 378 evlist__for_each_entry(evlist, evsel) {
389 struct hists *hists = evsel__hists(evsel); 379 struct hists *hists = evsel__hists(evsel);
390 380
391 hists__collapse_resort(hists, NULL); 381 hists__collapse_resort(hists, NULL);
@@ -428,7 +418,7 @@ static void hists__baseline_only(struct hists *hists)
428 struct rb_root *root; 418 struct rb_root *root;
429 struct rb_node *next; 419 struct rb_node *next;
430 420
431 if (sort__need_collapse) 421 if (hists__has(hists, need_collapse))
432 root = &hists->entries_collapsed; 422 root = &hists->entries_collapsed;
433 else 423 else
434 root = hists->entries_in; 424 root = hists->entries_in;
@@ -450,7 +440,7 @@ static void hists__precompute(struct hists *hists)
450 struct rb_root *root; 440 struct rb_root *root;
451 struct rb_node *next; 441 struct rb_node *next;
452 442
453 if (sort__need_collapse) 443 if (hists__has(hists, need_collapse))
454 root = &hists->entries_collapsed; 444 root = &hists->entries_collapsed;
455 else 445 else
456 root = hists->entries_in; 446 root = hists->entries_in;
@@ -666,7 +656,8 @@ static void hists__process(struct hists *hists)
666 hists__precompute(hists); 656 hists__precompute(hists);
667 hists__output_resort(hists, NULL); 657 hists__output_resort(hists, NULL);
668 658
669 hists__fprintf(hists, true, 0, 0, 0, stdout); 659 hists__fprintf(hists, true, 0, 0, 0, stdout,
660 symbol_conf.use_callchain);
670} 661}
671 662
672static void data__fprintf(void) 663static void data__fprintf(void)
@@ -690,7 +681,7 @@ static void data_process(void)
690 struct perf_evsel *evsel_base; 681 struct perf_evsel *evsel_base;
691 bool first = true; 682 bool first = true;
692 683
693 evlist__for_each(evlist_base, evsel_base) { 684 evlist__for_each_entry(evlist_base, evsel_base) {
694 struct hists *hists_base = evsel__hists(evsel_base); 685 struct hists *hists_base = evsel__hists(evsel_base);
695 struct data__file *d; 686 struct data__file *d;
696 int i; 687 int i;
@@ -765,9 +756,7 @@ static int __cmd_diff(void)
765 756
766 out_delete: 757 out_delete:
767 data__for_each_file(i, d) { 758 data__for_each_file(i, d) {
768 if (d->session) 759 perf_session__delete(d->session);
769 perf_session__delete(d->session);
770
771 data__free(d); 760 data__free(d);
772 } 761 }
773 762
@@ -812,8 +801,9 @@ static const struct option options[] = {
812 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator", 801 OPT_STRING_NOEMPTY('t', "field-separator", &symbol_conf.field_sep, "separator",
813 "separator for columns, no spaces will be added between " 802 "separator for columns, no spaces will be added between "
814 "columns '.' is reserved."), 803 "columns '.' is reserved."),
815 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 804 OPT_CALLBACK(0, "symfs", NULL, "directory",
816 "Look for files with symbols relative to this directory"), 805 "Look for files with symbols relative to this directory",
806 symbol__config_symfs),
817 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."), 807 OPT_UINTEGER('o', "order", &sort_compute, "Specify compute sorting."),
818 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute", 808 OPT_CALLBACK(0, "percentage", NULL, "relative|absolute",
819 "How to display percentage of filtered entries", parse_filter_percentage), 809 "How to display percentage of filtered entries", parse_filter_percentage),
@@ -1043,7 +1033,7 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
1043} 1033}
1044 1034
1045static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1035static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1046 struct perf_evsel *evsel __maybe_unused) 1036 struct hists *hists __maybe_unused)
1047{ 1037{
1048 struct diff_hpp_fmt *dfmt = 1038 struct diff_hpp_fmt *dfmt =
1049 container_of(fmt, struct diff_hpp_fmt, fmt); 1039 container_of(fmt, struct diff_hpp_fmt, fmt);
@@ -1054,7 +1044,7 @@ static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1054 1044
1055static int hpp__width(struct perf_hpp_fmt *fmt, 1045static int hpp__width(struct perf_hpp_fmt *fmt,
1056 struct perf_hpp *hpp __maybe_unused, 1046 struct perf_hpp *hpp __maybe_unused,
1057 struct perf_evsel *evsel __maybe_unused) 1047 struct hists *hists __maybe_unused)
1058{ 1048{
1059 struct diff_hpp_fmt *dfmt = 1049 struct diff_hpp_fmt *dfmt =
1060 container_of(fmt, struct diff_hpp_fmt, fmt); 1050 container_of(fmt, struct diff_hpp_fmt, fmt);
diff --git a/tools/perf/builtin-evlist.c b/tools/perf/builtin-evlist.c
index 8a31f511e1a0..e09c4287fe87 100644
--- a/tools/perf/builtin-evlist.c
+++ b/tools/perf/builtin-evlist.c
@@ -32,7 +32,7 @@ static int __cmd_evlist(const char *file_name, struct perf_attr_details *details
32 if (session == NULL) 32 if (session == NULL)
33 return -1; 33 return -1;
34 34
35 evlist__for_each(session->evlist, pos) { 35 evlist__for_each_entry(session->evlist, pos) {
36 perf_evsel__fprintf(pos, details, stdout); 36 perf_evsel__fprintf(pos, details, stdout);
37 37
38 if (pos->attr.type == PERF_TYPE_TRACEPOINT) 38 if (pos->attr.type == PERF_TYPE_TRACEPOINT)
diff --git a/tools/perf/builtin-help.c b/tools/perf/builtin-help.c
index bc1de9b8fd67..3bdb2c78a21b 100644
--- a/tools/perf/builtin-help.c
+++ b/tools/perf/builtin-help.c
@@ -4,7 +4,7 @@
4 * Builtin help command 4 * Builtin help command
5 */ 5 */
6#include "perf.h" 6#include "perf.h"
7#include "util/cache.h" 7#include "util/config.h"
8#include "builtin.h" 8#include "builtin.h"
9#include <subcmd/exec-cmd.h> 9#include <subcmd/exec-cmd.h>
10#include "common-cmds.h" 10#include "common-cmds.h"
@@ -61,6 +61,7 @@ static int check_emacsclient_version(void)
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)
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)
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)
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)
@@ -115,7 +117,7 @@ static void exec_woman_emacs(const char *path, const char *page)
115 free(man_page); 117 free(man_page);
116 } 118 }
117 warning("failed to exec '%s': %s", path, 119 warning("failed to exec '%s': %s", path,
118 strerror_r(errno, sbuf, sizeof(sbuf))); 120 str_error_r(errno, sbuf, sizeof(sbuf)));
119 } 121 }
120} 122}
121 123
@@ -148,7 +150,7 @@ static void exec_man_konqueror(const char *path, const char *page)
148 free(man_page); 150 free(man_page);
149 } 151 }
150 warning("failed to exec '%s': %s", path, 152 warning("failed to exec '%s': %s", path,
151 strerror_r(errno, sbuf, sizeof(sbuf))); 153 str_error_r(errno, sbuf, sizeof(sbuf)));
152 } 154 }
153} 155}
154 156
@@ -160,7 +162,7 @@ static void exec_man_man(const char *path, const char *page)
160 path = "man"; 162 path = "man";
161 execlp(path, "man", page, NULL); 163 execlp(path, "man", page, NULL);
162 warning("failed to exec '%s': %s", path, 164 warning("failed to exec '%s': %s", path,
163 strerror_r(errno, sbuf, sizeof(sbuf))); 165 str_error_r(errno, sbuf, sizeof(sbuf)));
164} 166}
165 167
166static void exec_man_cmd(const char *cmd, const char *page) 168static void exec_man_cmd(const char *cmd, const char *page)
@@ -173,7 +175,7 @@ static void exec_man_cmd(const char *cmd, const char *page)
173 free(shell_cmd); 175 free(shell_cmd);
174 } 176 }
175 warning("failed to exec '%s': %s", cmd, 177 warning("failed to exec '%s': %s", cmd,
176 strerror_r(errno, sbuf, sizeof(sbuf))); 178 str_error_r(errno, sbuf, sizeof(sbuf)));
177} 179}
178 180
179static void add_man_viewer(const char *name) 181static void add_man_viewer(const char *name)
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index d1a2d104f2bc..73c1c4cc3600 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -562,7 +562,7 @@ static void strip_init(struct perf_inject *inject)
562 562
563 inject->tool.context_switch = perf_event__drop; 563 inject->tool.context_switch = perf_event__drop;
564 564
565 evlist__for_each(evlist, evsel) 565 evlist__for_each_entry(evlist, evsel)
566 evsel->handler = drop_sample; 566 evsel->handler = drop_sample;
567} 567}
568 568
@@ -590,7 +590,7 @@ static bool ok_to_remove(struct perf_evlist *evlist,
590 if (!has_tracking(evsel_to_remove)) 590 if (!has_tracking(evsel_to_remove))
591 return true; 591 return true;
592 592
593 evlist__for_each(evlist, evsel) { 593 evlist__for_each_entry(evlist, evsel) {
594 if (evsel->handler != drop_sample) { 594 if (evsel->handler != drop_sample) {
595 cnt += 1; 595 cnt += 1;
596 if ((evsel->attr.sample_type & COMPAT_MASK) == 596 if ((evsel->attr.sample_type & COMPAT_MASK) ==
@@ -608,7 +608,7 @@ static void strip_fini(struct perf_inject *inject)
608 struct perf_evsel *evsel, *tmp; 608 struct perf_evsel *evsel, *tmp;
609 609
610 /* Remove non-synthesized evsels if possible */ 610 /* Remove non-synthesized evsels if possible */
611 evlist__for_each_safe(evlist, tmp, evsel) { 611 evlist__for_each_entry_safe(evlist, tmp, evsel) {
612 if (evsel->handler == drop_sample && 612 if (evsel->handler == drop_sample &&
613 ok_to_remove(evlist, evsel)) { 613 ok_to_remove(evlist, evsel)) {
614 pr_debug("Deleting %s\n", perf_evsel__name(evsel)); 614 pr_debug("Deleting %s\n", perf_evsel__name(evsel));
@@ -643,7 +643,7 @@ static int __cmd_inject(struct perf_inject *inject)
643 } else if (inject->sched_stat) { 643 } else if (inject->sched_stat) {
644 struct perf_evsel *evsel; 644 struct perf_evsel *evsel;
645 645
646 evlist__for_each(session->evlist, evsel) { 646 evlist__for_each_entry(session->evlist, evsel) {
647 const char *name = perf_evsel__name(evsel); 647 const char *name = perf_evsel__name(evsel);
648 648
649 if (!strcmp(name, "sched:sched_switch")) { 649 if (!strcmp(name, "sched:sched_switch")) {
@@ -748,6 +748,7 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
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,
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index c9cb3be47cff..fdde1bd3e306 100644
--- a/tools/perf/builtin-kmem.c
+++ b/tools/perf/builtin-kmem.c
@@ -4,7 +4,7 @@
4#include "util/evlist.h" 4#include "util/evlist.h"
5#include "util/evsel.h" 5#include "util/evsel.h"
6#include "util/util.h" 6#include "util/util.h"
7#include "util/cache.h" 7#include "util/config.h"
8#include "util/symbol.h" 8#include "util/symbol.h"
9#include "util/thread.h" 9#include "util/thread.h"
10#include "util/header.h" 10#include "util/header.h"
@@ -375,7 +375,7 @@ static u64 find_callsite(struct perf_evsel *evsel, struct perf_sample *sample)
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) {
@@ -608,6 +608,7 @@ static const struct {
608 const char *compact; 608 const char *compact;
609} gfp_compact_table[] = { 609} gfp_compact_table[] = {
610 { "GFP_TRANSHUGE", "THP" }, 610 { "GFP_TRANSHUGE", "THP" },
611 { "GFP_TRANSHUGE_LIGHT", "THL" },
611 { "GFP_HIGHUSER_MOVABLE", "HUM" }, 612 { "GFP_HIGHUSER_MOVABLE", "HUM" },
612 { "GFP_HIGHUSER", "HU" }, 613 { "GFP_HIGHUSER", "HU" },
613 { "GFP_USER", "U" }, 614 { "GFP_USER", "U" },
@@ -1354,7 +1355,7 @@ static int __cmd_kmem(struct perf_session *session)
1354 goto out; 1355 goto out;
1355 } 1356 }
1356 1357
1357 evlist__for_each(session->evlist, evsel) { 1358 evlist__for_each_entry(session->evlist, evsel) {
1358 if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") && 1359 if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") &&
1359 perf_evsel__field(evsel, "pfn")) { 1360 perf_evsel__field(evsel, "pfn")) {
1360 use_pfn = true; 1361 use_pfn = true;
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index bff666458b28..5e2127e04f83 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -982,13 +982,13 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
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.
989 * This command processes KVM tracepoints from host only 989 * This command processes KVM tracepoints from host only
990 */ 990 */
991 evlist__for_each(evlist, pos) { 991 evlist__for_each_entry(evlist, pos) {
992 struct perf_event_attr *attr = &pos->attr; 992 struct perf_event_attr *attr = &pos->attr;
993 993
994 /* make sure these *are* set */ 994 /* make sure these *are* set */
@@ -1018,13 +1018,13 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1018 err = perf_evlist__open(evlist); 1018 err = perf_evlist__open(evlist);
1019 if (err < 0) { 1019 if (err < 0) {
1020 printf("Couldn't create the events: %s\n", 1020 printf("Couldn't create the events: %s\n",
1021 strerror_r(errno, sbuf, sizeof(sbuf))); 1021 str_error_r(errno, sbuf, sizeof(sbuf)));
1022 goto out; 1022 goto out;
1023 } 1023 }
1024 1024
1025 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { 1025 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
1026 ui__error("Failed to mmap the events: %s\n", 1026 ui__error("Failed to mmap the events: %s\n",
1027 strerror_r(errno, sbuf, sizeof(sbuf))); 1027 str_error_r(errno, sbuf, sizeof(sbuf)));
1028 perf_evlist__close(evlist); 1028 perf_evlist__close(evlist);
1029 goto out; 1029 goto out;
1030 } 1030 }
@@ -1426,11 +1426,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1426 err = kvm_events_live_report(kvm); 1426 err = kvm_events_live_report(kvm);
1427 1427
1428out: 1428out:
1429 if (kvm->session) 1429 perf_session__delete(kvm->session);
1430 perf_session__delete(kvm->session);
1431 kvm->session = NULL; 1430 kvm->session = NULL;
1432 if (kvm->evlist) 1431 perf_evlist__delete(kvm->evlist);
1433 perf_evlist__delete(kvm->evlist);
1434 1432
1435 return err; 1433 return err;
1436} 1434}
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 5e22db4684b8..88ee419e5189 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -25,7 +25,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
25 OPT_END() 25 OPT_END()
26 }; 26 };
27 const char * const list_usage[] = { 27 const char * const list_usage[] = {
28 "perf list [hw|sw|cache|tracepoint|pmu|event_glob]", 28 "perf list [hw|sw|cache|tracepoint|pmu|sdt|event_glob]",
29 NULL 29 NULL
30 }; 30 };
31 31
@@ -62,6 +62,8 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
62 print_hwcache_events(NULL, raw_dump); 62 print_hwcache_events(NULL, raw_dump);
63 else if (strcmp(argv[i], "pmu") == 0) 63 else if (strcmp(argv[i], "pmu") == 0)
64 print_pmu_events(NULL, raw_dump); 64 print_pmu_events(NULL, raw_dump);
65 else if (strcmp(argv[i], "sdt") == 0)
66 print_sdt_events(NULL, NULL, raw_dump);
65 else if ((sep = strchr(argv[i], ':')) != NULL) { 67 else if ((sep = strchr(argv[i], ':')) != NULL) {
66 int sep_idx; 68 int sep_idx;
67 69
@@ -76,6 +78,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
76 78
77 s[sep_idx] = '\0'; 79 s[sep_idx] = '\0';
78 print_tracepoint_events(s, s + sep_idx + 1, raw_dump); 80 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
81 print_sdt_events(s, s + sep_idx + 1, raw_dump);
79 free(s); 82 free(s);
80 } else { 83 } else {
81 if (asprintf(&s, "*%s*", argv[i]) < 0) { 84 if (asprintf(&s, "*%s*", argv[i]) < 0) {
@@ -89,6 +92,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
89 print_hwcache_events(s, raw_dump); 92 print_hwcache_events(s, raw_dump);
90 print_pmu_events(s, raw_dump); 93 print_pmu_events(s, raw_dump);
91 print_tracepoint_events(NULL, s, raw_dump); 94 print_tracepoint_events(NULL, s, raw_dump);
95 print_sdt_events(NULL, s, raw_dump);
92 free(s); 96 free(s);
93 } 97 }
94 } 98 }
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 85db3be4b3cb..d1ce29be560e 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -62,19 +62,23 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
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),
70 OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads latency"),
69 OPT_INCR('v', "verbose", &verbose, 71 OPT_INCR('v', "verbose", &verbose,
70 "be more verbose (show counter open errors, etc)"), 72 "be more verbose (show counter open errors, etc)"),
73 OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"),
74 OPT_BOOLEAN('K', "--all-kernel", &all_kernel, "collect only kernel level data"),
71 OPT_END() 75 OPT_END()
72 }; 76 };
73 77
74 argc = parse_options(argc, argv, options, record_mem_usage, 78 argc = parse_options(argc, argv, options, record_mem_usage,
75 PARSE_OPT_STOP_AT_NON_OPTION); 79 PARSE_OPT_STOP_AT_NON_OPTION);
76 80
77 rec_argc = argc + 7; /* max number of arguments */ 81 rec_argc = argc + 9; /* max number of arguments */
78 rec_argv = calloc(rec_argc + 1, sizeof(char *)); 82 rec_argv = calloc(rec_argc + 1, sizeof(char *));
79 if (!rec_argv) 83 if (!rec_argv)
80 return -1; 84 return -1;
@@ -84,6 +88,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
84 if (mem->operation & MEM_OPERATION_LOAD) 88 if (mem->operation & MEM_OPERATION_LOAD)
85 perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; 89 perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
86 90
91 if (mem->operation & MEM_OPERATION_STORE)
92 perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
93
87 if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) 94 if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
88 rec_argv[i++] = "-W"; 95 rec_argv[i++] = "-W";
89 96
@@ -103,6 +110,12 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
103 rec_argv[i++] = perf_mem_events__name(j); 110 rec_argv[i++] = perf_mem_events__name(j);
104 }; 111 };
105 112
113 if (all_user)
114 rec_argv[i++] = "--all-user";
115
116 if (all_kernel)
117 rec_argv[i++] = "--all-kernel";
118
106 for (j = 0; j < argc; j++, i++) 119 for (j = 0; j < argc; j++, i++)
107 rec_argv[i] = argv[j]; 120 rec_argv[i] = argv[j];
108 121
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 9af859b28b15..ee5b42173ba3 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -44,7 +44,7 @@
44 44
45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*" 45#define DEFAULT_VAR_FILTER "!__k???tab_* & !__crc_*"
46#define DEFAULT_FUNC_FILTER "!_*" 46#define DEFAULT_FUNC_FILTER "!_*"
47#define DEFAULT_LIST_FILTER "*:*" 47#define DEFAULT_LIST_FILTER "*"
48 48
49/* Session management structure */ 49/* Session management structure */
50static struct { 50static struct {
@@ -308,7 +308,7 @@ static void pr_err_with_code(const char *msg, int err)
308 308
309 pr_err("%s", msg); 309 pr_err("%s", msg);
310 pr_debug(" Reason: %s (Code: %d)", 310 pr_debug(" Reason: %s (Code: %d)",
311 strerror_r(-err, sbuf, sizeof(sbuf)), err); 311 str_error_r(-err, sbuf, sizeof(sbuf)), err);
312 pr_err("\n"); 312 pr_err("\n");
313} 313}
314 314
@@ -363,6 +363,32 @@ out_cleanup:
363 return ret; 363 return ret;
364} 364}
365 365
366static int del_perf_probe_caches(struct strfilter *filter)
367{
368 struct probe_cache *cache;
369 struct strlist *bidlist;
370 struct str_node *nd;
371 int ret;
372
373 bidlist = build_id_cache__list_all(false);
374 if (!bidlist) {
375 ret = -errno;
376 pr_debug("Failed to get buildids: %d\n", ret);
377 return ret ?: -ENOMEM;
378 }
379
380 strlist__for_each_entry(nd, bidlist) {
381 cache = probe_cache__new(nd->s);
382 if (!cache)
383 continue;
384 if (probe_cache__filter_purge(cache, filter) < 0 ||
385 probe_cache__commit(cache) < 0)
386 pr_warning("Failed to remove entries for %s\n", nd->s);
387 probe_cache__delete(cache);
388 }
389 return 0;
390}
391
366static int perf_del_probe_events(struct strfilter *filter) 392static int perf_del_probe_events(struct strfilter *filter)
367{ 393{
368 int ret, ret2, ufd = -1, kfd = -1; 394 int ret, ret2, ufd = -1, kfd = -1;
@@ -375,6 +401,9 @@ static int perf_del_probe_events(struct strfilter *filter)
375 401
376 pr_debug("Delete filter: \'%s\'\n", str); 402 pr_debug("Delete filter: \'%s\'\n", str);
377 403
404 if (probe_conf.cache)
405 return del_perf_probe_caches(filter);
406
378 /* Get current event names */ 407 /* Get current event names */
379 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); 408 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
380 if (ret < 0) 409 if (ret < 0)
@@ -389,7 +418,7 @@ static int perf_del_probe_events(struct strfilter *filter)
389 418
390 ret = probe_file__get_events(kfd, filter, klist); 419 ret = probe_file__get_events(kfd, filter, klist);
391 if (ret == 0) { 420 if (ret == 0) {
392 strlist__for_each(ent, klist) 421 strlist__for_each_entry(ent, klist)
393 pr_info("Removed event: %s\n", ent->s); 422 pr_info("Removed event: %s\n", ent->s);
394 423
395 ret = probe_file__del_strlist(kfd, klist); 424 ret = probe_file__del_strlist(kfd, klist);
@@ -399,7 +428,7 @@ static int perf_del_probe_events(struct strfilter *filter)
399 428
400 ret2 = probe_file__get_events(ufd, filter, ulist); 429 ret2 = probe_file__get_events(ufd, filter, ulist);
401 if (ret2 == 0) { 430 if (ret2 == 0) {
402 strlist__for_each(ent, ulist) 431 strlist__for_each_entry(ent, ulist)
403 pr_info("Removed event: %s\n", ent->s); 432 pr_info("Removed event: %s\n", ent->s);
404 433
405 ret2 = probe_file__del_strlist(ufd, ulist); 434 ret2 = probe_file__del_strlist(ufd, ulist);
@@ -512,6 +541,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
512 "Enable symbol demangling"), 541 "Enable symbol demangling"),
513 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 542 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
514 "Enable kernel symbol demangling"), 543 "Enable kernel symbol demangling"),
544 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
515 OPT_END() 545 OPT_END()
516 }; 546 };
517 int ret; 547 int ret;
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 515510ecc76a..6355902fbfc8 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -13,6 +13,7 @@
13#include "util/util.h" 13#include "util/util.h"
14#include <subcmd/parse-options.h> 14#include <subcmd/parse-options.h>
15#include "util/parse-events.h" 15#include "util/parse-events.h"
16#include "util/config.h"
16 17
17#include "util/callchain.h" 18#include "util/callchain.h"
18#include "util/cgroup.h" 19#include "util/cgroup.h"
@@ -29,15 +30,18 @@
29#include "util/data.h" 30#include "util/data.h"
30#include "util/perf_regs.h" 31#include "util/perf_regs.h"
31#include "util/auxtrace.h" 32#include "util/auxtrace.h"
33#include "util/tsc.h"
32#include "util/parse-branch-options.h" 34#include "util/parse-branch-options.h"
33#include "util/parse-regs-options.h" 35#include "util/parse-regs-options.h"
34#include "util/llvm-utils.h" 36#include "util/llvm-utils.h"
35#include "util/bpf-loader.h" 37#include "util/bpf-loader.h"
38#include "util/trigger.h"
36#include "asm/bug.h" 39#include "asm/bug.h"
37 40
38#include <unistd.h> 41#include <unistd.h>
39#include <sched.h> 42#include <sched.h>
40#include <sys/mman.h> 43#include <sys/mman.h>
44#include <asm/bug.h>
41 45
42 46
43struct record { 47struct record {
@@ -55,6 +59,8 @@ struct record {
55 bool no_buildid_cache; 59 bool no_buildid_cache;
56 bool no_buildid_cache_set; 60 bool no_buildid_cache_set;
57 bool buildid_all; 61 bool buildid_all;
62 bool timestamp_filename;
63 bool switch_output;
58 unsigned long long samples; 64 unsigned long long samples;
59}; 65};
60 66
@@ -78,27 +84,87 @@ static int process_synthesized_event(struct perf_tool *tool,
78 return record__write(rec, event, event->header.size); 84 return record__write(rec, event, event->header.size);
79} 85}
80 86
81static int record__mmap_read(struct record *rec, int idx) 87static int
88backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
89{
90 struct perf_event_header *pheader;
91 u64 evt_head = head;
92 int size = mask + 1;
93
94 pr_debug2("backward_rb_find_range: buf=%p, head=%"PRIx64"\n", buf, head);
95 pheader = (struct perf_event_header *)(buf + (head & mask));
96 *start = head;
97 while (true) {
98 if (evt_head - head >= (unsigned int)size) {
99 pr_debug("Finshed reading backward ring buffer: rewind\n");
100 if (evt_head - head > (unsigned int)size)
101 evt_head -= pheader->size;
102 *end = evt_head;
103 return 0;
104 }
105
106 pheader = (struct perf_event_header *)(buf + (evt_head & mask));
107
108 if (pheader->size == 0) {
109 pr_debug("Finshed reading backward ring buffer: get start\n");
110 *end = evt_head;
111 return 0;
112 }
113
114 evt_head += pheader->size;
115 pr_debug3("move evt_head: %"PRIx64"\n", evt_head);
116 }
117 WARN_ONCE(1, "Shouldn't get here\n");
118 return -1;
119}
120
121static int
122rb_find_range(void *data, int mask, u64 head, u64 old,
123 u64 *start, u64 *end, bool backward)
124{
125 if (!backward) {
126 *start = old;
127 *end = head;
128 return 0;
129 }
130
131 return backward_rb_find_range(data, mask, head, start, end);
132}
133
134static int
135record__mmap_read(struct record *rec, struct perf_mmap *md,
136 bool overwrite, bool backward)
82{ 137{
83 struct perf_mmap *md = &rec->evlist->mmap[idx];
84 u64 head = perf_mmap__read_head(md); 138 u64 head = perf_mmap__read_head(md);
85 u64 old = md->prev; 139 u64 old = md->prev;
140 u64 end = head, start = old;
86 unsigned char *data = md->base + page_size; 141 unsigned char *data = md->base + page_size;
87 unsigned long size; 142 unsigned long size;
88 void *buf; 143 void *buf;
89 int rc = 0; 144 int rc = 0;
90 145
91 if (old == head) 146 if (rb_find_range(data, md->mask, head,
147 old, &start, &end, backward))
148 return -1;
149
150 if (start == end)
92 return 0; 151 return 0;
93 152
94 rec->samples++; 153 rec->samples++;
95 154
96 size = head - old; 155 size = end - start;
156 if (size > (unsigned long)(md->mask) + 1) {
157 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
158
159 md->prev = head;
160 perf_mmap__consume(md, overwrite || backward);
161 return 0;
162 }
97 163
98 if ((old & md->mask) + size != (head & md->mask)) { 164 if ((start & md->mask) + size != (end & md->mask)) {
99 buf = &data[old & md->mask]; 165 buf = &data[start & md->mask];
100 size = md->mask + 1 - (old & md->mask); 166 size = md->mask + 1 - (start & md->mask);
101 old += size; 167 start += size;
102 168
103 if (record__write(rec, buf, size) < 0) { 169 if (record__write(rec, buf, size) < 0) {
104 rc = -1; 170 rc = -1;
@@ -106,17 +172,17 @@ static int record__mmap_read(struct record *rec, int idx)
106 } 172 }
107 } 173 }
108 174
109 buf = &data[old & md->mask]; 175 buf = &data[start & md->mask];
110 size = head - old; 176 size = end - start;
111 old += size; 177 start += size;
112 178
113 if (record__write(rec, buf, size) < 0) { 179 if (record__write(rec, buf, size) < 0) {
114 rc = -1; 180 rc = -1;
115 goto out; 181 goto out;
116 } 182 }
117 183
118 md->prev = old; 184 md->prev = head;
119 perf_evlist__mmap_consume(rec->evlist, idx); 185 perf_mmap__consume(md, overwrite || backward);
120out: 186out:
121 return rc; 187 return rc;
122} 188}
@@ -124,9 +190,10 @@ out:
124static volatile int done; 190static volatile int done;
125static volatile int signr = -1; 191static volatile int signr = -1;
126static volatile int child_finished; 192static volatile int child_finished;
127static volatile int auxtrace_snapshot_enabled; 193
128static volatile int auxtrace_snapshot_err;
129static volatile int auxtrace_record__snapshot_started; 194static volatile int auxtrace_record__snapshot_started;
195static DEFINE_TRIGGER(auxtrace_snapshot_trigger);
196static DEFINE_TRIGGER(switch_output_trigger);
130 197
131static void sig_handler(int sig) 198static void sig_handler(int sig)
132{ 199{
@@ -244,11 +311,12 @@ static void record__read_auxtrace_snapshot(struct record *rec)
244{ 311{
245 pr_debug("Recording AUX area tracing snapshot\n"); 312 pr_debug("Recording AUX area tracing snapshot\n");
246 if (record__auxtrace_read_snapshot_all(rec) < 0) { 313 if (record__auxtrace_read_snapshot_all(rec) < 0) {
247 auxtrace_snapshot_err = -1; 314 trigger_error(&auxtrace_snapshot_trigger);
248 } else { 315 } else {
249 auxtrace_snapshot_err = auxtrace_record__snapshot_finish(rec->itr); 316 if (auxtrace_record__snapshot_finish(rec->itr))
250 if (!auxtrace_snapshot_err) 317 trigger_error(&auxtrace_snapshot_trigger);
251 auxtrace_snapshot_enabled = 1; 318 else
319 trigger_ready(&auxtrace_snapshot_trigger);
252 } 320 }
253} 321}
254 322
@@ -274,6 +342,40 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
274 342
275#endif 343#endif
276 344
345static int record__mmap_evlist(struct record *rec,
346 struct perf_evlist *evlist)
347{
348 struct record_opts *opts = &rec->opts;
349 char msg[512];
350
351 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
352 opts->auxtrace_mmap_pages,
353 opts->auxtrace_snapshot_mode) < 0) {
354 if (errno == EPERM) {
355 pr_err("Permission error mapping pages.\n"
356 "Consider increasing "
357 "/proc/sys/kernel/perf_event_mlock_kb,\n"
358 "or try again with a smaller value of -m/--mmap_pages.\n"
359 "(current value: %u,%u)\n",
360 opts->mmap_pages, opts->auxtrace_mmap_pages);
361 return -errno;
362 } else {
363 pr_err("failed to mmap with %d (%s)\n", errno,
364 str_error_r(errno, msg, sizeof(msg)));
365 if (errno)
366 return -errno;
367 else
368 return -EINVAL;
369 }
370 }
371 return 0;
372}
373
374static int record__mmap(struct record *rec)
375{
376 return record__mmap_evlist(rec, rec->evlist);
377}
378
277static int record__open(struct record *rec) 379static int record__open(struct record *rec)
278{ 380{
279 char msg[512]; 381 char msg[512];
@@ -283,9 +385,9 @@ static int record__open(struct record *rec)
283 struct record_opts *opts = &rec->opts; 385 struct record_opts *opts = &rec->opts;
284 int rc = 0; 386 int rc = 0;
285 387
286 perf_evlist__config(evlist, opts); 388 perf_evlist__config(evlist, opts, &callchain_param);
287 389
288 evlist__for_each(evlist, pos) { 390 evlist__for_each_entry(evlist, pos) {
289try_again: 391try_again:
290 if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 392 if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
291 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 393 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
@@ -305,32 +407,14 @@ try_again:
305 if (perf_evlist__apply_filters(evlist, &pos)) { 407 if (perf_evlist__apply_filters(evlist, &pos)) {
306 error("failed to set filter \"%s\" on event %s with %d (%s)\n", 408 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
307 pos->filter, perf_evsel__name(pos), errno, 409 pos->filter, perf_evsel__name(pos), errno,
308 strerror_r(errno, msg, sizeof(msg))); 410 str_error_r(errno, msg, sizeof(msg)));
309 rc = -1; 411 rc = -1;
310 goto out; 412 goto out;
311 } 413 }
312 414
313 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 415 rc = record__mmap(rec);
314 opts->auxtrace_mmap_pages, 416 if (rc)
315 opts->auxtrace_snapshot_mode) < 0) {
316 if (errno == EPERM) {
317 pr_err("Permission error mapping pages.\n"
318 "Consider increasing "
319 "/proc/sys/kernel/perf_event_mlock_kb,\n"
320 "or try again with a smaller value of -m/--mmap_pages.\n"
321 "(current value: %u,%u)\n",
322 opts->mmap_pages, opts->auxtrace_mmap_pages);
323 rc = -errno;
324 } else {
325 pr_err("failed to mmap with %d (%s)\n", errno,
326 strerror_r(errno, msg, sizeof(msg)));
327 if (errno)
328 rc = -errno;
329 else
330 rc = -EINVAL;
331 }
332 goto out; 417 goto out;
333 }
334 418
335 session->evlist = evlist; 419 session->evlist = evlist;
336 perf_session__set_id_hdr_size(session); 420 perf_session__set_id_hdr_size(session);
@@ -414,17 +498,30 @@ static struct perf_event_header finished_round_event = {
414 .type = PERF_RECORD_FINISHED_ROUND, 498 .type = PERF_RECORD_FINISHED_ROUND,
415}; 499};
416 500
417static int record__mmap_read_all(struct record *rec) 501static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
502 bool backward)
418{ 503{
419 u64 bytes_written = rec->bytes_written; 504 u64 bytes_written = rec->bytes_written;
420 int i; 505 int i;
421 int rc = 0; 506 int rc = 0;
507 struct perf_mmap *maps;
422 508
423 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 509 if (!evlist)
424 struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 510 return 0;
425 511
426 if (rec->evlist->mmap[i].base) { 512 maps = backward ? evlist->backward_mmap : evlist->mmap;
427 if (record__mmap_read(rec, i) != 0) { 513 if (!maps)
514 return 0;
515
516 if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
517 return 0;
518
519 for (i = 0; i < evlist->nr_mmaps; i++) {
520 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
521
522 if (maps[i].base) {
523 if (record__mmap_read(rec, &maps[i],
524 evlist->overwrite, backward) != 0) {
428 rc = -1; 525 rc = -1;
429 goto out; 526 goto out;
430 } 527 }
@@ -444,10 +541,23 @@ static int record__mmap_read_all(struct record *rec)
444 if (bytes_written != rec->bytes_written) 541 if (bytes_written != rec->bytes_written)
445 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 542 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
446 543
544 if (backward)
545 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
447out: 546out:
448 return rc; 547 return rc;
449} 548}
450 549
550static int record__mmap_read_all(struct record *rec)
551{
552 int err;
553
554 err = record__mmap_read_evlist(rec, rec->evlist, false);
555 if (err)
556 return err;
557
558 return record__mmap_read_evlist(rec, rec->evlist, true);
559}
560
451static void record__init_features(struct record *rec) 561static void record__init_features(struct record *rec)
452{ 562{
453 struct perf_session *session = rec->session; 563 struct perf_session *session = rec->session;
@@ -494,6 +604,80 @@ record__finish_output(struct record *rec)
494 return; 604 return;
495} 605}
496 606
607static int record__synthesize_workload(struct record *rec, bool tail)
608{
609 struct {
610 struct thread_map map;
611 struct thread_map_data map_data;
612 } thread_map;
613
614 if (rec->opts.tail_synthesize != tail)
615 return 0;
616
617 thread_map.map.nr = 1;
618 thread_map.map.map[0].pid = rec->evlist->workload.pid;
619 thread_map.map.map[0].comm = NULL;
620 return perf_event__synthesize_thread_map(&rec->tool, &thread_map.map,
621 process_synthesized_event,
622 &rec->session->machines.host,
623 rec->opts.sample_address,
624 rec->opts.proc_map_timeout);
625}
626
627static int record__synthesize(struct record *rec, bool tail);
628
629static int
630record__switch_output(struct record *rec, bool at_exit)
631{
632 struct perf_data_file *file = &rec->file;
633 int fd, err;
634
635 /* Same Size: "2015122520103046"*/
636 char timestamp[] = "InvalidTimestamp";
637
638 record__synthesize(rec, true);
639 if (target__none(&rec->opts.target))
640 record__synthesize_workload(rec, true);
641
642 rec->samples = 0;
643 record__finish_output(rec);
644 err = fetch_current_timestamp(timestamp, sizeof(timestamp));
645 if (err) {
646 pr_err("Failed to get current timestamp\n");
647 return -EINVAL;
648 }
649
650 fd = perf_data_file__switch(file, timestamp,
651 rec->session->header.data_offset,
652 at_exit);
653 if (fd >= 0 && !at_exit) {
654 rec->bytes_written = 0;
655 rec->session->header.data_size = 0;
656 }
657
658 if (!quiet)
659 fprintf(stderr, "[ perf record: Dump %s.%s ]\n",
660 file->path, timestamp);
661
662 /* Output tracking events */
663 if (!at_exit) {
664 record__synthesize(rec, false);
665
666 /*
667 * In 'perf record --switch-output' without -a,
668 * record__synthesize() in record__switch_output() won't
669 * generate tracking events because there's no thread_map
670 * in evlist. Which causes newly created perf.data doesn't
671 * contain map and comm information.
672 * Create a fake thread_map and directly call
673 * perf_event__synthesize_thread_map() for those events.
674 */
675 if (target__none(&rec->opts.target))
676 record__synthesize_workload(rec, false);
677 }
678 return fd;
679}
680
497static volatile int workload_exec_errno; 681static volatile int workload_exec_errno;
498 682
499/* 683/*
@@ -512,7 +696,38 @@ static void workload_exec_failed_signal(int signo __maybe_unused,
512 696
513static void snapshot_sig_handler(int sig); 697static void snapshot_sig_handler(int sig);
514 698
515static int record__synthesize(struct record *rec) 699int __weak
700perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused,
701 struct perf_tool *tool __maybe_unused,
702 perf_event__handler_t process __maybe_unused,
703 struct machine *machine __maybe_unused)
704{
705 return 0;
706}
707
708static const struct perf_event_mmap_page *
709perf_evlist__pick_pc(struct perf_evlist *evlist)
710{
711 if (evlist) {
712 if (evlist->mmap && evlist->mmap[0].base)
713 return evlist->mmap[0].base;
714 if (evlist->backward_mmap && evlist->backward_mmap[0].base)
715 return evlist->backward_mmap[0].base;
716 }
717 return NULL;
718}
719
720static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
721{
722 const struct perf_event_mmap_page *pc;
723
724 pc = perf_evlist__pick_pc(rec->evlist);
725 if (pc)
726 return pc;
727 return NULL;
728}
729
730static int record__synthesize(struct record *rec, bool tail)
516{ 731{
517 struct perf_session *session = rec->session; 732 struct perf_session *session = rec->session;
518 struct machine *machine = &session->machines.host; 733 struct machine *machine = &session->machines.host;
@@ -522,6 +737,9 @@ static int record__synthesize(struct record *rec)
522 int fd = perf_data_file__fd(file); 737 int fd = perf_data_file__fd(file);
523 int err = 0; 738 int err = 0;
524 739
740 if (rec->opts.tail_synthesize != tail)
741 return 0;
742
525 if (file->is_pipe) { 743 if (file->is_pipe) {
526 err = perf_event__synthesize_attrs(tool, session, 744 err = perf_event__synthesize_attrs(tool, session,
527 process_synthesized_event); 745 process_synthesized_event);
@@ -549,6 +767,11 @@ static int record__synthesize(struct record *rec)
549 } 767 }
550 } 768 }
551 769
770 err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
771 process_synthesized_event, machine);
772 if (err)
773 goto out;
774
552 if (rec->opts.full_auxtrace) { 775 if (rec->opts.full_auxtrace) {
553 err = perf_event__synthesize_auxtrace_info(rec->itr, tool, 776 err = perf_event__synthesize_auxtrace_info(rec->itr, tool,
554 session, process_synthesized_event); 777 session, process_synthesized_event);
@@ -600,10 +823,16 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
600 signal(SIGCHLD, sig_handler); 823 signal(SIGCHLD, sig_handler);
601 signal(SIGINT, sig_handler); 824 signal(SIGINT, sig_handler);
602 signal(SIGTERM, sig_handler); 825 signal(SIGTERM, sig_handler);
603 if (rec->opts.auxtrace_snapshot_mode) 826
827 if (rec->opts.auxtrace_snapshot_mode || rec->switch_output) {
604 signal(SIGUSR2, snapshot_sig_handler); 828 signal(SIGUSR2, snapshot_sig_handler);
605 else 829 if (rec->opts.auxtrace_snapshot_mode)
830 trigger_on(&auxtrace_snapshot_trigger);
831 if (rec->switch_output)
832 trigger_on(&switch_output_trigger);
833 } else {
606 signal(SIGUSR2, SIG_IGN); 834 signal(SIGUSR2, SIG_IGN);
835 }
607 836
608 session = perf_session__new(file, false, tool); 837 session = perf_session__new(file, false, tool);
609 if (session == NULL) { 838 if (session == NULL) {
@@ -674,7 +903,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
674 903
675 machine = &session->machines.host; 904 machine = &session->machines.host;
676 905
677 err = record__synthesize(rec); 906 err = record__synthesize(rec, false);
678 if (err < 0) 907 if (err < 0)
679 goto out_child; 908 goto out_child;
680 909
@@ -729,27 +958,74 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
729 perf_evlist__enable(rec->evlist); 958 perf_evlist__enable(rec->evlist);
730 } 959 }
731 960
732 auxtrace_snapshot_enabled = 1; 961 trigger_ready(&auxtrace_snapshot_trigger);
962 trigger_ready(&switch_output_trigger);
733 for (;;) { 963 for (;;) {
734 unsigned long long hits = rec->samples; 964 unsigned long long hits = rec->samples;
735 965
966 /*
967 * rec->evlist->bkw_mmap_state is possible to be
968 * BKW_MMAP_EMPTY here: when done == true and
969 * hits != rec->samples in previous round.
970 *
971 * perf_evlist__toggle_bkw_mmap ensure we never
972 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
973 */
974 if (trigger_is_hit(&switch_output_trigger) || done || draining)
975 perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
976
736 if (record__mmap_read_all(rec) < 0) { 977 if (record__mmap_read_all(rec) < 0) {
737 auxtrace_snapshot_enabled = 0; 978 trigger_error(&auxtrace_snapshot_trigger);
979 trigger_error(&switch_output_trigger);
738 err = -1; 980 err = -1;
739 goto out_child; 981 goto out_child;
740 } 982 }
741 983
742 if (auxtrace_record__snapshot_started) { 984 if (auxtrace_record__snapshot_started) {
743 auxtrace_record__snapshot_started = 0; 985 auxtrace_record__snapshot_started = 0;
744 if (!auxtrace_snapshot_err) 986 if (!trigger_is_error(&auxtrace_snapshot_trigger))
745 record__read_auxtrace_snapshot(rec); 987 record__read_auxtrace_snapshot(rec);
746 if (auxtrace_snapshot_err) { 988 if (trigger_is_error(&auxtrace_snapshot_trigger)) {
747 pr_err("AUX area tracing snapshot failed\n"); 989 pr_err("AUX area tracing snapshot failed\n");
748 err = -1; 990 err = -1;
749 goto out_child; 991 goto out_child;
750 } 992 }
751 } 993 }
752 994
995 if (trigger_is_hit(&switch_output_trigger)) {
996 /*
997 * If switch_output_trigger is hit, the data in
998 * overwritable ring buffer should have been collected,
999 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
1000 *
1001 * If SIGUSR2 raise after or during record__mmap_read_all(),
1002 * record__mmap_read_all() didn't collect data from
1003 * overwritable ring buffer. Read again.
1004 */
1005 if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
1006 continue;
1007 trigger_ready(&switch_output_trigger);
1008
1009 /*
1010 * Reenable events in overwrite ring buffer after
1011 * record__mmap_read_all(): we should have collected
1012 * data from it.
1013 */
1014 perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
1015
1016 if (!quiet)
1017 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
1018 waking);
1019 waking = 0;
1020 fd = record__switch_output(rec, false);
1021 if (fd < 0) {
1022 pr_err("Failed to switch to new file\n");
1023 trigger_error(&switch_output_trigger);
1024 err = fd;
1025 goto out_child;
1026 }
1027 }
1028
753 if (hits == rec->samples) { 1029 if (hits == rec->samples) {
754 if (done || draining) 1030 if (done || draining)
755 break; 1031 break;
@@ -772,16 +1048,17 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
772 * disable events in this case. 1048 * disable events in this case.
773 */ 1049 */
774 if (done && !disabled && !target__none(&opts->target)) { 1050 if (done && !disabled && !target__none(&opts->target)) {
775 auxtrace_snapshot_enabled = 0; 1051 trigger_off(&auxtrace_snapshot_trigger);
776 perf_evlist__disable(rec->evlist); 1052 perf_evlist__disable(rec->evlist);
777 disabled = true; 1053 disabled = true;
778 } 1054 }
779 } 1055 }
780 auxtrace_snapshot_enabled = 0; 1056 trigger_off(&auxtrace_snapshot_trigger);
1057 trigger_off(&switch_output_trigger);
781 1058
782 if (forks && workload_exec_errno) { 1059 if (forks && workload_exec_errno) {
783 char msg[STRERR_BUFSIZE]; 1060 char msg[STRERR_BUFSIZE];
784 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 1061 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
785 pr_err("Workload failed: %s\n", emsg); 1062 pr_err("Workload failed: %s\n", emsg);
786 err = -1; 1063 err = -1;
787 goto out_child; 1064 goto out_child;
@@ -790,6 +1067,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
790 if (!quiet) 1067 if (!quiet)
791 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 1068 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
792 1069
1070 if (target__none(&rec->opts.target))
1071 record__synthesize_workload(rec, true);
1072
793out_child: 1073out_child:
794 if (forks) { 1074 if (forks) {
795 int exit_status; 1075 int exit_status;
@@ -808,14 +1088,26 @@ out_child:
808 } else 1088 } else
809 status = err; 1089 status = err;
810 1090
1091 record__synthesize(rec, true);
811 /* this will be recalculated during process_buildids() */ 1092 /* this will be recalculated during process_buildids() */
812 rec->samples = 0; 1093 rec->samples = 0;
813 1094
814 if (!err) 1095 if (!err) {
815 record__finish_output(rec); 1096 if (!rec->timestamp_filename) {
1097 record__finish_output(rec);
1098 } else {
1099 fd = record__switch_output(rec, true);
1100 if (fd < 0) {
1101 status = fd;
1102 goto out_delete_session;
1103 }
1104 }
1105 }
816 1106
817 if (!err && !quiet) { 1107 if (!err && !quiet) {
818 char samples[128]; 1108 char samples[128];
1109 const char *postfix = rec->timestamp_filename ?
1110 ".<timestamp>" : "";
819 1111
820 if (rec->samples && !rec->opts.full_auxtrace) 1112 if (rec->samples && !rec->opts.full_auxtrace)
821 scnprintf(samples, sizeof(samples), 1113 scnprintf(samples, sizeof(samples),
@@ -823,9 +1115,9 @@ out_child:
823 else 1115 else
824 samples[0] = '\0'; 1116 samples[0] = '\0';
825 1117
826 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s ]\n", 1118 fprintf(stderr, "[ perf record: Captured and wrote %.3f MB %s%s%s ]\n",
827 perf_data_file__size(file) / 1024.0 / 1024.0, 1119 perf_data_file__size(file) / 1024.0 / 1024.0,
828 file->path, samples); 1120 file->path, postfix, samples);
829 } 1121 }
830 1122
831out_delete_session: 1123out_delete_session:
@@ -833,58 +1125,61 @@ out_delete_session:
833 return status; 1125 return status;
834} 1126}
835 1127
836static void callchain_debug(void) 1128static void callchain_debug(struct callchain_param *callchain)
837{ 1129{
838 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" }; 1130 static const char *str[CALLCHAIN_MAX] = { "NONE", "FP", "DWARF", "LBR" };
839 1131
840 pr_debug("callchain: type %s\n", str[callchain_param.record_mode]); 1132 pr_debug("callchain: type %s\n", str[callchain->record_mode]);
841 1133
842 if (callchain_param.record_mode == CALLCHAIN_DWARF) 1134 if (callchain->record_mode == CALLCHAIN_DWARF)
843 pr_debug("callchain: stack dump size %d\n", 1135 pr_debug("callchain: stack dump size %d\n",
844 callchain_param.dump_size); 1136 callchain->dump_size);
845} 1137}
846 1138
847int record_parse_callchain_opt(const struct option *opt, 1139int record_opts__parse_callchain(struct record_opts *record,
848 const char *arg, 1140 struct callchain_param *callchain,
849 int unset) 1141 const char *arg, bool unset)
850{ 1142{
851 int ret; 1143 int ret;
852 struct record_opts *record = (struct record_opts *)opt->value; 1144 callchain->enabled = !unset;
853
854 record->callgraph_set = true;
855 callchain_param.enabled = !unset;
856 1145
857 /* --no-call-graph */ 1146 /* --no-call-graph */
858 if (unset) { 1147 if (unset) {
859 callchain_param.record_mode = CALLCHAIN_NONE; 1148 callchain->record_mode = CALLCHAIN_NONE;
860 pr_debug("callchain: disabled\n"); 1149 pr_debug("callchain: disabled\n");
861 return 0; 1150 return 0;
862 } 1151 }
863 1152
864 ret = parse_callchain_record_opt(arg, &callchain_param); 1153 ret = parse_callchain_record_opt(arg, callchain);
865 if (!ret) { 1154 if (!ret) {
866 /* Enable data address sampling for DWARF unwind. */ 1155 /* Enable data address sampling for DWARF unwind. */
867 if (callchain_param.record_mode == CALLCHAIN_DWARF) 1156 if (callchain->record_mode == CALLCHAIN_DWARF)
868 record->sample_address = true; 1157 record->sample_address = true;
869 callchain_debug(); 1158 callchain_debug(callchain);
870 } 1159 }
871 1160
872 return ret; 1161 return ret;
873} 1162}
874 1163
1164int record_parse_callchain_opt(const struct option *opt,
1165 const char *arg,
1166 int unset)
1167{
1168 return record_opts__parse_callchain(opt->value, &callchain_param, arg, unset);
1169}
1170
875int record_callchain_opt(const struct option *opt, 1171int record_callchain_opt(const struct option *opt,
876 const char *arg __maybe_unused, 1172 const char *arg __maybe_unused,
877 int unset __maybe_unused) 1173 int unset __maybe_unused)
878{ 1174{
879 struct record_opts *record = (struct record_opts *)opt->value; 1175 struct callchain_param *callchain = opt->value;
880 1176
881 record->callgraph_set = true; 1177 callchain->enabled = true;
882 callchain_param.enabled = true;
883 1178
884 if (callchain_param.record_mode == CALLCHAIN_NONE) 1179 if (callchain->record_mode == CALLCHAIN_NONE)
885 callchain_param.record_mode = CALLCHAIN_FP; 1180 callchain->record_mode = CALLCHAIN_FP;
886 1181
887 callchain_debug(); 1182 callchain_debug(callchain);
888 return 0; 1183 return 0;
889} 1184}
890 1185
@@ -1080,6 +1375,8 @@ static struct record record = {
1080const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 1375const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
1081 "\n\t\t\t\tDefault: fp"; 1376 "\n\t\t\t\tDefault: fp";
1082 1377
1378static bool dry_run;
1379
1083/* 1380/*
1084 * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1381 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1085 * with it and switch to use the library functions in perf_evlist that came 1382 * with it and switch to use the library functions in perf_evlist that came
@@ -1116,13 +1413,16 @@ struct option __record_options[] = {
1116 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 1413 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
1117 &record.opts.no_inherit_set, 1414 &record.opts.no_inherit_set,
1118 "child tasks do not inherit counters"), 1415 "child tasks do not inherit counters"),
1416 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1417 "synthesize non-sample events at the end of output"),
1418 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1119 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1419 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1120 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1420 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1121 "number of mmap data pages and AUX area tracing mmap pages", 1421 "number of mmap data pages and AUX area tracing mmap pages",
1122 record__parse_mmap_pages), 1422 record__parse_mmap_pages),
1123 OPT_BOOLEAN(0, "group", &record.opts.group, 1423 OPT_BOOLEAN(0, "group", &record.opts.group,
1124 "put the counters into a counter group"), 1424 "put the counters into a counter group"),
1125 OPT_CALLBACK_NOOPT('g', NULL, &record.opts, 1425 OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
1126 NULL, "enables call-graph recording" , 1426 NULL, "enables call-graph recording" ,
1127 &record_callchain_opt), 1427 &record_callchain_opt),
1128 OPT_CALLBACK(0, "call-graph", &record.opts, 1428 OPT_CALLBACK(0, "call-graph", &record.opts,
@@ -1134,6 +1434,7 @@ struct option __record_options[] = {
1134 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1434 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1135 "per thread counts"), 1435 "per thread counts"),
1136 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1436 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
1437 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
1137 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 1438 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
1138 &record.opts.sample_time_set, 1439 &record.opts.sample_time_set,
1139 "Record the sample timestamps"), 1440 "Record the sample timestamps"),
@@ -1195,6 +1496,12 @@ struct option __record_options[] = {
1195 "file", "vmlinux pathname"), 1496 "file", "vmlinux pathname"),
1196 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all, 1497 OPT_BOOLEAN(0, "buildid-all", &record.buildid_all,
1197 "Record build-id of all DSOs regardless of hits"), 1498 "Record build-id of all DSOs regardless of hits"),
1499 OPT_BOOLEAN(0, "timestamp-filename", &record.timestamp_filename,
1500 "append timestamp to output filename"),
1501 OPT_BOOLEAN(0, "switch-output", &record.switch_output,
1502 "Switch output when receive SIGUSR2"),
1503 OPT_BOOLEAN(0, "dry-run", &dry_run,
1504 "Parse options then exit"),
1198 OPT_END() 1505 OPT_END()
1199}; 1506};
1200 1507
@@ -1250,6 +1557,9 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1250 return -EINVAL; 1557 return -EINVAL;
1251 } 1558 }
1252 1559
1560 if (rec->switch_output)
1561 rec->timestamp_filename = true;
1562
1253 if (!rec->itr) { 1563 if (!rec->itr) {
1254 rec->itr = auxtrace_record__init(rec->evlist, &err); 1564 rec->itr = auxtrace_record__init(rec->evlist, &err);
1255 if (err) 1565 if (err)
@@ -1261,6 +1571,17 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1261 if (err) 1571 if (err)
1262 return err; 1572 return err;
1263 1573
1574 if (dry_run)
1575 return 0;
1576
1577 err = bpf__setup_stdout(rec->evlist);
1578 if (err) {
1579 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1580 pr_err("ERROR: Setup BPF stdout failed: %s\n",
1581 errbuf);
1582 return err;
1583 }
1584
1264 err = -ENOMEM; 1585 err = -ENOMEM;
1265 1586
1266 symbol__init(NULL); 1587 symbol__init(NULL);
@@ -1275,8 +1596,39 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1275"If some relocation was applied (e.g. kexec) symbols may be misresolved\n" 1596"If some relocation was applied (e.g. kexec) symbols may be misresolved\n"
1276"even with a suitable vmlinux or kallsyms file.\n\n"); 1597"even with a suitable vmlinux or kallsyms file.\n\n");
1277 1598
1278 if (rec->no_buildid_cache || rec->no_buildid) 1599 if (rec->no_buildid_cache || rec->no_buildid) {
1279 disable_buildid_cache(); 1600 disable_buildid_cache();
1601 } else if (rec->switch_output) {
1602 /*
1603 * In 'perf record --switch-output', disable buildid
1604 * generation by default to reduce data file switching
1605 * overhead. Still generate buildid if they are required
1606 * explicitly using
1607 *
1608 * perf record --signal-trigger --no-no-buildid \
1609 * --no-no-buildid-cache
1610 *
1611 * Following code equals to:
1612 *
1613 * if ((rec->no_buildid || !rec->no_buildid_set) &&
1614 * (rec->no_buildid_cache || !rec->no_buildid_cache_set))
1615 * disable_buildid_cache();
1616 */
1617 bool disable = true;
1618
1619 if (rec->no_buildid_set && !rec->no_buildid)
1620 disable = false;
1621 if (rec->no_buildid_cache_set && !rec->no_buildid_cache)
1622 disable = false;
1623 if (disable) {
1624 rec->no_buildid = true;
1625 rec->no_buildid_cache = true;
1626 disable_buildid_cache();
1627 }
1628 }
1629
1630 if (record.opts.overwrite)
1631 record.opts.tail_synthesize = true;
1280 1632
1281 if (rec->evlist->nr_entries == 0 && 1633 if (rec->evlist->nr_entries == 0 &&
1282 perf_evlist__add_default(rec->evlist) < 0) { 1634 perf_evlist__add_default(rec->evlist) < 0) {
@@ -1335,9 +1687,13 @@ out_symbol_exit:
1335 1687
1336static void snapshot_sig_handler(int sig __maybe_unused) 1688static void snapshot_sig_handler(int sig __maybe_unused)
1337{ 1689{
1338 if (!auxtrace_snapshot_enabled) 1690 if (trigger_is_ready(&auxtrace_snapshot_trigger)) {
1339 return; 1691 trigger_hit(&auxtrace_snapshot_trigger);
1340 auxtrace_snapshot_enabled = 0; 1692 auxtrace_record__snapshot_started = 1;
1341 auxtrace_snapshot_err = auxtrace_record__snapshot_start(record.itr); 1693 if (auxtrace_record__snapshot_start(record.itr))
1342 auxtrace_record__snapshot_started = 1; 1694 trigger_error(&auxtrace_snapshot_trigger);
1695 }
1696
1697 if (trigger_is_ready(&switch_output_trigger))
1698 trigger_hit(&switch_output_trigger);
1343} 1699}
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 160ea23b45aa..949e5a15c960 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -8,7 +8,7 @@
8#include "builtin.h" 8#include "builtin.h"
9 9
10#include "util/util.h" 10#include "util/util.h"
11#include "util/cache.h" 11#include "util/config.h"
12 12
13#include "util/annotate.h" 13#include "util/annotate.h"
14#include "util/color.h" 14#include "util/color.h"
@@ -47,7 +47,6 @@ struct report {
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)
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)
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;
@@ -362,7 +361,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
362 struct perf_evsel *pos; 361 struct perf_evsel *pos;
363 362
364 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples); 363 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
365 evlist__for_each(evlist, pos) { 364 evlist__for_each_entry(evlist, pos) {
366 struct hists *hists = evsel__hists(pos); 365 struct hists *hists = evsel__hists(pos);
367 const char *evname = perf_evsel__name(pos); 366 const char *evname = perf_evsel__name(pos);
368 367
@@ -371,7 +370,8 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
371 continue; 370 continue;
372 371
373 hists__fprintf_nr_sample_events(hists, rep, evname, stdout); 372 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
374 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); 373 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout,
374 symbol_conf.use_callchain);
375 fprintf(stdout, "\n\n"); 375 fprintf(stdout, "\n\n");
376 } 376 }
377 377
@@ -478,7 +478,7 @@ static int report__collapse_hists(struct report *rep)
478 478
479 ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); 479 ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
480 480
481 evlist__for_each(rep->session->evlist, pos) { 481 evlist__for_each_entry(rep->session->evlist, pos) {
482 struct hists *hists = evsel__hists(pos); 482 struct hists *hists = evsel__hists(pos);
483 483
484 if (pos->idx == 0) 484 if (pos->idx == 0)
@@ -511,7 +511,7 @@ static void report__output_resort(struct report *rep)
511 511
512 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); 512 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
513 513
514 evlist__for_each(rep->session->evlist, pos) 514 evlist__for_each_entry(rep->session->evlist, pos)
515 perf_evsel__output_resort(pos, &prog); 515 perf_evsel__output_resort(pos, &prog);
516 516
517 ui_progress__finish(); 517 ui_progress__finish();
@@ -552,7 +552,7 @@ static int __cmd_report(struct report *rep)
552 552
553 report__warn_kptr_restrict(rep); 553 report__warn_kptr_restrict(rep);
554 554
555 evlist__for_each(session->evlist, pos) 555 evlist__for_each_entry(session->evlist, pos)
556 rep->nr_entries += evsel__hists(pos)->nr_entries; 556 rep->nr_entries += evsel__hists(pos)->nr_entries;
557 557
558 if (use_browser == 0) { 558 if (use_browser == 0) {
@@ -583,7 +583,7 @@ static int __cmd_report(struct report *rep)
583 * might be changed during the collapse phase. 583 * might be changed during the collapse phase.
584 */ 584 */
585 rep->nr_entries = 0; 585 rep->nr_entries = 0;
586 evlist__for_each(session->evlist, pos) 586 evlist__for_each_entry(session->evlist, pos)
587 rep->nr_entries += evsel__hists(pos)->nr_entries; 587 rep->nr_entries += evsel__hists(pos)->nr_entries;
588 588
589 if (rep->nr_entries == 0) { 589 if (rep->nr_entries == 0) {
@@ -599,13 +599,15 @@ static int __cmd_report(struct report *rep)
599static int 599static int
600report_parse_callchain_opt(const struct option *opt, const char *arg, int unset) 600report_parse_callchain_opt(const struct option *opt, const char *arg, int unset)
601{ 601{
602 struct report *rep = (struct report *)opt->value; 602 struct callchain_param *callchain = opt->value;
603 603
604 callchain->enabled = !unset;
604 /* 605 /*
605 * --no-call-graph 606 * --no-call-graph
606 */ 607 */
607 if (unset) { 608 if (unset) {
608 rep->dont_use_callchains = true; 609 symbol_conf.use_callchain = false;
610 callchain->mode = CHAIN_NONE;
609 return 0; 611 return 0;
610 } 612 }
611 613
@@ -734,7 +736,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
734 "regex filter to identify parent, see: '--sort parent'"), 736 "regex filter to identify parent, see: '--sort parent'"),
735 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other, 737 OPT_BOOLEAN('x', "exclude-other", &symbol_conf.exclude_other,
736 "Only display entries with parent-match"), 738 "Only display entries with parent-match"),
737 OPT_CALLBACK_DEFAULT('g', "call-graph", &report, 739 OPT_CALLBACK_DEFAULT('g', "call-graph", &callchain_param,
738 "print_type,threshold[,print_limit],order,sort_key[,branch],value", 740 "print_type,threshold[,print_limit],order,sort_key[,branch],value",
739 report_callchain_help, &report_parse_callchain_opt, 741 report_callchain_help, &report_parse_callchain_opt,
740 callchain_default_opt), 742 callchain_default_opt),
@@ -743,7 +745,7 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
743 OPT_INTEGER(0, "max-stack", &report.max_stack, 745 OPT_INTEGER(0, "max-stack", &report.max_stack,
744 "Set the maximum stack depth when parsing the callchain, " 746 "Set the maximum stack depth when parsing the callchain, "
745 "anything beyond the specified depth will be ignored. " 747 "anything beyond the specified depth will be ignored. "
746 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 748 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
747 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain, 749 OPT_BOOLEAN('G', "inverted", &report.inverted_callchain,
748 "alias for inverted call graph"), 750 "alias for inverted call graph"),
749 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 751 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
@@ -769,8 +771,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
769 "columns '.' is reserved."), 771 "columns '.' is reserved."),
770 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved, 772 OPT_BOOLEAN('U', "hide-unresolved", &symbol_conf.hide_unresolved,
771 "Only display entries resolved to a symbol"), 773 "Only display entries resolved to a symbol"),
772 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 774 OPT_CALLBACK(0, "symfs", NULL, "directory",
773 "Look for files with symbols relative to this directory"), 775 "Look for files with symbols relative to this directory",
776 symbol__config_symfs),
774 OPT_STRING('C', "cpu", &report.cpu_list, "cpu", 777 OPT_STRING('C', "cpu", &report.cpu_list, "cpu",
775 "list of cpus to profile"), 778 "list of cpus to profile"),
776 OPT_BOOLEAN('I', "show-info", &report.show_full_info, 779 OPT_BOOLEAN('I', "show-info", &report.show_full_info,
@@ -814,6 +817,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
814 "Show raw trace event output (do not use print fmt or plugins)"), 817 "Show raw trace event output (do not use print fmt or plugins)"),
815 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, 818 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
816 "Show entries in a hierarchy"), 819 "Show entries in a hierarchy"),
820 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
821 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
822 stdio__config_color, "always"),
817 OPT_END() 823 OPT_END()
818 }; 824 };
819 struct perf_data_file file = { 825 struct perf_data_file file = {
@@ -935,7 +941,7 @@ repeat:
935 goto error; 941 goto error;
936 } 942 }
937 943
938 sort__need_collapse = true; 944 perf_hpp_list.need_collapse = true;
939 } 945 }
940 946
941 /* Force tty output for header output and per-thread stat. */ 947 /* Force tty output for header output and per-thread stat. */
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index 871b55ae22a4..0dfe8df2ab9b 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -11,6 +11,8 @@
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 {
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 {
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)
@@ -476,7 +494,7 @@ force_again:
476 } 494 }
477 pr_err("Error: sys_perf_event_open() syscall returned " 495 pr_err("Error: sys_perf_event_open() syscall returned "
478 "with %d (%s)\n%s", fd, 496 "with %d (%s)\n%s", fd,
479 strerror_r(errno, sbuf, sizeof(sbuf)), info); 497 str_error_r(errno, sbuf, sizeof(sbuf)), info);
480 exit(EXIT_FAILURE); 498 exit(EXIT_FAILURE);
481 } 499 }
482 return fd; 500 return fd;
@@ -1339,6 +1357,38 @@ static int process_sched_wakeup_event(struct perf_tool *tool,
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,
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,
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,
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 else 1482 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 else 1487 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)
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)
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 NULL 2001 NULL
@@ -1839,6 +2004,10 @@ int cmd_sched(int argc, const char **argv, const char *prefix __maybe_unused)
1839 "perf sched replay [<options>]", 2004 "perf sched replay [<options>]",
1840 NULL 2005 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)
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);
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 52826696c852..c859e59dfe3e 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -21,7 +21,9 @@
21#include "util/cpumap.h" 21#include "util/cpumap.h"
22#include "util/thread_map.h" 22#include "util/thread_map.h"
23#include "util/stat.h" 23#include "util/stat.h"
24#include "util/thread-stack.h"
24#include <linux/bitmap.h> 25#include <linux/bitmap.h>
26#include <linux/stringify.h>
25#include "asm/bug.h" 27#include "asm/bug.h"
26#include "util/mem-events.h" 28#include "util/mem-events.h"
27 29
@@ -62,6 +64,7 @@ enum perf_output_field {
62 PERF_OUTPUT_DATA_SRC = 1U << 17, 64 PERF_OUTPUT_DATA_SRC = 1U << 17,
63 PERF_OUTPUT_WEIGHT = 1U << 18, 65 PERF_OUTPUT_WEIGHT = 1U << 18,
64 PERF_OUTPUT_BPF_OUTPUT = 1U << 19, 66 PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
67 PERF_OUTPUT_CALLINDENT = 1U << 20,
65}; 68};
66 69
67struct output_option { 70struct output_option {
@@ -88,6 +91,7 @@ struct output_option {
88 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC}, 91 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
89 {.str = "weight", .field = PERF_OUTPUT_WEIGHT}, 92 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},
90 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT}, 93 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
94 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
91}; 95};
92 96
93/* default set to maintain compatibility with current format */ 97/* default set to maintain compatibility with current format */
@@ -317,19 +321,19 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
317 321
318 output[type].print_ip_opts = 0; 322 output[type].print_ip_opts = 0;
319 if (PRINT_FIELD(IP)) 323 if (PRINT_FIELD(IP))
320 output[type].print_ip_opts |= PRINT_IP_OPT_IP; 324 output[type].print_ip_opts |= EVSEL__PRINT_IP;
321 325
322 if (PRINT_FIELD(SYM)) 326 if (PRINT_FIELD(SYM))
323 output[type].print_ip_opts |= PRINT_IP_OPT_SYM; 327 output[type].print_ip_opts |= EVSEL__PRINT_SYM;
324 328
325 if (PRINT_FIELD(DSO)) 329 if (PRINT_FIELD(DSO))
326 output[type].print_ip_opts |= PRINT_IP_OPT_DSO; 330 output[type].print_ip_opts |= EVSEL__PRINT_DSO;
327 331
328 if (PRINT_FIELD(SYMOFFSET)) 332 if (PRINT_FIELD(SYMOFFSET))
329 output[type].print_ip_opts |= PRINT_IP_OPT_SYMOFFSET; 333 output[type].print_ip_opts |= EVSEL__PRINT_SYMOFFSET;
330 334
331 if (PRINT_FIELD(SRCLINE)) 335 if (PRINT_FIELD(SRCLINE))
332 output[type].print_ip_opts |= PRINT_IP_OPT_SRCLINE; 336 output[type].print_ip_opts |= EVSEL__PRINT_SRCLINE;
333} 337}
334 338
335/* 339/*
@@ -338,7 +342,7 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
338 */ 342 */
339static int perf_session__check_output_opt(struct perf_session *session) 343static int perf_session__check_output_opt(struct perf_session *session)
340{ 344{
341 int j; 345 unsigned int j;
342 struct perf_evsel *evsel; 346 struct perf_evsel *evsel;
343 347
344 for (j = 0; j < PERF_TYPE_MAX; ++j) { 348 for (j = 0; j < PERF_TYPE_MAX; ++j) {
@@ -367,14 +371,16 @@ static int perf_session__check_output_opt(struct perf_session *session)
367 371
368 if (!no_callchain) { 372 if (!no_callchain) {
369 bool use_callchain = false; 373 bool use_callchain = false;
374 bool not_pipe = false;
370 375
371 evlist__for_each(session->evlist, evsel) { 376 evlist__for_each_entry(session->evlist, evsel) {
377 not_pipe = true;
372 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { 378 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
373 use_callchain = true; 379 use_callchain = true;
374 break; 380 break;
375 } 381 }
376 } 382 }
377 if (!use_callchain) 383 if (not_pipe && !use_callchain)
378 symbol_conf.use_callchain = false; 384 symbol_conf.use_callchain = false;
379 } 385 }
380 386
@@ -387,17 +393,20 @@ static int perf_session__check_output_opt(struct perf_session *session)
387 struct perf_event_attr *attr; 393 struct perf_event_attr *attr;
388 394
389 j = PERF_TYPE_TRACEPOINT; 395 j = PERF_TYPE_TRACEPOINT;
390 evsel = perf_session__find_first_evtype(session, j);
391 if (evsel == NULL)
392 goto out;
393 396
394 attr = &evsel->attr; 397 evlist__for_each_entry(session->evlist, evsel) {
398 if (evsel->attr.type != j)
399 continue;
400
401 attr = &evsel->attr;
395 402
396 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { 403 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
397 output[j].fields |= PERF_OUTPUT_IP; 404 output[j].fields |= PERF_OUTPUT_IP;
398 output[j].fields |= PERF_OUTPUT_SYM; 405 output[j].fields |= PERF_OUTPUT_SYM;
399 output[j].fields |= PERF_OUTPUT_DSO; 406 output[j].fields |= PERF_OUTPUT_DSO;
400 set_print_ip_opts(attr); 407 set_print_ip_opts(attr);
408 goto out;
409 }
401 } 410 }
402 } 411 }
403 412
@@ -558,6 +567,62 @@ static void print_sample_addr(struct perf_sample *sample,
558 } 567 }
559} 568}
560 569
570static void print_sample_callindent(struct perf_sample *sample,
571 struct perf_evsel *evsel,
572 struct thread *thread,
573 struct addr_location *al)
574{
575 struct perf_event_attr *attr = &evsel->attr;
576 size_t depth = thread_stack__depth(thread);
577 struct addr_location addr_al;
578 const char *name = NULL;
579 static int spacing;
580 int len = 0;
581 u64 ip = 0;
582
583 /*
584 * The 'return' has already been popped off the stack so the depth has
585 * to be adjusted to match the 'call'.
586 */
587 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
588 depth += 1;
589
590 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
591 if (sample_addr_correlates_sym(attr)) {
592 thread__resolve(thread, &addr_al, sample);
593 if (addr_al.sym)
594 name = addr_al.sym->name;
595 else
596 ip = sample->addr;
597 } else {
598 ip = sample->addr;
599 }
600 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
601 if (al->sym)
602 name = al->sym->name;
603 else
604 ip = sample->ip;
605 }
606
607 if (name)
608 len = printf("%*s%s", (int)depth * 4, "", name);
609 else if (ip)
610 len = printf("%*s%16" PRIx64, (int)depth * 4, "", ip);
611
612 if (len < 0)
613 return;
614
615 /*
616 * Try to keep the output length from changing frequently so that the
617 * output lines up more nicely.
618 */
619 if (len > spacing || (len && len < spacing - 52))
620 spacing = round_up(len + 4, 32);
621
622 if (len < spacing)
623 printf("%*s", spacing - len, "");
624}
625
561static void print_sample_bts(struct perf_sample *sample, 626static void print_sample_bts(struct perf_sample *sample,
562 struct perf_evsel *evsel, 627 struct perf_evsel *evsel,
563 struct thread *thread, 628 struct thread *thread,
@@ -566,21 +631,29 @@ static void print_sample_bts(struct perf_sample *sample,
566 struct perf_event_attr *attr = &evsel->attr; 631 struct perf_event_attr *attr = &evsel->attr;
567 bool print_srcline_last = false; 632 bool print_srcline_last = false;
568 633
634 if (PRINT_FIELD(CALLINDENT))
635 print_sample_callindent(sample, evsel, thread, al);
636
569 /* print branch_from information */ 637 /* print branch_from information */
570 if (PRINT_FIELD(IP)) { 638 if (PRINT_FIELD(IP)) {
571 unsigned int print_opts = output[attr->type].print_ip_opts; 639 unsigned int print_opts = output[attr->type].print_ip_opts;
640 struct callchain_cursor *cursor = NULL;
572 641
573 if (symbol_conf.use_callchain && sample->callchain) { 642 if (symbol_conf.use_callchain && sample->callchain &&
574 printf("\n"); 643 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
575 } else { 644 sample, NULL, NULL, scripting_max_stack) == 0)
576 printf(" "); 645 cursor = &callchain_cursor;
577 if (print_opts & PRINT_IP_OPT_SRCLINE) { 646
647 if (cursor == NULL) {
648 putchar(' ');
649 if (print_opts & EVSEL__PRINT_SRCLINE) {
578 print_srcline_last = true; 650 print_srcline_last = true;
579 print_opts &= ~PRINT_IP_OPT_SRCLINE; 651 print_opts &= ~EVSEL__PRINT_SRCLINE;
580 } 652 }
581 } 653 } else
582 perf_evsel__print_ip(evsel, sample, al, print_opts, 654 putchar('\n');
583 scripting_max_stack); 655
656 sample__fprintf_sym(sample, al, 0, print_opts, cursor, stdout);
584 } 657 }
585 658
586 /* print branch_to information */ 659 /* print branch_to information */
@@ -597,13 +670,42 @@ static void print_sample_bts(struct perf_sample *sample,
597 printf("\n"); 670 printf("\n");
598} 671}
599 672
673static struct {
674 u32 flags;
675 const char *name;
676} sample_flags[] = {
677 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
678 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
679 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"},
680 {PERF_IP_FLAG_BRANCH, "jmp"},
681 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"},
682 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"},
683 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"},
684 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"},
685 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"},
686 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"},
687 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},
688 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},
689 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
690 {0, NULL}
691};
692
600static void print_sample_flags(u32 flags) 693static void print_sample_flags(u32 flags)
601{ 694{
602 const char *chars = PERF_IP_FLAG_CHARS; 695 const char *chars = PERF_IP_FLAG_CHARS;
603 const int n = strlen(PERF_IP_FLAG_CHARS); 696 const int n = strlen(PERF_IP_FLAG_CHARS);
697 bool in_tx = flags & PERF_IP_FLAG_IN_TX;
698 const char *name = NULL;
604 char str[33]; 699 char str[33];
605 int i, pos = 0; 700 int i, pos = 0;
606 701
702 for (i = 0; sample_flags[i].name ; i++) {
703 if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) {
704 name = sample_flags[i].name;
705 break;
706 }
707 }
708
607 for (i = 0; i < n; i++, flags >>= 1) { 709 for (i = 0; i < n; i++, flags >>= 1) {
608 if (flags & 1) 710 if (flags & 1)
609 str[pos++] = chars[i]; 711 str[pos++] = chars[i];
@@ -613,7 +715,11 @@ static void print_sample_flags(u32 flags)
613 str[pos++] = '?'; 715 str[pos++] = '?';
614 } 716 }
615 str[pos] = 0; 717 str[pos] = 0;
616 printf(" %-4s ", str); 718
719 if (name)
720 printf(" %-7s%4s ", name, in_tx ? "(x)" : "");
721 else
722 printf(" %-11s ", str);
617} 723}
618 724
619struct printer_data { 725struct printer_data {
@@ -711,7 +817,7 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)
711 struct perf_evsel *evsel; 817 struct perf_evsel *evsel;
712 int max = 0; 818 int max = 0;
713 819
714 evlist__for_each(evlist, evsel) { 820 evlist__for_each_entry(evlist, evsel) {
715 int len = strlen(perf_evsel__name(evsel)); 821 int len = strlen(perf_evsel__name(evsel));
716 822
717 max = MAX(len, max); 823 max = MAX(len, max);
@@ -783,14 +889,15 @@ static void process_event(struct perf_script *script,
783 printf("%16" PRIu64, sample->weight); 889 printf("%16" PRIu64, sample->weight);
784 890
785 if (PRINT_FIELD(IP)) { 891 if (PRINT_FIELD(IP)) {
786 if (!symbol_conf.use_callchain) 892 struct callchain_cursor *cursor = NULL;
787 printf(" "); 893
788 else 894 if (symbol_conf.use_callchain && sample->callchain &&
789 printf("\n"); 895 thread__resolve_callchain(al->thread, &callchain_cursor, evsel,
896 sample, NULL, NULL, scripting_max_stack) == 0)
897 cursor = &callchain_cursor;
790 898
791 perf_evsel__print_ip(evsel, sample, al, 899 putchar(cursor ? '\n' : ' ');
792 output[attr->type].print_ip_opts, 900 sample__fprintf_sym(sample, al, 0, output[attr->type].print_ip_opts, cursor, stdout);
793 scripting_max_stack);
794 } 901 }
795 902
796 if (PRINT_FIELD(IREGS)) 903 if (PRINT_FIELD(IREGS))
@@ -935,7 +1042,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
935 if (evsel->attr.type >= PERF_TYPE_MAX) 1042 if (evsel->attr.type >= PERF_TYPE_MAX)
936 return 0; 1043 return 0;
937 1044
938 evlist__for_each(evlist, pos) { 1045 evlist__for_each_entry(evlist, pos) {
939 if (pos->attr.type == evsel->attr.type && pos != evsel) 1046 if (pos->attr.type == evsel->attr.type && pos != evsel)
940 return 0; 1047 return 0;
941 } 1048 }
@@ -1585,8 +1692,13 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1585 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path()); 1692 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
1586 1693
1587 scripts_dir = opendir(scripts_path); 1694 scripts_dir = opendir(scripts_path);
1588 if (!scripts_dir) 1695 if (!scripts_dir) {
1589 return -1; 1696 fprintf(stdout,
1697 "open(%s) failed.\n"
1698 "Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",
1699 scripts_path);
1700 exit(-1);
1701 }
1590 1702
1591 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 1703 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
1592 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 1704 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
@@ -1661,7 +1773,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
1661 snprintf(evname, len + 1, "%s", p); 1773 snprintf(evname, len + 1, "%s", p);
1662 1774
1663 match = 0; 1775 match = 0;
1664 evlist__for_each(session->evlist, pos) { 1776 evlist__for_each_entry(session->evlist, pos) {
1665 if (!strcmp(perf_evsel__name(pos), evname)) { 1777 if (!strcmp(perf_evsel__name(pos), evname)) {
1666 match = 1; 1778 match = 1;
1667 break; 1779 break;
@@ -1863,7 +1975,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1863 struct stat_round_event *round = &event->stat_round; 1975 struct stat_round_event *round = &event->stat_round;
1864 struct perf_evsel *counter; 1976 struct perf_evsel *counter;
1865 1977
1866 evlist__for_each(session->evlist, counter) { 1978 evlist__for_each_entry(session->evlist, counter) {
1867 perf_stat_process_counter(&stat_config, counter); 1979 perf_stat_process_counter(&stat_config, counter);
1868 process_stat(counter, round->time); 1980 process_stat(counter, round->time);
1869 } 1981 }
@@ -1959,6 +2071,7 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
1959 .exit = perf_event__process_exit, 2071 .exit = perf_event__process_exit,
1960 .fork = perf_event__process_fork, 2072 .fork = perf_event__process_fork,
1961 .attr = process_attr, 2073 .attr = process_attr,
2074 .event_update = perf_event__process_event_update,
1962 .tracing_data = perf_event__process_tracing_data, 2075 .tracing_data = perf_event__process_tracing_data,
1963 .build_id = perf_event__process_build_id, 2076 .build_id = perf_event__process_build_id,
1964 .id_index = perf_event__process_id_index, 2077 .id_index = perf_event__process_id_index,
@@ -2002,13 +2115,15 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2002 "file", "kallsyms pathname"), 2115 "file", "kallsyms pathname"),
2003 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain, 2116 OPT_BOOLEAN('G', "hide-call-graph", &no_callchain,
2004 "When printing symbols do not display call chain"), 2117 "When printing symbols do not display call chain"),
2005 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 2118 OPT_CALLBACK(0, "symfs", NULL, "directory",
2006 "Look for files with symbols relative to this directory"), 2119 "Look for files with symbols relative to this directory",
2120 symbol__config_symfs),
2007 OPT_CALLBACK('F', "fields", NULL, "str", 2121 OPT_CALLBACK('F', "fields", NULL, "str",
2008 "comma separated output fields prepend with 'type:'. " 2122 "comma separated output fields prepend with 'type:'. "
2009 "Valid types: hw,sw,trace,raw. " 2123 "Valid types: hw,sw,trace,raw. "
2010 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2124 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2011 "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields), 2125 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2126 "bpf-output,callindent", parse_output_fields),
2012 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2127 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2013 "system-wide collection from all CPUs"), 2128 "system-wide collection from all CPUs"),
2014 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 2129 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -2020,6 +2135,10 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2020 "only consider symbols in these pids"), 2135 "only consider symbols in these pids"),
2021 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]", 2136 OPT_STRING(0, "tid", &symbol_conf.tid_list_str, "tid[,tid...]",
2022 "only consider symbols in these tids"), 2137 "only consider symbols in these tids"),
2138 OPT_UINTEGER(0, "max-stack", &scripting_max_stack,
2139 "Set the maximum stack depth when parsing the callchain, "
2140 "anything beyond the specified depth will be ignored. "
2141 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
2023 OPT_BOOLEAN('I', "show-info", &show_full_info, 2142 OPT_BOOLEAN('I', "show-info", &show_full_info,
2024 "display extended information from perf.data file"), 2143 "display extended information from perf.data file"),
2025 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path, 2144 OPT_BOOLEAN('\0', "show-kernel-path", &symbol_conf.show_kernel_path,
@@ -2243,6 +2362,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2243 script.session = session; 2362 script.session = session;
2244 script__setup_sample_type(&script); 2363 script__setup_sample_type(&script);
2245 2364
2365 if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT)
2366 itrace_synth_opts.thread_stack = true;
2367
2246 session->itrace_synth_opts = &itrace_synth_opts; 2368 session->itrace_synth_opts = &itrace_synth_opts;
2247 2369
2248 if (cpu_list) { 2370 if (cpu_list) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index 307e8a1a003c..3c7452b39f57 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -59,13 +59,17 @@
59#include "util/thread.h" 59#include "util/thread.h"
60#include "util/thread_map.h" 60#include "util/thread_map.h"
61#include "util/counts.h" 61#include "util/counts.h"
62#include "util/group.h"
62#include "util/session.h" 63#include "util/session.h"
63#include "util/tool.h" 64#include "util/tool.h"
65#include "util/group.h"
64#include "asm/bug.h" 66#include "asm/bug.h"
65 67
68#include <api/fs/fs.h>
66#include <stdlib.h> 69#include <stdlib.h>
67#include <sys/prctl.h> 70#include <sys/prctl.h>
68#include <locale.h> 71#include <locale.h>
72#include <math.h>
69 73
70#define DEFAULT_SEPARATOR " " 74#define DEFAULT_SEPARATOR " "
71#define CNTR_NOT_SUPPORTED "<not supported>" 75#define CNTR_NOT_SUPPORTED "<not supported>"
@@ -97,6 +101,15 @@ static const char * transaction_limited_attrs = {
97 "}" 101 "}"
98}; 102};
99 103
104static const char * topdown_attrs[] = {
105 "topdown-total-slots",
106 "topdown-slots-retired",
107 "topdown-recovery-bubbles",
108 "topdown-fetch-bubbles",
109 "topdown-slots-issued",
110 NULL,
111};
112
100static struct perf_evlist *evsel_list; 113static struct perf_evlist *evsel_list;
101 114
102static struct target target = { 115static struct target target = {
@@ -111,6 +124,7 @@ static volatile pid_t child_pid = -1;
111static bool null_run = false; 124static bool null_run = false;
112static int detailed_run = 0; 125static int detailed_run = 0;
113static bool transaction_run; 126static bool transaction_run;
127static bool topdown_run = false;
114static bool big_num = true; 128static bool big_num = true;
115static int big_num_opt = -1; 129static int big_num_opt = -1;
116static const char *csv_sep = NULL; 130static const char *csv_sep = NULL;
@@ -123,6 +137,7 @@ static unsigned int initial_delay = 0;
123static unsigned int unit_width = 4; /* strlen("unit") */ 137static unsigned int unit_width = 4; /* strlen("unit") */
124static bool forever = false; 138static bool forever = false;
125static bool metric_only = false; 139static bool metric_only = false;
140static bool force_metric_only = false;
126static struct timespec ref_time; 141static struct timespec ref_time;
127static struct cpu_map *aggr_map; 142static struct cpu_map *aggr_map;
128static aggr_get_id_t aggr_get_id; 143static aggr_get_id_t aggr_get_id;
@@ -275,8 +290,12 @@ perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
275static int read_counter(struct perf_evsel *counter) 290static int read_counter(struct perf_evsel *counter)
276{ 291{
277 int nthreads = thread_map__nr(evsel_list->threads); 292 int nthreads = thread_map__nr(evsel_list->threads);
278 int ncpus = perf_evsel__nr_cpus(counter); 293 int ncpus, cpu, thread;
279 int cpu, thread; 294
295 if (target__has_cpu(&target))
296 ncpus = perf_evsel__nr_cpus(counter);
297 else
298 ncpus = 1;
280 299
281 if (!counter->supported) 300 if (!counter->supported)
282 return -ENOENT; 301 return -ENOENT;
@@ -298,27 +317,30 @@ static int read_counter(struct perf_evsel *counter)
298 return -1; 317 return -1;
299 } 318 }
300 } 319 }
320
321 if (verbose > 1) {
322 fprintf(stat_config.output,
323 "%s: %d: %" PRIu64 " %" PRIu64 " %" PRIu64 "\n",
324 perf_evsel__name(counter),
325 cpu,
326 count->val, count->ena, count->run);
327 }
301 } 328 }
302 } 329 }
303 330
304 return 0; 331 return 0;
305} 332}
306 333
307static void read_counters(bool close_counters) 334static void read_counters(void)
308{ 335{
309 struct perf_evsel *counter; 336 struct perf_evsel *counter;
310 337
311 evlist__for_each(evsel_list, counter) { 338 evlist__for_each_entry(evsel_list, counter) {
312 if (read_counter(counter)) 339 if (read_counter(counter))
313 pr_debug("failed to read counter %s\n", counter->name); 340 pr_debug("failed to read counter %s\n", counter->name);
314 341
315 if (perf_stat_process_counter(&stat_config, counter)) 342 if (perf_stat_process_counter(&stat_config, counter))
316 pr_warning("failed to process counter %s\n", counter->name); 343 pr_warning("failed to process counter %s\n", counter->name);
317
318 if (close_counters) {
319 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
320 thread_map__nr(evsel_list->threads));
321 }
322 } 344 }
323} 345}
324 346
@@ -326,7 +348,7 @@ static void process_interval(void)
326{ 348{
327 struct timespec ts, rs; 349 struct timespec ts, rs;
328 350
329 read_counters(false); 351 read_counters();
330 352
331 clock_gettime(CLOCK_MONOTONIC, &ts); 353 clock_gettime(CLOCK_MONOTONIC, &ts);
332 diff_timespec(&rs, &ts, &ref_time); 354 diff_timespec(&rs, &ts, &ref_time);
@@ -353,6 +375,17 @@ static void enable_counters(void)
353 perf_evlist__enable(evsel_list); 375 perf_evlist__enable(evsel_list);
354} 376}
355 377
378static void disable_counters(void)
379{
380 /*
381 * If we don't have tracee (attaching to task or cpu), counters may
382 * still be running. To get accurate group ratios, we must stop groups
383 * from counting before reading their constituent counters.
384 */
385 if (!target__none(&target))
386 perf_evlist__disable(evsel_list);
387}
388
356static volatile int workload_exec_errno; 389static volatile int workload_exec_errno;
357 390
358/* 391/*
@@ -394,7 +427,7 @@ static int perf_stat_synthesize_config(bool is_pipe)
394 * Synthesize other events stuff not carried within 427 * Synthesize other events stuff not carried within
395 * attr event - unit, scale, name 428 * attr event - unit, scale, name
396 */ 429 */
397 evlist__for_each(evsel_list, counter) { 430 evlist__for_each_entry(evsel_list, counter) {
398 if (!counter->supported) 431 if (!counter->supported)
399 continue; 432 continue;
400 433
@@ -527,7 +560,7 @@ static int __run_perf_stat(int argc, const char **argv)
527 if (group) 560 if (group)
528 perf_evlist__set_leader(evsel_list); 561 perf_evlist__set_leader(evsel_list);
529 562
530 evlist__for_each(evsel_list, counter) { 563 evlist__for_each_entry(evsel_list, counter) {
531try_again: 564try_again:
532 if (create_perf_stat_counter(counter) < 0) { 565 if (create_perf_stat_counter(counter) < 0) {
533 /* 566 /*
@@ -573,7 +606,7 @@ try_again:
573 if (perf_evlist__apply_filters(evsel_list, &counter)) { 606 if (perf_evlist__apply_filters(evsel_list, &counter)) {
574 error("failed to set filter \"%s\" on event %s with %d (%s)\n", 607 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
575 counter->filter, perf_evsel__name(counter), errno, 608 counter->filter, perf_evsel__name(counter), errno,
576 strerror_r(errno, msg, sizeof(msg))); 609 str_error_r(errno, msg, sizeof(msg)));
577 return -1; 610 return -1;
578 } 611 }
579 612
@@ -614,7 +647,7 @@ try_again:
614 wait(&status); 647 wait(&status);
615 648
616 if (workload_exec_errno) { 649 if (workload_exec_errno) {
617 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 650 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
618 pr_err("Workload failed: %s\n", emsg); 651 pr_err("Workload failed: %s\n", emsg);
619 return -1; 652 return -1;
620 } 653 }
@@ -630,11 +663,20 @@ try_again:
630 } 663 }
631 } 664 }
632 665
666 disable_counters();
667
633 t1 = rdclock(); 668 t1 = rdclock();
634 669
635 update_stats(&walltime_nsecs_stats, t1 - t0); 670 update_stats(&walltime_nsecs_stats, t1 - t0);
636 671
637 read_counters(true); 672 /*
673 * Closing a group leader splits the group, and as we only disable
674 * group leaders, results in remaining events becoming enabled. To
675 * avoid arbitrary skew, we must read all counters before closing any
676 * group leaders.
677 */
678 read_counters();
679 perf_evlist__close(evsel_list);
638 680
639 return WEXITSTATUS(status); 681 return WEXITSTATUS(status);
640} 682}
@@ -983,12 +1025,12 @@ static void abs_printout(int id, int nr, struct perf_evsel *evsel, double avg)
983 const char *fmt; 1025 const char *fmt;
984 1026
985 if (csv_output) { 1027 if (csv_output) {
986 fmt = sc != 1.0 ? "%.2f%s" : "%.0f%s"; 1028 fmt = floor(sc) != sc ? "%.2f%s" : "%.0f%s";
987 } else { 1029 } else {
988 if (big_num) 1030 if (big_num)
989 fmt = sc != 1.0 ? "%'18.2f%s" : "%'18.0f%s"; 1031 fmt = floor(sc) != sc ? "%'18.2f%s" : "%'18.0f%s";
990 else 1032 else
991 fmt = sc != 1.0 ? "%18.2f%s" : "%18.0f%s"; 1033 fmt = floor(sc) != sc ? "%18.2f%s" : "%18.0f%s";
992 } 1034 }
993 1035
994 aggr_printout(evsel, id, nr); 1036 aggr_printout(evsel, id, nr);
@@ -1111,7 +1153,7 @@ static void aggr_update_shadow(void)
1111 1153
1112 for (s = 0; s < aggr_map->nr; s++) { 1154 for (s = 0; s < aggr_map->nr; s++) {
1113 id = aggr_map->map[s]; 1155 id = aggr_map->map[s];
1114 evlist__for_each(evsel_list, counter) { 1156 evlist__for_each_entry(evsel_list, counter) {
1115 val = 0; 1157 val = 0;
1116 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1158 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1117 s2 = aggr_get_id(evsel_list->cpus, cpu); 1159 s2 = aggr_get_id(evsel_list->cpus, cpu);
@@ -1150,7 +1192,7 @@ static void print_aggr(char *prefix)
1150 1192
1151 id = aggr_map->map[s]; 1193 id = aggr_map->map[s];
1152 first = true; 1194 first = true;
1153 evlist__for_each(evsel_list, counter) { 1195 evlist__for_each_entry(evsel_list, counter) {
1154 val = ena = run = 0; 1196 val = ena = run = 0;
1155 nr = 0; 1197 nr = 0;
1156 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1198 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@@ -1269,7 +1311,7 @@ static void print_no_aggr_metric(char *prefix)
1269 1311
1270 if (prefix) 1312 if (prefix)
1271 fputs(prefix, stat_config.output); 1313 fputs(prefix, stat_config.output);
1272 evlist__for_each(evsel_list, counter) { 1314 evlist__for_each_entry(evsel_list, counter) {
1273 if (first) { 1315 if (first) {
1274 aggr_printout(counter, cpu, 0); 1316 aggr_printout(counter, cpu, 0);
1275 first = false; 1317 first = false;
@@ -1293,7 +1335,15 @@ static int aggr_header_lens[] = {
1293 [AGGR_GLOBAL] = 0, 1335 [AGGR_GLOBAL] = 0,
1294}; 1336};
1295 1337
1296static void print_metric_headers(char *prefix) 1338static const char *aggr_header_csv[] = {
1339 [AGGR_CORE] = "core,cpus,",
1340 [AGGR_SOCKET] = "socket,cpus",
1341 [AGGR_NONE] = "cpu,",
1342 [AGGR_THREAD] = "comm-pid,",
1343 [AGGR_GLOBAL] = ""
1344};
1345
1346static void print_metric_headers(const char *prefix, bool no_indent)
1297{ 1347{
1298 struct perf_stat_output_ctx out; 1348 struct perf_stat_output_ctx out;
1299 struct perf_evsel *counter; 1349 struct perf_evsel *counter;
@@ -1304,12 +1354,18 @@ static void print_metric_headers(char *prefix)
1304 if (prefix) 1354 if (prefix)
1305 fprintf(stat_config.output, "%s", prefix); 1355 fprintf(stat_config.output, "%s", prefix);
1306 1356
1307 if (!csv_output) 1357 if (!csv_output && !no_indent)
1308 fprintf(stat_config.output, "%*s", 1358 fprintf(stat_config.output, "%*s",
1309 aggr_header_lens[stat_config.aggr_mode], ""); 1359 aggr_header_lens[stat_config.aggr_mode], "");
1360 if (csv_output) {
1361 if (stat_config.interval)
1362 fputs("time,", stat_config.output);
1363 fputs(aggr_header_csv[stat_config.aggr_mode],
1364 stat_config.output);
1365 }
1310 1366
1311 /* Print metrics headers only */ 1367 /* Print metrics headers only */
1312 evlist__for_each(evsel_list, counter) { 1368 evlist__for_each_entry(evsel_list, counter) {
1313 os.evsel = counter; 1369 os.evsel = counter;
1314 out.ctx = &os; 1370 out.ctx = &os;
1315 out.print_metric = print_metric_header; 1371 out.print_metric = print_metric_header;
@@ -1329,28 +1385,40 @@ static void print_interval(char *prefix, struct timespec *ts)
1329 1385
1330 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); 1386 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
1331 1387
1332 if (num_print_interval == 0 && !csv_output && !metric_only) { 1388 if (num_print_interval == 0 && !csv_output) {
1333 switch (stat_config.aggr_mode) { 1389 switch (stat_config.aggr_mode) {
1334 case AGGR_SOCKET: 1390 case AGGR_SOCKET:
1335 fprintf(output, "# time socket cpus counts %*s events\n", unit_width, "unit"); 1391 fprintf(output, "# time socket cpus");
1392 if (!metric_only)
1393 fprintf(output, " counts %*s events\n", unit_width, "unit");
1336 break; 1394 break;
1337 case AGGR_CORE: 1395 case AGGR_CORE:
1338 fprintf(output, "# time core cpus counts %*s events\n", unit_width, "unit"); 1396 fprintf(output, "# time core cpus");
1397 if (!metric_only)
1398 fprintf(output, " counts %*s events\n", unit_width, "unit");
1339 break; 1399 break;
1340 case AGGR_NONE: 1400 case AGGR_NONE:
1341 fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit"); 1401 fprintf(output, "# time CPU");
1402 if (!metric_only)
1403 fprintf(output, " counts %*s events\n", unit_width, "unit");
1342 break; 1404 break;
1343 case AGGR_THREAD: 1405 case AGGR_THREAD:
1344 fprintf(output, "# time comm-pid counts %*s events\n", unit_width, "unit"); 1406 fprintf(output, "# time comm-pid");
1407 if (!metric_only)
1408 fprintf(output, " counts %*s events\n", unit_width, "unit");
1345 break; 1409 break;
1346 case AGGR_GLOBAL: 1410 case AGGR_GLOBAL:
1347 default: 1411 default:
1348 fprintf(output, "# time counts %*s events\n", unit_width, "unit"); 1412 fprintf(output, "# time");
1413 if (!metric_only)
1414 fprintf(output, " counts %*s events\n", unit_width, "unit");
1349 case AGGR_UNSET: 1415 case AGGR_UNSET:
1350 break; 1416 break;
1351 } 1417 }
1352 } 1418 }
1353 1419
1420 if (num_print_interval == 0 && metric_only)
1421 print_metric_headers(" ", true);
1354 if (++num_print_interval == 25) 1422 if (++num_print_interval == 25)
1355 num_print_interval = 0; 1423 num_print_interval = 0;
1356} 1424}
@@ -1419,8 +1487,8 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1419 if (metric_only) { 1487 if (metric_only) {
1420 static int num_print_iv; 1488 static int num_print_iv;
1421 1489
1422 if (num_print_iv == 0) 1490 if (num_print_iv == 0 && !interval)
1423 print_metric_headers(prefix); 1491 print_metric_headers(prefix, false);
1424 if (num_print_iv++ == 25) 1492 if (num_print_iv++ == 25)
1425 num_print_iv = 0; 1493 num_print_iv = 0;
1426 if (stat_config.aggr_mode == AGGR_GLOBAL && prefix) 1494 if (stat_config.aggr_mode == AGGR_GLOBAL && prefix)
@@ -1433,11 +1501,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1433 print_aggr(prefix); 1501 print_aggr(prefix);
1434 break; 1502 break;
1435 case AGGR_THREAD: 1503 case AGGR_THREAD:
1436 evlist__for_each(evsel_list, counter) 1504 evlist__for_each_entry(evsel_list, counter)
1437 print_aggr_thread(counter, prefix); 1505 print_aggr_thread(counter, prefix);
1438 break; 1506 break;
1439 case AGGR_GLOBAL: 1507 case AGGR_GLOBAL:
1440 evlist__for_each(evsel_list, counter) 1508 evlist__for_each_entry(evsel_list, counter)
1441 print_counter_aggr(counter, prefix); 1509 print_counter_aggr(counter, prefix);
1442 if (metric_only) 1510 if (metric_only)
1443 fputc('\n', stat_config.output); 1511 fputc('\n', stat_config.output);
@@ -1446,7 +1514,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1446 if (metric_only) 1514 if (metric_only)
1447 print_no_aggr_metric(prefix); 1515 print_no_aggr_metric(prefix);
1448 else { 1516 else {
1449 evlist__for_each(evsel_list, counter) 1517 evlist__for_each_entry(evsel_list, counter)
1450 print_counter(counter, prefix); 1518 print_counter(counter, prefix);
1451 } 1519 }
1452 break; 1520 break;
@@ -1511,6 +1579,14 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
1511 return 0; 1579 return 0;
1512} 1580}
1513 1581
1582static int enable_metric_only(const struct option *opt __maybe_unused,
1583 const char *s __maybe_unused, int unset)
1584{
1585 force_metric_only = true;
1586 metric_only = !unset;
1587 return 0;
1588}
1589
1514static const struct option stat_options[] = { 1590static const struct option stat_options[] = {
1515 OPT_BOOLEAN('T', "transaction", &transaction_run, 1591 OPT_BOOLEAN('T', "transaction", &transaction_run,
1516 "hardware transaction statistics"), 1592 "hardware transaction statistics"),
@@ -1569,8 +1645,10 @@ static const struct option stat_options[] = {
1569 "aggregate counts per thread", AGGR_THREAD), 1645 "aggregate counts per thread", AGGR_THREAD),
1570 OPT_UINTEGER('D', "delay", &initial_delay, 1646 OPT_UINTEGER('D', "delay", &initial_delay,
1571 "ms to wait before starting measurement after program start"), 1647 "ms to wait before starting measurement after program start"),
1572 OPT_BOOLEAN(0, "metric-only", &metric_only, 1648 OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL,
1573 "Only print computed metrics. No raw values"), 1649 "Only print computed metrics. No raw values", enable_metric_only),
1650 OPT_BOOLEAN(0, "topdown", &topdown_run,
1651 "measure topdown level 1 statistics"),
1574 OPT_END() 1652 OPT_END()
1575}; 1653};
1576 1654
@@ -1763,12 +1841,62 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
1763 return 0; 1841 return 0;
1764} 1842}
1765 1843
1844static int topdown_filter_events(const char **attr, char **str, bool use_group)
1845{
1846 int off = 0;
1847 int i;
1848 int len = 0;
1849 char *s;
1850
1851 for (i = 0; attr[i]; i++) {
1852 if (pmu_have_event("cpu", attr[i])) {
1853 len += strlen(attr[i]) + 1;
1854 attr[i - off] = attr[i];
1855 } else
1856 off++;
1857 }
1858 attr[i - off] = NULL;
1859
1860 *str = malloc(len + 1 + 2);
1861 if (!*str)
1862 return -1;
1863 s = *str;
1864 if (i - off == 0) {
1865 *s = 0;
1866 return 0;
1867 }
1868 if (use_group)
1869 *s++ = '{';
1870 for (i = 0; attr[i]; i++) {
1871 strcpy(s, attr[i]);
1872 s += strlen(s);
1873 *s++ = ',';
1874 }
1875 if (use_group) {
1876 s[-1] = '}';
1877 *s = 0;
1878 } else
1879 s[-1] = 0;
1880 return 0;
1881}
1882
1883__weak bool arch_topdown_check_group(bool *warn)
1884{
1885 *warn = false;
1886 return false;
1887}
1888
1889__weak void arch_topdown_group_warn(void)
1890{
1891}
1892
1766/* 1893/*
1767 * Add default attributes, if there were no attributes specified or 1894 * Add default attributes, if there were no attributes specified or
1768 * if -d/--detailed, -d -d or -d -d -d is used: 1895 * if -d/--detailed, -d -d or -d -d -d is used:
1769 */ 1896 */
1770static int add_default_attributes(void) 1897static int add_default_attributes(void)
1771{ 1898{
1899 int err;
1772 struct perf_event_attr default_attrs0[] = { 1900 struct perf_event_attr default_attrs0[] = {
1773 1901
1774 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 1902 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
@@ -1887,7 +2015,6 @@ static int add_default_attributes(void)
1887 return 0; 2015 return 0;
1888 2016
1889 if (transaction_run) { 2017 if (transaction_run) {
1890 int err;
1891 if (pmu_have_event("cpu", "cycles-ct") && 2018 if (pmu_have_event("cpu", "cycles-ct") &&
1892 pmu_have_event("cpu", "el-start")) 2019 pmu_have_event("cpu", "el-start"))
1893 err = parse_events(evsel_list, transaction_attrs, NULL); 2020 err = parse_events(evsel_list, transaction_attrs, NULL);
@@ -1900,7 +2027,50 @@ static int add_default_attributes(void)
1900 return 0; 2027 return 0;
1901 } 2028 }
1902 2029
2030 if (topdown_run) {
2031 char *str = NULL;
2032 bool warn = false;
2033
2034 if (stat_config.aggr_mode != AGGR_GLOBAL &&
2035 stat_config.aggr_mode != AGGR_CORE) {
2036 pr_err("top down event configuration requires --per-core mode\n");
2037 return -1;
2038 }
2039 stat_config.aggr_mode = AGGR_CORE;
2040 if (nr_cgroups || !target__has_cpu(&target)) {
2041 pr_err("top down event configuration requires system-wide mode (-a)\n");
2042 return -1;
2043 }
2044
2045 if (!force_metric_only)
2046 metric_only = true;
2047 if (topdown_filter_events(topdown_attrs, &str,
2048 arch_topdown_check_group(&warn)) < 0) {
2049 pr_err("Out of memory\n");
2050 return -1;
2051 }
2052 if (topdown_attrs[0] && str) {
2053 if (warn)
2054 arch_topdown_group_warn();
2055 err = parse_events(evsel_list, str, NULL);
2056 if (err) {
2057 fprintf(stderr,
2058 "Cannot set up top down events %s: %d\n",
2059 str, err);
2060 free(str);
2061 return -1;
2062 }
2063 } else {
2064 fprintf(stderr, "System does not support topdown\n");
2065 return -1;
2066 }
2067 free(str);
2068 }
2069
1903 if (!evsel_list->nr_entries) { 2070 if (!evsel_list->nr_entries) {
2071 if (target__has_cpu(&target))
2072 default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;
2073
1904 if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0) 2074 if (perf_evlist__add_default_attrs(evsel_list, default_attrs0) < 0)
1905 return -1; 2075 return -1;
1906 if (pmu_have_event("cpu", "stalled-cycles-frontend")) { 2076 if (pmu_have_event("cpu", "stalled-cycles-frontend")) {
@@ -1992,21 +2162,21 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1992 union perf_event *event, 2162 union perf_event *event,
1993 struct perf_session *session) 2163 struct perf_session *session)
1994{ 2164{
1995 struct stat_round_event *round = &event->stat_round; 2165 struct stat_round_event *stat_round = &event->stat_round;
1996 struct perf_evsel *counter; 2166 struct perf_evsel *counter;
1997 struct timespec tsh, *ts = NULL; 2167 struct timespec tsh, *ts = NULL;
1998 const char **argv = session->header.env.cmdline_argv; 2168 const char **argv = session->header.env.cmdline_argv;
1999 int argc = session->header.env.nr_cmdline; 2169 int argc = session->header.env.nr_cmdline;
2000 2170
2001 evlist__for_each(evsel_list, counter) 2171 evlist__for_each_entry(evsel_list, counter)
2002 perf_stat_process_counter(&stat_config, counter); 2172 perf_stat_process_counter(&stat_config, counter);
2003 2173
2004 if (round->type == PERF_STAT_ROUND_TYPE__FINAL) 2174 if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL)
2005 update_stats(&walltime_nsecs_stats, round->time); 2175 update_stats(&walltime_nsecs_stats, stat_round->time);
2006 2176
2007 if (stat_config.interval && round->time) { 2177 if (stat_config.interval && stat_round->time) {
2008 tsh.tv_sec = round->time / NSECS_PER_SEC; 2178 tsh.tv_sec = stat_round->time / NSECS_PER_SEC;
2009 tsh.tv_nsec = round->time % NSECS_PER_SEC; 2179 tsh.tv_nsec = stat_round->time % NSECS_PER_SEC;
2010 ts = &tsh; 2180 ts = &tsh;
2011 } 2181 }
2012 2182
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 40cc9bb3506c..733a55422d03 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -1945,8 +1945,9 @@ int cmd_timechart(int argc, const char **argv,
1945 OPT_CALLBACK('p', "process", NULL, "process", 1945 OPT_CALLBACK('p', "process", NULL, "process",
1946 "process selector. Pass a pid or process name.", 1946 "process selector. Pass a pid or process name.",
1947 parse_process), 1947 parse_process),
1948 OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory", 1948 OPT_CALLBACK(0, "symfs", NULL, "directory",
1949 "Look for files with symbols relative to this directory"), 1949 "Look for files with symbols relative to this directory",
1950 symbol__config_symfs),
1950 OPT_INTEGER('n', "proc-num", &tchart.proc_num, 1951 OPT_INTEGER('n', "proc-num", &tchart.proc_num,
1951 "min. number of tasks to print"), 1952 "min. number of tasks to print"),
1952 OPT_BOOLEAN('t', "topology", &tchart.topology, 1953 OPT_BOOLEAN('t', "topology", &tchart.topology,
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 833214979c4f..418ed94756d3 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,7 +22,7 @@
22#include "perf.h" 22#include "perf.h"
23 23
24#include "util/annotate.h" 24#include "util/annotate.h"
25#include "util/cache.h" 25#include "util/config.h"
26#include "util/color.h" 26#include "util/color.h"
27#include "util/evlist.h" 27#include "util/evlist.h"
28#include "util/evsel.h" 28#include "util/evsel.h"
@@ -128,10 +128,14 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
128 return err; 128 return err;
129 } 129 }
130 130
131 err = symbol__annotate(sym, map, 0); 131 err = symbol__disassemble(sym, map, 0);
132 if (err == 0) { 132 if (err == 0) {
133out_assign: 133out_assign:
134 top->sym_filter_entry = he; 134 top->sym_filter_entry = he;
135 } else {
136 char msg[BUFSIZ];
137 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
138 pr_err("Couldn't annotate %s: %s\n", sym->name, msg);
135 } 139 }
136 140
137 pthread_mutex_unlock(&notes->lock); 141 pthread_mutex_unlock(&notes->lock);
@@ -295,7 +299,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
295 hists__output_recalc_col_len(hists, top->print_entries - printed); 299 hists__output_recalc_col_len(hists, top->print_entries - printed);
296 putchar('\n'); 300 putchar('\n');
297 hists__fprintf(hists, false, top->print_entries - printed, win_width, 301 hists__fprintf(hists, false, top->print_entries - printed, win_width,
298 top->min_percent, stdout); 302 top->min_percent, stdout, symbol_conf.use_callchain);
299} 303}
300 304
301static void prompt_integer(int *target, const char *msg) 305static void prompt_integer(int *target, const char *msg)
@@ -479,7 +483,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
479 483
480 fprintf(stderr, "\nAvailable events:"); 484 fprintf(stderr, "\nAvailable events:");
481 485
482 evlist__for_each(top->evlist, top->sym_evsel) 486 evlist__for_each_entry(top->evlist, top->sym_evsel)
483 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel)); 487 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
484 488
485 prompt_integer(&counter, "Enter details event counter"); 489 prompt_integer(&counter, "Enter details event counter");
@@ -490,7 +494,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
490 sleep(1); 494 sleep(1);
491 break; 495 break;
492 } 496 }
493 evlist__for_each(top->evlist, top->sym_evsel) 497 evlist__for_each_entry(top->evlist, top->sym_evsel)
494 if (top->sym_evsel->idx == counter) 498 if (top->sym_evsel->idx == counter)
495 break; 499 break;
496 } else 500 } else
@@ -583,7 +587,7 @@ static void *display_thread_tui(void *arg)
583 * Zooming in/out UIDs. For now juse use whatever the user passed 587 * Zooming in/out UIDs. For now juse use whatever the user passed
584 * via --uid. 588 * via --uid.
585 */ 589 */
586 evlist__for_each(top->evlist, pos) { 590 evlist__for_each_entry(top->evlist, pos) {
587 struct hists *hists = evsel__hists(pos); 591 struct hists *hists = evsel__hists(pos);
588 hists->uid_filter_str = top->record_opts.target.uid_str; 592 hists->uid_filter_str = top->record_opts.target.uid_str;
589 } 593 }
@@ -688,7 +692,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
688 struct hist_entry *he = iter->he; 692 struct hist_entry *he = iter->he;
689 struct perf_evsel *evsel = iter->evsel; 693 struct perf_evsel *evsel = iter->evsel;
690 694
691 if (sort__has_sym && single) 695 if (perf_hpp_list.sym && single)
692 perf_top__record_precise_ip(top, he, evsel->idx, al->addr); 696 perf_top__record_precise_ip(top, he, evsel->idx, al->addr);
693 697
694 hist__account_cycles(iter->sample->branch_stack, al, iter->sample, 698 hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
@@ -732,7 +736,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
732 if (machine__resolve(machine, &al, sample) < 0) 736 if (machine__resolve(machine, &al, sample) < 0)
733 return; 737 return;
734 738
735 if (!top->kptr_restrict_warned && 739 if (!machine->kptr_restrict_warned &&
736 symbol_conf.kptr_restrict && 740 symbol_conf.kptr_restrict &&
737 al.cpumode == PERF_RECORD_MISC_KERNEL) { 741 al.cpumode == PERF_RECORD_MISC_KERNEL) {
738 ui__warning( 742 ui__warning(
@@ -743,7 +747,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
743 " modules" : ""); 747 " modules" : "");
744 if (use_browser <= 0) 748 if (use_browser <= 0)
745 sleep(5); 749 sleep(5);
746 top->kptr_restrict_warned = true; 750 machine->kptr_restrict_warned = true;
747 } 751 }
748 752
749 if (al.sym == NULL) { 753 if (al.sym == NULL) {
@@ -759,7 +763,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
759 * --hide-kernel-symbols, even if the user specifies an 763 * --hide-kernel-symbols, even if the user specifies an
760 * invalid --vmlinux ;-) 764 * invalid --vmlinux ;-)
761 */ 765 */
762 if (!top->kptr_restrict_warned && !top->vmlinux_warned && 766 if (!machine->kptr_restrict_warned && !top->vmlinux_warned &&
763 al.map == machine->vmlinux_maps[MAP__FUNCTION] && 767 al.map == machine->vmlinux_maps[MAP__FUNCTION] &&
764 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) { 768 RB_EMPTY_ROOT(&al.map->dso->symbols[MAP__FUNCTION])) {
765 if (symbol_conf.vmlinux_name) { 769 if (symbol_conf.vmlinux_name) {
@@ -886,9 +890,9 @@ static int perf_top__start_counters(struct perf_top *top)
886 struct perf_evlist *evlist = top->evlist; 890 struct perf_evlist *evlist = top->evlist;
887 struct record_opts *opts = &top->record_opts; 891 struct record_opts *opts = &top->record_opts;
888 892
889 perf_evlist__config(evlist, opts); 893 perf_evlist__config(evlist, opts, &callchain_param);
890 894
891 evlist__for_each(evlist, counter) { 895 evlist__for_each_entry(evlist, counter) {
892try_again: 896try_again:
893 if (perf_evsel__open(counter, top->evlist->cpus, 897 if (perf_evsel__open(counter, top->evlist->cpus,
894 top->evlist->threads) < 0) { 898 top->evlist->threads) < 0) {
@@ -907,7 +911,7 @@ try_again:
907 911
908 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 912 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
909 ui__error("Failed to mmap with %d (%s)\n", 913 ui__error("Failed to mmap with %d (%s)\n",
910 errno, strerror_r(errno, msg, sizeof(msg))); 914 errno, str_error_r(errno, msg, sizeof(msg)));
911 goto out_err; 915 goto out_err;
912 } 916 }
913 917
@@ -917,15 +921,15 @@ out_err:
917 return -1; 921 return -1;
918} 922}
919 923
920static int perf_top__setup_sample_type(struct perf_top *top __maybe_unused) 924static int callchain_param__setup_sample_type(struct callchain_param *callchain)
921{ 925{
922 if (!sort__has_sym) { 926 if (!perf_hpp_list.sym) {
923 if (symbol_conf.use_callchain) { 927 if (callchain->enabled) {
924 ui__error("Selected -g but \"sym\" not present in --sort/-s."); 928 ui__error("Selected -g but \"sym\" not present in --sort/-s.");
925 return -EINVAL; 929 return -EINVAL;
926 } 930 }
927 } else if (callchain_param.mode != CHAIN_NONE) { 931 } else if (callchain->mode != CHAIN_NONE) {
928 if (callchain_register_param(&callchain_param) < 0) { 932 if (callchain_register_param(callchain) < 0) {
929 ui__error("Can't register callchain params.\n"); 933 ui__error("Can't register callchain params.\n");
930 return -EINVAL; 934 return -EINVAL;
931 } 935 }
@@ -952,7 +956,7 @@ static int __cmd_top(struct perf_top *top)
952 goto out_delete; 956 goto out_delete;
953 } 957 }
954 958
955 ret = perf_top__setup_sample_type(top); 959 ret = callchain_param__setup_sample_type(&callchain_param);
956 if (ret) 960 if (ret)
957 goto out_delete; 961 goto out_delete;
958 962
@@ -962,7 +966,7 @@ static int __cmd_top(struct perf_top *top)
962 machine__synthesize_threads(&top->session->machines.host, &opts->target, 966 machine__synthesize_threads(&top->session->machines.host, &opts->target,
963 top->evlist->threads, false, opts->proc_map_timeout); 967 top->evlist->threads, false, opts->proc_map_timeout);
964 968
965 if (sort__has_socket) { 969 if (perf_hpp_list.socket) {
966 ret = perf_env__read_cpu_topology_map(&perf_env); 970 ret = perf_env__read_cpu_topology_map(&perf_env);
967 if (ret < 0) 971 if (ret < 0)
968 goto out_err_cpu_topo; 972 goto out_err_cpu_topo;
@@ -1028,7 +1032,7 @@ out_delete:
1028 1032
1029out_err_cpu_topo: { 1033out_err_cpu_topo: {
1030 char errbuf[BUFSIZ]; 1034 char errbuf[BUFSIZ];
1031 const char *err = strerror_r(-ret, errbuf, sizeof(errbuf)); 1035 const char *err = str_error_r(-ret, errbuf, sizeof(errbuf));
1032 1036
1033 ui__error("Could not read the CPU topology map: %s\n", err); 1037 ui__error("Could not read the CPU topology map: %s\n", err);
1034 goto out_delete; 1038 goto out_delete;
@@ -1045,18 +1049,17 @@ callchain_opt(const struct option *opt, const char *arg, int unset)
1045static int 1049static int
1046parse_callchain_opt(const struct option *opt, const char *arg, int unset) 1050parse_callchain_opt(const struct option *opt, const char *arg, int unset)
1047{ 1051{
1048 struct record_opts *record = (struct record_opts *)opt->value; 1052 struct callchain_param *callchain = opt->value;
1049 1053
1050 record->callgraph_set = true; 1054 callchain->enabled = !unset;
1051 callchain_param.enabled = !unset; 1055 callchain->record_mode = CALLCHAIN_FP;
1052 callchain_param.record_mode = CALLCHAIN_FP;
1053 1056
1054 /* 1057 /*
1055 * --no-call-graph 1058 * --no-call-graph
1056 */ 1059 */
1057 if (unset) { 1060 if (unset) {
1058 symbol_conf.use_callchain = false; 1061 symbol_conf.use_callchain = false;
1059 callchain_param.record_mode = CALLCHAIN_NONE; 1062 callchain->record_mode = CALLCHAIN_NONE;
1060 return 0; 1063 return 0;
1061 } 1064 }
1062 1065
@@ -1104,7 +1107,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1104 }, 1107 },
1105 .proc_map_timeout = 500, 1108 .proc_map_timeout = 500,
1106 }, 1109 },
1107 .max_stack = PERF_MAX_STACK_DEPTH, 1110 .max_stack = sysctl_perf_event_max_stack,
1108 .sym_pcnt_filter = 5, 1111 .sym_pcnt_filter = 5,
1109 }; 1112 };
1110 struct record_opts *opts = &top.record_opts; 1113 struct record_opts *opts = &top.record_opts;
@@ -1162,17 +1165,17 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1162 "output field(s): overhead, period, sample plus all of sort keys"), 1165 "output field(s): overhead, period, sample plus all of sort keys"),
1163 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, 1166 OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
1164 "Show a column with the number of samples"), 1167 "Show a column with the number of samples"),
1165 OPT_CALLBACK_NOOPT('g', NULL, &top.record_opts, 1168 OPT_CALLBACK_NOOPT('g', NULL, &callchain_param,
1166 NULL, "enables call-graph recording and display", 1169 NULL, "enables call-graph recording and display",
1167 &callchain_opt), 1170 &callchain_opt),
1168 OPT_CALLBACK(0, "call-graph", &top.record_opts, 1171 OPT_CALLBACK(0, "call-graph", &callchain_param,
1169 "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]", 1172 "record_mode[,record_size],print_type,threshold[,print_limit],order,sort_key[,branch]",
1170 top_callchain_help, &parse_callchain_opt), 1173 top_callchain_help, &parse_callchain_opt),
1171 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain, 1174 OPT_BOOLEAN(0, "children", &symbol_conf.cumulate_callchain,
1172 "Accumulate callchains of children and show total overhead as well"), 1175 "Accumulate callchains of children and show total overhead as well"),
1173 OPT_INTEGER(0, "max-stack", &top.max_stack, 1176 OPT_INTEGER(0, "max-stack", &top.max_stack,
1174 "Set the maximum stack depth when parsing the callchain. " 1177 "Set the maximum stack depth when parsing the callchain. "
1175 "Default: " __stringify(PERF_MAX_STACK_DEPTH)), 1178 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
1176 OPT_CALLBACK(0, "ignore-callees", NULL, "regex", 1179 OPT_CALLBACK(0, "ignore-callees", NULL, "regex",
1177 "ignore callees of these functions in call graphs", 1180 "ignore callees of these functions in call graphs",
1178 report_parse_ignore_callees_opt), 1181 report_parse_ignore_callees_opt),
@@ -1256,7 +1259,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1256 1259
1257 sort__mode = SORT_MODE__TOP; 1260 sort__mode = SORT_MODE__TOP;
1258 /* display thread wants entries to be collapsed in a different tree */ 1261 /* display thread wants entries to be collapsed in a different tree */
1259 sort__need_collapse = 1; 1262 perf_hpp_list.need_collapse = 1;
1260 1263
1261 if (top.use_stdio) 1264 if (top.use_stdio)
1262 use_browser = 0; 1265 use_browser = 0;
@@ -1296,7 +1299,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1296 1299
1297 if (perf_evlist__create_maps(top.evlist, target) < 0) { 1300 if (perf_evlist__create_maps(top.evlist, target) < 0) {
1298 ui__error("Couldn't create thread/CPU maps: %s\n", 1301 ui__error("Couldn't create thread/CPU maps: %s\n",
1299 errno == ENOENT ? "No such process" : strerror_r(errno, errbuf, sizeof(errbuf))); 1302 errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf)));
1300 goto out_delete_evlist; 1303 goto out_delete_evlist;
1301 } 1304 }
1302 1305
@@ -1312,7 +1315,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1312 1315
1313 top.sym_evsel = perf_evlist__first(top.evlist); 1316 top.sym_evsel = perf_evlist__first(top.evlist);
1314 1317
1315 if (!symbol_conf.use_callchain) { 1318 if (!callchain_param.enabled) {
1316 symbol_conf.cumulate_callchain = false; 1319 symbol_conf.cumulate_callchain = false;
1317 perf_hpp__cancel_cumulate(); 1320 perf_hpp__cancel_cumulate();
1318 } 1321 }
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 93ac724fb635..b8c6766301db 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -34,79 +34,75 @@
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_STACK 46#include <linux/random.h>
46# define MAP_STACK 0x20000 47#include <linux/stringify.h>
47#endif
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 48
74#ifndef O_CLOEXEC 49#ifndef O_CLOEXEC
75# define O_CLOEXEC 02000000 50# define O_CLOEXEC 02000000
76#endif 51#endif
77 52
78#ifndef SOCK_DCCP 53struct trace {
79# define SOCK_DCCP 6 54 struct perf_tool tool;
80#endif 55 struct syscalltbl *sctbl;
81 56 struct {
82#ifndef SOCK_CLOEXEC 57 int max;
83# define SOCK_CLOEXEC 02000000 58 struct syscall *table;
84#endif 59 struct {
85 60 struct perf_evsel *sys_enter,
86#ifndef SOCK_NONBLOCK 61 *sys_exit;
87# define SOCK_NONBLOCK 00004000 62 } events;
88#endif 63 } syscalls;
89 64 struct record_opts opts;
90#ifndef MSG_CMSG_CLOEXEC 65 struct perf_evlist *evlist;
91# define MSG_CMSG_CLOEXEC 0x40000000 66 struct machine *host;
92#endif 67 struct thread *current;
93 68 u64 base_time;
94#ifndef PERF_FLAG_FD_NO_GROUP 69 FILE *output;
95# define PERF_FLAG_FD_NO_GROUP (1UL << 0) 70 unsigned long nr_events;
96#endif 71 struct strlist *ev_qualifier;
97 72 struct {
98#ifndef PERF_FLAG_FD_OUTPUT 73 size_t nr;
99# define PERF_FLAG_FD_OUTPUT (1UL << 1) 74 int *entries;
100#endif 75 } ev_qualifier_ids;
101 76 struct intlist *tid_list;
102#ifndef PERF_FLAG_PID_CGROUP 77 struct intlist *pid_list;
103# define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */ 78 struct {
104#endif 79 size_t nr;
105 80 pid_t *entries;
106#ifndef PERF_FLAG_FD_CLOEXEC 81 } filter_pids;
107# define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */ 82 double duration_filter;
108#endif 83 double runtime_ms;
109 84 struct {
85 u64 vfs_getname,
86 proc_getname;
87 } stats;
88 unsigned int max_stack;
89 unsigned int min_stack;
90 bool not_ev_qualifier;
91 bool live;
92 bool full_time;
93 bool sched;
94 bool multiple_threads;
95 bool summary;
96 bool summary_only;
97 bool show_comm;
98 bool show_tool_stats;
99 bool trace_syscalls;
100 bool kernel_syscallchains;
101 bool force;
102 bool vfs_getname;
103 int trace_pgfaults;
104 int open_id;
105};
110 106
111struct tp_field { 107struct tp_field {
112 int offset; 108 int offset;
@@ -337,6 +333,10 @@ static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
337 333
338#define SCA_FD syscall_arg__scnprintf_fd 334#define SCA_FD syscall_arg__scnprintf_fd
339 335
336#ifndef AT_FDCWD
337#define AT_FDCWD -100
338#endif
339
340static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size, 340static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
341 struct syscall_arg *arg) 341 struct syscall_arg *arg)
342{ 342{
@@ -371,221 +371,6 @@ static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
371 371
372#define SCA_INT syscall_arg__scnprintf_int 372#define SCA_INT syscall_arg__scnprintf_int
373 373
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[] = { 374static const char *bpf_cmd[] = {
590 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM", 375 "MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
591 "MAP_GET_NEXT_KEY", "PROG_LOAD", 376 "MAP_GET_NEXT_KEY", "PROG_LOAD",
@@ -652,110 +437,6 @@ static const char *socket_families[] = {
652}; 437};
653static DEFINE_STRARRAY(socket_families); 438static DEFINE_STRARRAY(socket_families);
654 439
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, 440static size_t syscall_arg__scnprintf_access_mode(char *bf, size_t size,
760 struct syscall_arg *arg) 441 struct syscall_arg *arg)
761{ 442{
@@ -788,116 +469,6 @@ static size_t syscall_arg__scnprintf_filename(char *bf, size_t size,
788 469
789#define SCA_FILENAME syscall_arg__scnprintf_filename 470#define SCA_FILENAME syscall_arg__scnprintf_filename
790 471
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, 472static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
902 struct syscall_arg *arg) 473 struct syscall_arg *arg)
903{ 474{
@@ -921,59 +492,6 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
921 492
922#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags 493#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
923 494
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__) 495#if defined(__i386__) || defined(__x86_64__)
978/* 496/*
979 * FIXME: Make this available to all arches. 497 * FIXME: Make this available to all arches.
@@ -1001,105 +519,125 @@ static const char *tioctls[] = {
1001static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401); 519static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
1002#endif /* defined(__i386__) || defined(__x86_64__) */ 520#endif /* defined(__i386__) || defined(__x86_64__) */
1003 521
522#ifndef GRND_NONBLOCK
523#define GRND_NONBLOCK 0x0001
524#endif
525#ifndef GRND_RANDOM
526#define GRND_RANDOM 0x0002
527#endif
528
529static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
530 struct syscall_arg *arg)
531{
532 int printed = 0, flags = arg->val;
533
534#define P_FLAG(n) \
535 if (flags & GRND_##n) { \
536 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
537 flags &= ~GRND_##n; \
538 }
539
540 P_FLAG(RANDOM);
541 P_FLAG(NONBLOCK);
542#undef P_FLAG
543
544 if (flags)
545 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
546
547 return printed;
548}
549
550#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
551
1004#define STRARRAY(arg, name, array) \ 552#define STRARRAY(arg, name, array) \
1005 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \ 553 .arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
1006 .arg_parm = { [arg] = &strarray__##array, } 554 .arg_parm = { [arg] = &strarray__##array, }
1007 555
556#include "trace/beauty/eventfd.c"
557#include "trace/beauty/flock.c"
558#include "trace/beauty/futex_op.c"
559#include "trace/beauty/mmap.c"
560#include "trace/beauty/mode_t.c"
561#include "trace/beauty/msg_flags.c"
562#include "trace/beauty/open_flags.c"
563#include "trace/beauty/perf_event_open.c"
564#include "trace/beauty/pid.c"
565#include "trace/beauty/sched_policy.c"
566#include "trace/beauty/seccomp.c"
567#include "trace/beauty/signum.c"
568#include "trace/beauty/socket_type.c"
569#include "trace/beauty/waitid_options.c"
570
1008static struct syscall_fmt { 571static struct syscall_fmt {
1009 const char *name; 572 const char *name;
1010 const char *alias; 573 const char *alias;
1011 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg); 574 size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
1012 void *arg_parm[6]; 575 void *arg_parm[6];
1013 bool errmsg; 576 bool errmsg;
577 bool errpid;
1014 bool timeout; 578 bool timeout;
1015 bool hexret; 579 bool hexret;
1016} syscall_fmts[] = { 580} syscall_fmts[] = {
1017 { .name = "access", .errmsg = true, 581 { .name = "access", .errmsg = true,
1018 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ 582 .arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
1019 [1] = SCA_ACCMODE, /* mode */ }, },
1020 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", }, 583 { .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
1021 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), }, 584 { .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
1022 { .name = "brk", .hexret = true, 585 { .name = "brk", .hexret = true,
1023 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, }, 586 .arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
1024 { .name = "chdir", .errmsg = true, 587 { .name = "chdir", .errmsg = true, },
1025 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 588 { .name = "chmod", .errmsg = true, },
1026 { .name = "chmod", .errmsg = true, 589 { .name = "chroot", .errmsg = true, },
1027 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1028 { .name = "chroot", .errmsg = true,
1029 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1030 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), }, 590 { .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
591 { .name = "clone", .errpid = true, },
1031 { .name = "close", .errmsg = true, 592 { .name = "close", .errmsg = true,
1032 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, }, 593 .arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
1033 { .name = "connect", .errmsg = true, }, 594 { .name = "connect", .errmsg = true, },
1034 { .name = "creat", .errmsg = true, 595 { .name = "creat", .errmsg = true, },
1035 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 596 { .name = "dup", .errmsg = true, },
1036 { .name = "dup", .errmsg = true, 597 { .name = "dup2", .errmsg = true, },
1037 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 598 { .name = "dup3", .errmsg = true, },
1038 { .name = "dup2", .errmsg = true,
1039 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1040 { .name = "dup3", .errmsg = true,
1041 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1042 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), }, 599 { .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
1043 { .name = "eventfd2", .errmsg = true, 600 { .name = "eventfd2", .errmsg = true,
1044 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, }, 601 .arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
1045 { .name = "faccessat", .errmsg = true, 602 { .name = "faccessat", .errmsg = true, },
1046 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 603 { .name = "fadvise64", .errmsg = true, },
1047 [1] = SCA_FILENAME, /* filename */ }, }, 604 { .name = "fallocate", .errmsg = true, },
1048 { .name = "fadvise64", .errmsg = true, 605 { .name = "fchdir", .errmsg = true, },
1049 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 606 { .name = "fchmod", .errmsg = true, },
1050 { .name = "fallocate", .errmsg = true,
1051 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1052 { .name = "fchdir", .errmsg = true,
1053 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1054 { .name = "fchmod", .errmsg = true,
1055 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1056 { .name = "fchmodat", .errmsg = true, 607 { .name = "fchmodat", .errmsg = true,
1057 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 608 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1058 [1] = SCA_FILENAME, /* filename */ }, }, 609 { .name = "fchown", .errmsg = true, },
1059 { .name = "fchown", .errmsg = true,
1060 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1061 { .name = "fchownat", .errmsg = true, 610 { .name = "fchownat", .errmsg = true,
1062 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 611 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1063 [1] = SCA_FILENAME, /* filename */ }, },
1064 { .name = "fcntl", .errmsg = true, 612 { .name = "fcntl", .errmsg = true,
1065 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 613 .arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
1066 [1] = SCA_STRARRAY, /* cmd */ },
1067 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, }, 614 .arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
1068 { .name = "fdatasync", .errmsg = true, 615 { .name = "fdatasync", .errmsg = true, },
1069 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1070 { .name = "flock", .errmsg = true, 616 { .name = "flock", .errmsg = true,
1071 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 617 .arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
1072 [1] = SCA_FLOCK, /* cmd */ }, }, 618 { .name = "fsetxattr", .errmsg = true, },
1073 { .name = "fsetxattr", .errmsg = true, 619 { .name = "fstat", .errmsg = true, .alias = "newfstat", },
1074 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 620 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
1075 { .name = "fstat", .errmsg = true, .alias = "newfstat", 621 { .name = "fstatfs", .errmsg = true, },
1076 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 622 { .name = "fsync", .errmsg = true, },
1077 { .name = "fstatat", .errmsg = true, .alias = "newfstatat", 623 { .name = "ftruncate", .errmsg = true, },
1078 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1079 [1] = SCA_FILENAME, /* filename */ }, },
1080 { .name = "fstatfs", .errmsg = true,
1081 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1082 { .name = "fsync", .errmsg = true,
1083 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1084 { .name = "ftruncate", .errmsg = true,
1085 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1086 { .name = "futex", .errmsg = true, 624 { .name = "futex", .errmsg = true,
1087 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, }, 625 .arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
1088 { .name = "futimesat", .errmsg = true, 626 { .name = "futimesat", .errmsg = true,
1089 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 627 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1090 [1] = SCA_FILENAME, /* filename */ }, }, 628 { .name = "getdents", .errmsg = true, },
1091 { .name = "getdents", .errmsg = true, 629 { .name = "getdents64", .errmsg = true, },
1092 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1093 { .name = "getdents64", .errmsg = true,
1094 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1095 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 630 { .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
631 { .name = "getpid", .errpid = true, },
632 { .name = "getpgid", .errpid = true, },
633 { .name = "getppid", .errpid = true, },
634 { .name = "getrandom", .errmsg = true,
635 .arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
1096 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 636 { .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1097 { .name = "getxattr", .errmsg = true, 637 { .name = "getxattr", .errmsg = true, },
1098 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 638 { .name = "inotify_add_watch", .errmsg = true, },
1099 { .name = "inotify_add_watch", .errmsg = true,
1100 .arg_scnprintf = { [1] = SCA_FILENAME, /* pathname */ }, },
1101 { .name = "ioctl", .errmsg = true, 639 { .name = "ioctl", .errmsg = true,
1102 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 640 .arg_scnprintf = {
1103#if defined(__i386__) || defined(__x86_64__) 641#if defined(__i386__) || defined(__x86_64__)
1104/* 642/*
1105 * FIXME: Make this available to all arches. 643 * FIXME: Make this available to all arches.
@@ -1113,41 +651,28 @@ static struct syscall_fmt {
1113 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), }, 651 { .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
1114 { .name = "kill", .errmsg = true, 652 { .name = "kill", .errmsg = true,
1115 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 653 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1116 { .name = "lchown", .errmsg = true, 654 { .name = "lchown", .errmsg = true, },
1117 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 655 { .name = "lgetxattr", .errmsg = true, },
1118 { .name = "lgetxattr", .errmsg = true,
1119 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1120 { .name = "linkat", .errmsg = true, 656 { .name = "linkat", .errmsg = true,
1121 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, }, 657 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1122 { .name = "listxattr", .errmsg = true, 658 { .name = "listxattr", .errmsg = true, },
1123 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 659 { .name = "llistxattr", .errmsg = true, },
1124 { .name = "llistxattr", .errmsg = true, 660 { .name = "lremovexattr", .errmsg = true, },
1125 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1126 { .name = "lremovexattr", .errmsg = true,
1127 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1128 { .name = "lseek", .errmsg = true, 661 { .name = "lseek", .errmsg = true,
1129 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 662 .arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
1130 [2] = SCA_STRARRAY, /* whence */ },
1131 .arg_parm = { [2] = &strarray__whences, /* whence */ }, }, 663 .arg_parm = { [2] = &strarray__whences, /* whence */ }, },
1132 { .name = "lsetxattr", .errmsg = true, 664 { .name = "lsetxattr", .errmsg = true, },
1133 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 665 { .name = "lstat", .errmsg = true, .alias = "newlstat", },
1134 { .name = "lstat", .errmsg = true, .alias = "newlstat", 666 { .name = "lsxattr", .errmsg = true, },
1135 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1136 { .name = "lsxattr", .errmsg = true,
1137 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1138 { .name = "madvise", .errmsg = true, 667 { .name = "madvise", .errmsg = true,
1139 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 668 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1140 [2] = SCA_MADV_BHV, /* behavior */ }, }, 669 [2] = SCA_MADV_BHV, /* behavior */ }, },
1141 { .name = "mkdir", .errmsg = true, 670 { .name = "mkdir", .errmsg = true, },
1142 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1143 { .name = "mkdirat", .errmsg = true, 671 { .name = "mkdirat", .errmsg = true,
1144 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 672 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1145 [1] = SCA_FILENAME, /* pathname */ }, }, 673 { .name = "mknod", .errmsg = true, },
1146 { .name = "mknod", .errmsg = true,
1147 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1148 { .name = "mknodat", .errmsg = true, 674 { .name = "mknodat", .errmsg = true,
1149 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ 675 .arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
1150 [1] = SCA_FILENAME, /* filename */ }, },
1151 { .name = "mlock", .errmsg = true, 676 { .name = "mlock", .errmsg = true,
1152 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, }, 677 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
1153 { .name = "mlockall", .errmsg = true, 678 { .name = "mlockall", .errmsg = true,
@@ -1155,8 +680,7 @@ static struct syscall_fmt {
1155 { .name = "mmap", .hexret = true, 680 { .name = "mmap", .hexret = true,
1156 .arg_scnprintf = { [0] = SCA_HEX, /* addr */ 681 .arg_scnprintf = { [0] = SCA_HEX, /* addr */
1157 [2] = SCA_MMAP_PROT, /* prot */ 682 [2] = SCA_MMAP_PROT, /* prot */
1158 [3] = SCA_MMAP_FLAGS, /* flags */ 683 [3] = SCA_MMAP_FLAGS, /* flags */ }, },
1159 [4] = SCA_FD, /* fd */ }, },
1160 { .name = "mprotect", .errmsg = true, 684 { .name = "mprotect", .errmsg = true,
1161 .arg_scnprintf = { [0] = SCA_HEX, /* start */ 685 .arg_scnprintf = { [0] = SCA_HEX, /* start */
1162 [2] = SCA_MMAP_PROT, /* prot */ }, }, 686 [2] = SCA_MMAP_PROT, /* prot */ }, },
@@ -1173,60 +697,43 @@ static struct syscall_fmt {
1173 { .name = "name_to_handle_at", .errmsg = true, 697 { .name = "name_to_handle_at", .errmsg = true,
1174 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 698 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1175 { .name = "newfstatat", .errmsg = true, 699 { .name = "newfstatat", .errmsg = true,
1176 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 700 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1177 [1] = SCA_FILENAME, /* filename */ }, },
1178 { .name = "open", .errmsg = true, 701 { .name = "open", .errmsg = true,
1179 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ 702 .arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
1180 [1] = SCA_OPEN_FLAGS, /* flags */ }, },
1181 { .name = "open_by_handle_at", .errmsg = true, 703 { .name = "open_by_handle_at", .errmsg = true,
1182 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 704 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1183 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 705 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1184 { .name = "openat", .errmsg = true, 706 { .name = "openat", .errmsg = true,
1185 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 707 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
1186 [1] = SCA_FILENAME, /* filename */
1187 [2] = SCA_OPEN_FLAGS, /* flags */ }, }, 708 [2] = SCA_OPEN_FLAGS, /* flags */ }, },
1188 { .name = "perf_event_open", .errmsg = true, 709 { .name = "perf_event_open", .errmsg = true,
1189 .arg_scnprintf = { [1] = SCA_INT, /* pid */ 710 .arg_scnprintf = { [2] = SCA_INT, /* cpu */
1190 [2] = SCA_INT, /* cpu */
1191 [3] = SCA_FD, /* group_fd */ 711 [3] = SCA_FD, /* group_fd */
1192 [4] = SCA_PERF_FLAGS, /* flags */ }, }, 712 [4] = SCA_PERF_FLAGS, /* flags */ }, },
1193 { .name = "pipe2", .errmsg = true, 713 { .name = "pipe2", .errmsg = true,
1194 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, }, 714 .arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
1195 { .name = "poll", .errmsg = true, .timeout = true, }, 715 { .name = "poll", .errmsg = true, .timeout = true, },
1196 { .name = "ppoll", .errmsg = true, .timeout = true, }, 716 { .name = "ppoll", .errmsg = true, .timeout = true, },
1197 { .name = "pread", .errmsg = true, .alias = "pread64", 717 { .name = "pread", .errmsg = true, .alias = "pread64", },
1198 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 718 { .name = "preadv", .errmsg = true, .alias = "pread", },
1199 { .name = "preadv", .errmsg = true, .alias = "pread",
1200 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1201 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), }, 719 { .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
1202 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", 720 { .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
1203 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 721 { .name = "pwritev", .errmsg = true, },
1204 { .name = "pwritev", .errmsg = true, 722 { .name = "read", .errmsg = true, },
1205 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 723 { .name = "readlink", .errmsg = true, },
1206 { .name = "read", .errmsg = true,
1207 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1208 { .name = "readlink", .errmsg = true,
1209 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
1210 { .name = "readlinkat", .errmsg = true, 724 { .name = "readlinkat", .errmsg = true,
1211 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 725 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1212 [1] = SCA_FILENAME, /* pathname */ }, }, 726 { .name = "readv", .errmsg = true, },
1213 { .name = "readv", .errmsg = true,
1214 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1215 { .name = "recvfrom", .errmsg = true, 727 { .name = "recvfrom", .errmsg = true,
1216 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 728 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1217 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1218 { .name = "recvmmsg", .errmsg = true, 729 { .name = "recvmmsg", .errmsg = true,
1219 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 730 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1220 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1221 { .name = "recvmsg", .errmsg = true, 731 { .name = "recvmsg", .errmsg = true,
1222 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 732 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1223 [2] = SCA_MSG_FLAGS, /* flags */ }, }, 733 { .name = "removexattr", .errmsg = true, },
1224 { .name = "removexattr", .errmsg = true,
1225 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1226 { .name = "renameat", .errmsg = true, 734 { .name = "renameat", .errmsg = true,
1227 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, }, 735 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1228 { .name = "rmdir", .errmsg = true, 736 { .name = "rmdir", .errmsg = true, },
1229 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1230 { .name = "rt_sigaction", .errmsg = true, 737 { .name = "rt_sigaction", .errmsg = true,
1231 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, }, 738 .arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
1232 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), }, 739 { .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
@@ -1234,22 +741,24 @@ static struct syscall_fmt {
1234 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 741 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1235 { .name = "rt_tgsigqueueinfo", .errmsg = true, 742 { .name = "rt_tgsigqueueinfo", .errmsg = true,
1236 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 743 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
744 { .name = "sched_setscheduler", .errmsg = true,
745 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
746 { .name = "seccomp", .errmsg = true,
747 .arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
748 [1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
1237 { .name = "select", .errmsg = true, .timeout = true, }, 749 { .name = "select", .errmsg = true, .timeout = true, },
1238 { .name = "sendmmsg", .errmsg = true, 750 { .name = "sendmmsg", .errmsg = true,
1239 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 751 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1240 [3] = SCA_MSG_FLAGS, /* flags */ }, },
1241 { .name = "sendmsg", .errmsg = true, 752 { .name = "sendmsg", .errmsg = true,
1242 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 753 .arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
1243 [2] = SCA_MSG_FLAGS, /* flags */ }, },
1244 { .name = "sendto", .errmsg = true, 754 { .name = "sendto", .errmsg = true,
1245 .arg_scnprintf = { [0] = SCA_FD, /* fd */ 755 .arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
1246 [3] = SCA_MSG_FLAGS, /* flags */ }, }, 756 { .name = "set_tid_address", .errpid = true, },
1247 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), }, 757 { .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
758 { .name = "setpgid", .errmsg = true, },
1248 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), }, 759 { .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
1249 { .name = "setxattr", .errmsg = true, 760 { .name = "setxattr", .errmsg = true, },
1250 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 761 { .name = "shutdown", .errmsg = true, },
1251 { .name = "shutdown", .errmsg = true,
1252 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1253 { .name = "socket", .errmsg = true, 762 { .name = "socket", .errmsg = true,
1254 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 763 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1255 [1] = SCA_SK_TYPE, /* type */ }, 764 [1] = SCA_SK_TYPE, /* type */ },
@@ -1258,10 +767,8 @@ static struct syscall_fmt {
1258 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */ 767 .arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
1259 [1] = SCA_SK_TYPE, /* type */ }, 768 [1] = SCA_SK_TYPE, /* type */ },
1260 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, }, 769 .arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
1261 { .name = "stat", .errmsg = true, .alias = "newstat", 770 { .name = "stat", .errmsg = true, .alias = "newstat", },
1262 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, }, 771 { .name = "statfs", .errmsg = true, },
1263 { .name = "statfs", .errmsg = true,
1264 .arg_scnprintf = { [0] = SCA_FILENAME, /* pathname */ }, },
1265 { .name = "swapoff", .errmsg = true, 772 { .name = "swapoff", .errmsg = true,
1266 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, }, 773 .arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
1267 { .name = "swapon", .errmsg = true, 774 { .name = "swapon", .errmsg = true,
@@ -1272,25 +779,21 @@ static struct syscall_fmt {
1272 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 779 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
1273 { .name = "tkill", .errmsg = true, 780 { .name = "tkill", .errmsg = true,
1274 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 781 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
1275 { .name = "truncate", .errmsg = true, 782 { .name = "truncate", .errmsg = true, },
1276 .arg_scnprintf = { [0] = SCA_FILENAME, /* path */ }, },
1277 { .name = "uname", .errmsg = true, .alias = "newuname", }, 783 { .name = "uname", .errmsg = true, .alias = "newuname", },
1278 { .name = "unlinkat", .errmsg = true, 784 { .name = "unlinkat", .errmsg = true,
1279 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ 785 .arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
1280 [1] = SCA_FILENAME, /* pathname */ }, }, 786 { .name = "utime", .errmsg = true, },
1281 { .name = "utime", .errmsg = true,
1282 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, },
1283 { .name = "utimensat", .errmsg = true, 787 { .name = "utimensat", .errmsg = true,
1284 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ 788 .arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
1285 [1] = SCA_FILENAME, /* filename */ }, }, 789 { .name = "utimes", .errmsg = true, },
1286 { .name = "utimes", .errmsg = true, 790 { .name = "vmsplice", .errmsg = true, },
1287 .arg_scnprintf = { [0] = SCA_FILENAME, /* filename */ }, }, 791 { .name = "wait4", .errpid = true,
1288 { .name = "vmsplice", .errmsg = true, 792 .arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
1289 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 793 { .name = "waitid", .errpid = true,
1290 { .name = "write", .errmsg = true, 794 .arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
1291 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, }, 795 { .name = "write", .errmsg = true, },
1292 { .name = "writev", .errmsg = true, 796 { .name = "writev", .errmsg = true, },
1293 .arg_scnprintf = { [0] = SCA_FD, /* fd */ }, },
1294}; 797};
1295 798
1296static int syscall_fmt__cmp(const void *name, const void *fmtp) 799static int syscall_fmt__cmp(const void *name, const void *fmtp)
@@ -1398,59 +901,6 @@ fail:
1398 901
1399static const size_t trace__entry_str_size = 2048; 902static const size_t trace__entry_str_size = 2048;
1400 903
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) 904static int trace__set_fd_pathname(struct thread *thread, int fd, const char *pathname)
1455{ 905{
1456 struct thread_trace *ttrace = thread__priv(thread); 906 struct thread_trace *ttrace = thread__priv(thread);
@@ -1618,6 +1068,7 @@ static int trace__process_event(struct trace *trace, struct machine *machine,
1618 color_fprintf(trace->output, PERF_COLOR_RED, 1068 color_fprintf(trace->output, PERF_COLOR_RED,
1619 "LOST %" PRIu64 " events!\n", event->lost.lost); 1069 "LOST %" PRIu64 " events!\n", event->lost.lost);
1620 ret = machine__process_lost_event(machine, event, sample); 1070 ret = machine__process_lost_event(machine, event, sample);
1071 break;
1621 default: 1072 default:
1622 ret = machine__process_event(machine, event, sample); 1073 ret = machine__process_event(machine, event, sample);
1623 break; 1074 break;
@@ -1635,6 +1086,24 @@ static int trace__tool_process(struct perf_tool *tool,
1635 return trace__process_event(trace, machine, event, sample); 1086 return trace__process_event(trace, machine, event, sample);
1636} 1087}
1637 1088
1089static char *trace__machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, char **modp)
1090{
1091 struct machine *machine = vmachine;
1092
1093 if (machine->kptr_restrict_warned)
1094 return NULL;
1095
1096 if (symbol_conf.kptr_restrict) {
1097 pr_warning("Kernel address maps (/proc/{kallsyms,modules}) are restricted.\n\n"
1098 "Check /proc/sys/kernel/kptr_restrict.\n\n"
1099 "Kernel samples will not be resolved.\n");
1100 machine->kptr_restrict_warned = true;
1101 return NULL;
1102 }
1103
1104 return machine__resolve_kernel_addr(vmachine, addrp, modp);
1105}
1106
1638static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist) 1107static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1639{ 1108{
1640 int err = symbol__init(NULL); 1109 int err = symbol__init(NULL);
@@ -1646,7 +1115,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1646 if (trace->host == NULL) 1115 if (trace->host == NULL)
1647 return -ENOMEM; 1116 return -ENOMEM;
1648 1117
1649 if (trace_event__register_resolver(trace->host, machine__resolve_kernel_addr) < 0) 1118 if (trace_event__register_resolver(trace->host, trace__machine__resolve_kernel_addr) < 0)
1650 return -errno; 1119 return -errno;
1651 1120
1652 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target, 1121 err = __machine__synthesize_threads(trace->host, &trace->tool, &trace->opts.target,
@@ -1661,7 +1130,7 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
1661static int syscall__set_arg_fmts(struct syscall *sc) 1130static int syscall__set_arg_fmts(struct syscall *sc)
1662{ 1131{
1663 struct format_field *field; 1132 struct format_field *field;
1664 int idx = 0; 1133 int idx = 0, len;
1665 1134
1666 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *)); 1135 sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
1667 if (sc->arg_scnprintf == NULL) 1136 if (sc->arg_scnprintf == NULL)
@@ -1673,8 +1142,31 @@ static int syscall__set_arg_fmts(struct syscall *sc)
1673 for (field = sc->args; field; field = field->next) { 1142 for (field = sc->args; field; field = field->next) {
1674 if (sc->fmt && sc->fmt->arg_scnprintf[idx]) 1143 if (sc->fmt && sc->fmt->arg_scnprintf[idx])
1675 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx]; 1144 sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
1145 else if (strcmp(field->type, "const char *") == 0 &&
1146 (strcmp(field->name, "filename") == 0 ||
1147 strcmp(field->name, "path") == 0 ||
1148 strcmp(field->name, "pathname") == 0))
1149 sc->arg_scnprintf[idx] = SCA_FILENAME;
1676 else if (field->flags & FIELD_IS_POINTER) 1150 else if (field->flags & FIELD_IS_POINTER)
1677 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex; 1151 sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
1152 else if (strcmp(field->type, "pid_t") == 0)
1153 sc->arg_scnprintf[idx] = SCA_PID;
1154 else if (strcmp(field->type, "umode_t") == 0)
1155 sc->arg_scnprintf[idx] = SCA_MODE_T;
1156 else if ((strcmp(field->type, "int") == 0 ||
1157 strcmp(field->type, "unsigned int") == 0 ||
1158 strcmp(field->type, "long") == 0) &&
1159 (len = strlen(field->name)) >= 2 &&
1160 strcmp(field->name + len - 2, "fd") == 0) {
1161 /*
1162 * /sys/kernel/tracing/events/syscalls/sys_enter*
1163 * egrep 'field:.*fd;' .../format|sed -r 's/.*field:([a-z ]+) [a-z_]*fd.+/\1/g'|sort|uniq -c
1164 * 65 int
1165 * 23 unsigned int
1166 * 7 unsigned long
1167 */
1168 sc->arg_scnprintf[idx] = SCA_FD;
1169 }
1678 ++idx; 1170 ++idx;
1679 } 1171 }
1680 1172
@@ -1685,7 +1177,7 @@ static int trace__read_syscall_info(struct trace *trace, int id)
1685{ 1177{
1686 char tp_name[128]; 1178 char tp_name[128];
1687 struct syscall *sc; 1179 struct syscall *sc;
1688 const char *name = audit_syscall_to_name(id, trace->audit.machine); 1180 const char *name = syscalltbl__name(trace->sctbl, id);
1689 1181
1690 if (name == NULL) 1182 if (name == NULL)
1691 return -1; 1183 return -1;
@@ -1758,9 +1250,9 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1758 1250
1759 i = 0; 1251 i = 0;
1760 1252
1761 strlist__for_each(pos, trace->ev_qualifier) { 1253 strlist__for_each_entry(pos, trace->ev_qualifier) {
1762 const char *sc = pos->s; 1254 const char *sc = pos->s;
1763 int id = audit_name_to_syscall(sc, trace->audit.machine); 1255 int id = syscalltbl__id(trace->sctbl, sc);
1764 1256
1765 if (id < 0) { 1257 if (id < 0) {
1766 if (err == 0) { 1258 if (err == 0) {
@@ -1846,7 +1338,12 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
1846 "%ld", val); 1338 "%ld", val);
1847 } 1339 }
1848 } 1340 }
1849 } else { 1341 } else if (IS_ERR(sc->tp_format)) {
1342 /*
1343 * If we managed to read the tracepoint /format file, then we
1344 * may end up not having any args, like with gettid(), so only
1345 * print the raw args when we didn't manage to read it.
1346 */
1850 int i = 0; 1347 int i = 0;
1851 1348
1852 while (i < 6) { 1349 while (i < 6) {
@@ -1987,7 +1484,7 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1987 goto out_put; 1484 goto out_put;
1988 } 1485 }
1989 1486
1990 if (!trace->summary_only) 1487 if (!(trace->duration_filter || trace->summary_only || trace->min_stack))
1991 trace__printf_interrupted_entry(trace, sample); 1488 trace__printf_interrupted_entry(trace, sample);
1992 1489
1993 ttrace->entry_time = sample->time; 1490 ttrace->entry_time = sample->time;
@@ -1998,9 +1495,9 @@ static int trace__sys_enter(struct trace *trace, struct perf_evsel *evsel,
1998 args, trace, thread); 1495 args, trace, thread);
1999 1496
2000 if (sc->is_exit) { 1497 if (sc->is_exit) {
2001 if (!trace->duration_filter && !trace->summary_only) { 1498 if (!(trace->duration_filter || trace->summary_only || trace->min_stack)) {
2002 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output); 1499 trace__fprintf_entry_head(trace, thread, 1, sample->time, trace->output);
2003 fprintf(trace->output, "%-70s\n", ttrace->entry_str); 1500 fprintf(trace->output, "%-70s)\n", ttrace->entry_str);
2004 } 1501 }
2005 } else { 1502 } else {
2006 ttrace->entry_pending = true; 1503 ttrace->entry_pending = true;
@@ -2018,6 +1515,29 @@ out_put:
2018 return err; 1515 return err;
2019} 1516}
2020 1517
1518static int trace__resolve_callchain(struct trace *trace, struct perf_evsel *evsel,
1519 struct perf_sample *sample,
1520 struct callchain_cursor *cursor)
1521{
1522 struct addr_location al;
1523
1524 if (machine__resolve(trace->host, &al, sample) < 0 ||
1525 thread__resolve_callchain(al.thread, cursor, evsel, sample, NULL, NULL, trace->max_stack))
1526 return -1;
1527
1528 return 0;
1529}
1530
1531static int trace__fprintf_callchain(struct trace *trace, struct perf_sample *sample)
1532{
1533 /* TODO: user-configurable print_opts */
1534 const unsigned int print_opts = EVSEL__PRINT_SYM |
1535 EVSEL__PRINT_DSO |
1536 EVSEL__PRINT_UNKNOWN_AS_ADDR;
1537
1538 return sample__fprintf_callchain(sample, 38, print_opts, &callchain_cursor, trace->output);
1539}
1540
2021static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel, 1541static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2022 union perf_event *event __maybe_unused, 1542 union perf_event *event __maybe_unused,
2023 struct perf_sample *sample) 1543 struct perf_sample *sample)
@@ -2025,7 +1545,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2025 long ret; 1545 long ret;
2026 u64 duration = 0; 1546 u64 duration = 0;
2027 struct thread *thread; 1547 struct thread *thread;
2028 int id = perf_evsel__sc_tp_uint(evsel, id, sample), err = -1; 1548 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); 1549 struct syscall *sc = trace__syscall_info(trace, evsel, id);
2030 struct thread_trace *ttrace; 1550 struct thread_trace *ttrace;
2031 1551
@@ -2042,7 +1562,7 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2042 1562
2043 ret = perf_evsel__sc_tp_uint(evsel, ret, sample); 1563 ret = perf_evsel__sc_tp_uint(evsel, ret, sample);
2044 1564
2045 if (id == trace->audit.open_id && ret >= 0 && ttrace->filename.pending_open) { 1565 if (id == trace->open_id && ret >= 0 && ttrace->filename.pending_open) {
2046 trace__set_fd_pathname(thread, ret, ttrace->filename.name); 1566 trace__set_fd_pathname(thread, ret, ttrace->filename.name);
2047 ttrace->filename.pending_open = false; 1567 ttrace->filename.pending_open = false;
2048 ++trace->stats.vfs_getname; 1568 ++trace->stats.vfs_getname;
@@ -2057,6 +1577,15 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2057 } else if (trace->duration_filter) 1577 } else if (trace->duration_filter)
2058 goto out; 1578 goto out;
2059 1579
1580 if (sample->callchain) {
1581 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1582 if (callchain_ret == 0) {
1583 if (callchain_cursor.nr < trace->min_stack)
1584 goto out;
1585 callchain_ret = 1;
1586 }
1587 }
1588
2060 if (trace->summary_only) 1589 if (trace->summary_only)
2061 goto out; 1590 goto out;
2062 1591
@@ -2073,9 +1602,9 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
2073 if (sc->fmt == NULL) { 1602 if (sc->fmt == NULL) {
2074signed_print: 1603signed_print:
2075 fprintf(trace->output, ") = %ld", ret); 1604 fprintf(trace->output, ") = %ld", ret);
2076 } else if (ret < 0 && sc->fmt->errmsg) { 1605 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
2077 char bf[STRERR_BUFSIZE]; 1606 char bf[STRERR_BUFSIZE];
2078 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1607 const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
2079 *e = audit_errno_to_name(-ret); 1608 *e = audit_errno_to_name(-ret);
2080 1609
2081 fprintf(trace->output, ") = -1 %s %s", e, emsg); 1610 fprintf(trace->output, ") = -1 %s %s", e, emsg);
@@ -2083,10 +1612,24 @@ signed_print:
2083 fprintf(trace->output, ") = 0 Timeout"); 1612 fprintf(trace->output, ") = 0 Timeout");
2084 else if (sc->fmt->hexret) 1613 else if (sc->fmt->hexret)
2085 fprintf(trace->output, ") = %#lx", ret); 1614 fprintf(trace->output, ") = %#lx", ret);
2086 else 1615 else if (sc->fmt->errpid) {
1616 struct thread *child = machine__find_thread(trace->host, ret, ret);
1617
1618 if (child != NULL) {
1619 fprintf(trace->output, ") = %ld", ret);
1620 if (child->comm_set)
1621 fprintf(trace->output, " (%s)", thread__comm_str(child));
1622 thread__put(child);
1623 }
1624 } else
2087 goto signed_print; 1625 goto signed_print;
2088 1626
2089 fputc('\n', trace->output); 1627 fputc('\n', trace->output);
1628
1629 if (callchain_ret > 0)
1630 trace__fprintf_callchain(trace, sample);
1631 else if (callchain_ret < 0)
1632 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2090out: 1633out:
2091 ttrace->entry_pending = false; 1634 ttrace->entry_pending = false;
2092 err = 0; 1635 err = 0;
@@ -2217,6 +1760,17 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2217 union perf_event *event __maybe_unused, 1760 union perf_event *event __maybe_unused,
2218 struct perf_sample *sample) 1761 struct perf_sample *sample)
2219{ 1762{
1763 int callchain_ret = 0;
1764
1765 if (sample->callchain) {
1766 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1767 if (callchain_ret == 0) {
1768 if (callchain_cursor.nr < trace->min_stack)
1769 goto out;
1770 callchain_ret = 1;
1771 }
1772 }
1773
2220 trace__printf_interrupted_entry(trace, sample); 1774 trace__printf_interrupted_entry(trace, sample);
2221 trace__fprintf_tstamp(trace, sample->time, trace->output); 1775 trace__fprintf_tstamp(trace, sample->time, trace->output);
2222 1776
@@ -2234,6 +1788,12 @@ static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
2234 } 1788 }
2235 1789
2236 fprintf(trace->output, ")\n"); 1790 fprintf(trace->output, ")\n");
1791
1792 if (callchain_ret > 0)
1793 trace__fprintf_callchain(trace, sample);
1794 else if (callchain_ret < 0)
1795 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
1796out:
2237 return 0; 1797 return 0;
2238} 1798}
2239 1799
@@ -2264,8 +1824,19 @@ static int trace__pgfault(struct trace *trace,
2264 char map_type = 'd'; 1824 char map_type = 'd';
2265 struct thread_trace *ttrace; 1825 struct thread_trace *ttrace;
2266 int err = -1; 1826 int err = -1;
1827 int callchain_ret = 0;
2267 1828
2268 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid); 1829 thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
1830
1831 if (sample->callchain) {
1832 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
1833 if (callchain_ret == 0) {
1834 if (callchain_cursor.nr < trace->min_stack)
1835 goto out_put;
1836 callchain_ret = 1;
1837 }
1838 }
1839
2269 ttrace = thread__trace(thread, trace->output); 1840 ttrace = thread__trace(thread, trace->output);
2270 if (ttrace == NULL) 1841 if (ttrace == NULL)
2271 goto out_put; 1842 goto out_put;
@@ -2307,6 +1878,11 @@ static int trace__pgfault(struct trace *trace,
2307 print_location(trace->output, sample, &al, true, false); 1878 print_location(trace->output, sample, &al, true, false);
2308 1879
2309 fprintf(trace->output, " (%c%c)\n", map_type, al.level); 1880 fprintf(trace->output, " (%c%c)\n", map_type, al.level);
1881
1882 if (callchain_ret > 0)
1883 trace__fprintf_callchain(trace, sample);
1884 else if (callchain_ret < 0)
1885 pr_err("Problem processing %s callchain, skipping...\n", perf_evsel__name(evsel));
2310out: 1886out:
2311 err = 0; 1887 err = 0;
2312out_put: 1888out_put:
@@ -2326,6 +1902,23 @@ static bool skip_sample(struct trace *trace, struct perf_sample *sample)
2326 return false; 1902 return false;
2327} 1903}
2328 1904
1905static void trace__set_base_time(struct trace *trace,
1906 struct perf_evsel *evsel,
1907 struct perf_sample *sample)
1908{
1909 /*
1910 * BPF events were not setting PERF_SAMPLE_TIME, so be more robust
1911 * and don't use sample->time unconditionally, we may end up having
1912 * some other event in the future without PERF_SAMPLE_TIME for good
1913 * reason, i.e. we may not be interested in its timestamps, just in
1914 * it taking place, picking some piece of information when it
1915 * appears in our event stream (vfs_getname comes to mind).
1916 */
1917 if (trace->base_time == 0 && !trace->full_time &&
1918 (evsel->attr.sample_type & PERF_SAMPLE_TIME))
1919 trace->base_time = sample->time;
1920}
1921
2329static int trace__process_sample(struct perf_tool *tool, 1922static int trace__process_sample(struct perf_tool *tool,
2330 union perf_event *event, 1923 union perf_event *event,
2331 struct perf_sample *sample, 1924 struct perf_sample *sample,
@@ -2340,8 +1933,7 @@ static int trace__process_sample(struct perf_tool *tool,
2340 if (skip_sample(trace, sample)) 1933 if (skip_sample(trace, sample))
2341 return 0; 1934 return 0;
2342 1935
2343 if (!trace->full_time && trace->base_time == 0) 1936 trace__set_base_time(trace, evsel, sample);
2344 trace->base_time = sample->time;
2345 1937
2346 if (handler) { 1938 if (handler) {
2347 ++trace->nr_events; 1939 ++trace->nr_events;
@@ -2450,8 +2042,7 @@ static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
2450 return true; 2042 return true;
2451} 2043}
2452 2044
2453static int perf_evlist__add_pgfault(struct perf_evlist *evlist, 2045static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
2454 u64 config)
2455{ 2046{
2456 struct perf_evsel *evsel; 2047 struct perf_evsel *evsel;
2457 struct perf_event_attr attr = { 2048 struct perf_event_attr attr = {
@@ -2465,13 +2056,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
2465 event_attr_init(&attr); 2056 event_attr_init(&attr);
2466 2057
2467 evsel = perf_evsel__new(&attr); 2058 evsel = perf_evsel__new(&attr);
2468 if (!evsel) 2059 if (evsel)
2469 return -ENOMEM; 2060 evsel->handler = trace__pgfault;
2470
2471 evsel->handler = trace__pgfault;
2472 perf_evlist__add(evlist, evsel);
2473 2061
2474 return 0; 2062 return evsel;
2475} 2063}
2476 2064
2477static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) 2065static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
@@ -2479,9 +2067,6 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2479 const u32 type = event->header.type; 2067 const u32 type = event->header.type;
2480 struct perf_evsel *evsel; 2068 struct perf_evsel *evsel;
2481 2069
2482 if (!trace->full_time && trace->base_time == 0)
2483 trace->base_time = sample->time;
2484
2485 if (type != PERF_RECORD_SAMPLE) { 2070 if (type != PERF_RECORD_SAMPLE) {
2486 trace__process_event(trace, trace->host, event, sample); 2071 trace__process_event(trace, trace->host, event, sample);
2487 return; 2072 return;
@@ -2493,6 +2078,8 @@ static void trace__handle_event(struct trace *trace, union perf_event *event, st
2493 return; 2078 return;
2494 } 2079 }
2495 2080
2081 trace__set_base_time(trace, evsel, sample);
2082
2496 if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 2083 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
2497 sample->raw_data == NULL) { 2084 sample->raw_data == NULL) {
2498 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n", 2085 fprintf(trace->output, "%s sample with no payload for tid: %d, cpu %d, raw_size=%d, skipping...\n",
@@ -2527,6 +2114,15 @@ static int trace__add_syscall_newtp(struct trace *trace)
2527 perf_evlist__add(evlist, sys_enter); 2114 perf_evlist__add(evlist, sys_enter);
2528 perf_evlist__add(evlist, sys_exit); 2115 perf_evlist__add(evlist, sys_exit);
2529 2116
2117 if (callchain_param.enabled && !trace->kernel_syscallchains) {
2118 /*
2119 * We're interested only in the user space callchain
2120 * leading to the syscall, allow overriding that for
2121 * debugging reasons using --kernel_syscall_callchains
2122 */
2123 sys_exit->attr.exclude_callchain_kernel = 1;
2124 }
2125
2530 trace->syscalls.events.sys_enter = sys_enter; 2126 trace->syscalls.events.sys_enter = sys_enter;
2531 trace->syscalls.events.sys_exit = sys_exit; 2127 trace->syscalls.events.sys_exit = sys_exit;
2532 2128
@@ -2565,7 +2161,7 @@ out_enomem:
2565static int trace__run(struct trace *trace, int argc, const char **argv) 2161static int trace__run(struct trace *trace, int argc, const char **argv)
2566{ 2162{
2567 struct perf_evlist *evlist = trace->evlist; 2163 struct perf_evlist *evlist = trace->evlist;
2568 struct perf_evsel *evsel; 2164 struct perf_evsel *evsel, *pgfault_maj = NULL, *pgfault_min = NULL;
2569 int err = -1, i; 2165 int err = -1, i;
2570 unsigned long before; 2166 unsigned long before;
2571 const bool forks = argc > 0; 2167 const bool forks = argc > 0;
@@ -2579,14 +2175,19 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2579 if (trace->trace_syscalls) 2175 if (trace->trace_syscalls)
2580 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist); 2176 trace->vfs_getname = perf_evlist__add_vfs_getname(evlist);
2581 2177
2582 if ((trace->trace_pgfaults & TRACE_PFMAJ) && 2178 if ((trace->trace_pgfaults & TRACE_PFMAJ)) {
2583 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MAJ)) { 2179 pgfault_maj = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MAJ);
2584 goto out_error_mem; 2180 if (pgfault_maj == NULL)
2181 goto out_error_mem;
2182 perf_evlist__add(evlist, pgfault_maj);
2585 } 2183 }
2586 2184
2587 if ((trace->trace_pgfaults & TRACE_PFMIN) && 2185 if ((trace->trace_pgfaults & TRACE_PFMIN)) {
2588 perf_evlist__add_pgfault(evlist, PERF_COUNT_SW_PAGE_FAULTS_MIN)) 2186 pgfault_min = perf_evsel__new_pgfault(PERF_COUNT_SW_PAGE_FAULTS_MIN);
2589 goto out_error_mem; 2187 if (pgfault_min == NULL)
2188 goto out_error_mem;
2189 perf_evlist__add(evlist, pgfault_min);
2190 }
2590 2191
2591 if (trace->sched && 2192 if (trace->sched &&
2592 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime", 2193 perf_evlist__add_newtp(evlist, "sched", "sched_stat_runtime",
@@ -2605,7 +2206,45 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
2605 goto out_delete_evlist; 2206 goto out_delete_evlist;
2606 } 2207 }
2607 2208
2608 perf_evlist__config(evlist, &trace->opts); 2209 perf_evlist__config(evlist, &trace->opts, NULL);
2210
2211 if (callchain_param.enabled) {
2212 bool use_identifier = false;
2213
2214 if (trace->syscalls.events.sys_exit) {
2215 perf_evsel__config_callchain(trace->syscalls.events.sys_exit,
2216 &trace->opts, &callchain_param);
2217 use_identifier = true;
2218 }
2219
2220 if (pgfault_maj) {
2221 perf_evsel__config_callchain(pgfault_maj, &trace->opts, &callchain_param);
2222 use_identifier = true;
2223 }
2224
2225 if (pgfault_min) {
2226 perf_evsel__config_callchain(pgfault_min, &trace->opts, &callchain_param);
2227 use_identifier = true;
2228 }
2229
2230 if (use_identifier) {
2231 /*
2232 * Now we have evsels with different sample_ids, use
2233 * PERF_SAMPLE_IDENTIFIER to map from sample to evsel
2234 * from a fixed position in each ring buffer record.
2235 *
2236 * As of this the changeset introducing this comment, this
2237 * isn't strictly needed, as the fields that can come before
2238 * PERF_SAMPLE_ID are all used, but we'll probably disable
2239 * some of those for things like copying the payload of
2240 * pointer syscall arguments, and for vfs_getname we don't
2241 * need PERF_SAMPLE_ADDR and PERF_SAMPLE_IP, so do this
2242 * here as a warning we need to use PERF_SAMPLE_IDENTIFIER.
2243 */
2244 perf_evlist__set_sample_bit(evlist, IDENTIFIER);
2245 perf_evlist__reset_sample_bit(evlist, ID);
2246 }
2247 }
2609 2248
2610 signal(SIGCHLD, sig_handler); 2249 signal(SIGCHLD, sig_handler);
2611 signal(SIGINT, sig_handler); 2250 signal(SIGINT, sig_handler);
@@ -2766,7 +2405,7 @@ out_error_apply_filters:
2766 fprintf(trace->output, 2405 fprintf(trace->output,
2767 "Failed to set filter \"%s\" on event %s with %d (%s)\n", 2406 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2768 evsel->filter, perf_evsel__name(evsel), errno, 2407 evsel->filter, perf_evsel__name(evsel), errno,
2769 strerror_r(errno, errbuf, sizeof(errbuf))); 2408 str_error_r(errno, errbuf, sizeof(errbuf)));
2770 goto out_delete_evlist; 2409 goto out_delete_evlist;
2771} 2410}
2772out_error_mem: 2411out_error_mem:
@@ -2847,7 +2486,7 @@ static int trace__replay(struct trace *trace)
2847 goto out; 2486 goto out;
2848 } 2487 }
2849 2488
2850 evlist__for_each(session->evlist, evsel) { 2489 evlist__for_each_entry(session->evlist, evsel) {
2851 if (evsel->attr.type == PERF_TYPE_SOFTWARE && 2490 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2852 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ || 2491 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2853 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN || 2492 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
@@ -2883,15 +2522,29 @@ static size_t trace__fprintf_threads_header(FILE *fp)
2883 return printed; 2522 return printed;
2884} 2523}
2885 2524
2525DEFINE_RESORT_RB(syscall_stats, a->msecs > b->msecs,
2526 struct stats *stats;
2527 double msecs;
2528 int syscall;
2529)
2530{
2531 struct int_node *source = rb_entry(nd, struct int_node, rb_node);
2532 struct stats *stats = source->priv;
2533
2534 entry->syscall = source->i;
2535 entry->stats = stats;
2536 entry->msecs = stats ? (u64)stats->n * (avg_stats(stats) / NSEC_PER_MSEC) : 0;
2537}
2538
2886static size_t thread__dump_stats(struct thread_trace *ttrace, 2539static size_t thread__dump_stats(struct thread_trace *ttrace,
2887 struct trace *trace, FILE *fp) 2540 struct trace *trace, FILE *fp)
2888{ 2541{
2889 struct stats *stats;
2890 size_t printed = 0; 2542 size_t printed = 0;
2891 struct syscall *sc; 2543 struct syscall *sc;
2892 struct int_node *inode = intlist__first(ttrace->syscall_stats); 2544 struct rb_node *nd;
2545 DECLARE_RESORT_RB_INTLIST(syscall_stats, ttrace->syscall_stats);
2893 2546
2894 if (inode == NULL) 2547 if (syscall_stats == NULL)
2895 return 0; 2548 return 0;
2896 2549
2897 printed += fprintf(fp, "\n"); 2550 printed += fprintf(fp, "\n");
@@ -2900,9 +2553,8 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
2900 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n"); 2553 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2901 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n"); 2554 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
2902 2555
2903 /* each int_node is a syscall */ 2556 resort_rb__for_each_entry(nd, syscall_stats) {
2904 while (inode) { 2557 struct stats *stats = syscall_stats_entry->stats;
2905 stats = inode->priv;
2906 if (stats) { 2558 if (stats) {
2907 double min = (double)(stats->min) / NSEC_PER_MSEC; 2559 double min = (double)(stats->min) / NSEC_PER_MSEC;
2908 double max = (double)(stats->max) / NSEC_PER_MSEC; 2560 double max = (double)(stats->max) / NSEC_PER_MSEC;
@@ -2913,34 +2565,23 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
2913 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0; 2565 pct = avg ? 100.0 * stddev_stats(stats)/avg : 0.0;
2914 avg /= NSEC_PER_MSEC; 2566 avg /= NSEC_PER_MSEC;
2915 2567
2916 sc = &trace->syscalls.table[inode->i]; 2568 sc = &trace->syscalls.table[syscall_stats_entry->syscall];
2917 printed += fprintf(fp, " %-15s", sc->name); 2569 printed += fprintf(fp, " %-15s", sc->name);
2918 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f", 2570 printed += fprintf(fp, " %8" PRIu64 " %9.3f %9.3f %9.3f",
2919 n, avg * n, min, avg); 2571 n, syscall_stats_entry->msecs, min, avg);
2920 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct); 2572 printed += fprintf(fp, " %9.3f %9.2f%%\n", max, pct);
2921 } 2573 }
2922
2923 inode = intlist__next(inode);
2924 } 2574 }
2925 2575
2576 resort_rb__delete(syscall_stats);
2926 printed += fprintf(fp, "\n\n"); 2577 printed += fprintf(fp, "\n\n");
2927 2578
2928 return printed; 2579 return printed;
2929} 2580}
2930 2581
2931/* struct used to pass data to per-thread function */ 2582static 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{ 2583{
2940 struct summary_data *data = priv; 2584 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); 2585 struct thread_trace *ttrace = thread__priv(thread);
2945 double ratio; 2586 double ratio;
2946 2587
@@ -2956,25 +2597,45 @@ static int trace__fprintf_one_thread(struct thread *thread, void *priv)
2956 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj); 2597 printed += fprintf(fp, ", %lu majfaults", ttrace->pfmaj);
2957 if (ttrace->pfmin) 2598 if (ttrace->pfmin)
2958 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin); 2599 printed += fprintf(fp, ", %lu minfaults", ttrace->pfmin);
2959 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms); 2600 if (trace->sched)
2601 printed += fprintf(fp, ", %.3f msec\n", ttrace->runtime_ms);
2602 else if (fputc('\n', fp) != EOF)
2603 ++printed;
2604
2960 printed += thread__dump_stats(ttrace, trace, fp); 2605 printed += thread__dump_stats(ttrace, trace, fp);
2961 2606
2962 data->printed += printed; 2607 return printed;
2608}
2963 2609
2964 return 0; 2610static unsigned long thread__nr_events(struct thread_trace *ttrace)
2611{
2612 return ttrace ? ttrace->nr_events : 0;
2613}
2614
2615DEFINE_RESORT_RB(threads, (thread__nr_events(a->thread->priv) < thread__nr_events(b->thread->priv)),
2616 struct thread *thread;
2617)
2618{
2619 entry->thread = rb_entry(nd, struct thread, rb_node);
2965} 2620}
2966 2621
2967static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp) 2622static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2968{ 2623{
2969 struct summary_data data = { 2624 DECLARE_RESORT_RB_MACHINE_THREADS(threads, trace->host);
2970 .fp = fp, 2625 size_t printed = trace__fprintf_threads_header(fp);
2971 .trace = trace 2626 struct rb_node *nd;
2972 };
2973 data.printed = trace__fprintf_threads_header(fp);
2974 2627
2975 machine__for_each_thread(trace->host, trace__fprintf_one_thread, &data); 2628 if (threads == NULL) {
2629 fprintf(fp, "%s", "Error sorting output by nr_events!\n");
2630 return 0;
2631 }
2976 2632
2977 return data.printed; 2633 resort_rb__for_each_entry(nd, threads)
2634 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2635
2636 resort_rb__delete(threads);
2637
2638 return printed;
2978} 2639}
2979 2640
2980static int trace__set_duration(const struct option *opt, const char *str, 2641static int trace__set_duration(const struct option *opt, const char *str,
@@ -3056,7 +2717,7 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
3056{ 2717{
3057 struct perf_evsel *evsel; 2718 struct perf_evsel *evsel;
3058 2719
3059 evlist__for_each(evlist, evsel) 2720 evlist__for_each_entry(evlist, evsel)
3060 evsel->handler = handler; 2721 evsel->handler = handler;
3061} 2722}
3062 2723
@@ -3070,10 +2731,6 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3070 NULL 2731 NULL
3071 }; 2732 };
3072 struct trace trace = { 2733 struct trace trace = {
3073 .audit = {
3074 .machine = audit_detect_machine(),
3075 .open_id = audit_name_to_syscall("open", trace.audit.machine),
3076 },
3077 .syscalls = { 2734 .syscalls = {
3078 . max = -1, 2735 . max = -1,
3079 }, 2736 },
@@ -3091,6 +2748,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3091 .output = stderr, 2748 .output = stderr,
3092 .show_comm = true, 2749 .show_comm = true,
3093 .trace_syscalls = true, 2750 .trace_syscalls = true,
2751 .kernel_syscallchains = false,
2752 .max_stack = UINT_MAX,
3094 }; 2753 };
3095 const char *output_name = NULL; 2754 const char *output_name = NULL;
3096 const char *ev_qualifier_str = NULL; 2755 const char *ev_qualifier_str = NULL;
@@ -3136,10 +2795,24 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3136 "Trace pagefaults", parse_pagefaults, "maj"), 2795 "Trace pagefaults", parse_pagefaults, "maj"),
3137 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"), 2796 OPT_BOOLEAN(0, "syscalls", &trace.trace_syscalls, "Trace syscalls"),
3138 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"), 2797 OPT_BOOLEAN('f', "force", &trace.force, "don't complain, do it"),
2798 OPT_CALLBACK(0, "call-graph", &trace.opts,
2799 "record_mode[,record_size]", record_callchain_help,
2800 &record_parse_callchain_opt),
2801 OPT_BOOLEAN(0, "kernel-syscall-graph", &trace.kernel_syscallchains,
2802 "Show the kernel callchains on the syscall exit path"),
2803 OPT_UINTEGER(0, "min-stack", &trace.min_stack,
2804 "Set the minimum stack depth when parsing the callchain, "
2805 "anything below the specified depth will be ignored."),
2806 OPT_UINTEGER(0, "max-stack", &trace.max_stack,
2807 "Set the maximum stack depth when parsing the callchain, "
2808 "anything beyond the specified depth will be ignored. "
2809 "Default: kernel.perf_event_max_stack or " __stringify(PERF_MAX_STACK_DEPTH)),
3139 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout, 2810 OPT_UINTEGER(0, "proc-map-timeout", &trace.opts.proc_map_timeout,
3140 "per thread proc mmap processing timeout in ms"), 2811 "per thread proc mmap processing timeout in ms"),
3141 OPT_END() 2812 OPT_END()
3142 }; 2813 };
2814 bool __maybe_unused max_stack_user_set = true;
2815 bool mmap_pages_user_set = true;
3143 const char * const trace_subcommands[] = { "record", NULL }; 2816 const char * const trace_subcommands[] = { "record", NULL };
3144 int err; 2817 int err;
3145 char bf[BUFSIZ]; 2818 char bf[BUFSIZ];
@@ -3148,8 +2821,9 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3148 signal(SIGFPE, sighandler_dump_stack); 2821 signal(SIGFPE, sighandler_dump_stack);
3149 2822
3150 trace.evlist = perf_evlist__new(); 2823 trace.evlist = perf_evlist__new();
2824 trace.sctbl = syscalltbl__new();
3151 2825
3152 if (trace.evlist == NULL) { 2826 if (trace.evlist == NULL || trace.sctbl == NULL) {
3153 pr_err("Not enough memory to run!\n"); 2827 pr_err("Not enough memory to run!\n");
3154 err = -ENOMEM; 2828 err = -ENOMEM;
3155 goto out; 2829 goto out;
@@ -3158,11 +2832,40 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3158 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands, 2832 argc = parse_options_subcommand(argc, argv, trace_options, trace_subcommands,
3159 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION); 2833 trace_usage, PARSE_OPT_STOP_AT_NON_OPTION);
3160 2834
2835 err = bpf__setup_stdout(trace.evlist);
2836 if (err) {
2837 bpf__strerror_setup_stdout(trace.evlist, err, bf, sizeof(bf));
2838 pr_err("ERROR: Setup BPF stdout failed: %s\n", bf);
2839 goto out;
2840 }
2841
2842 err = -1;
2843
3161 if (trace.trace_pgfaults) { 2844 if (trace.trace_pgfaults) {
3162 trace.opts.sample_address = true; 2845 trace.opts.sample_address = true;
3163 trace.opts.sample_time = true; 2846 trace.opts.sample_time = true;
3164 } 2847 }
3165 2848
2849 if (trace.opts.mmap_pages == UINT_MAX)
2850 mmap_pages_user_set = false;
2851
2852 if (trace.max_stack == UINT_MAX) {
2853 trace.max_stack = input_name ? PERF_MAX_STACK_DEPTH : sysctl_perf_event_max_stack;
2854 max_stack_user_set = false;
2855 }
2856
2857#ifdef HAVE_DWARF_UNWIND_SUPPORT
2858 if ((trace.min_stack || max_stack_user_set) && !callchain_param.enabled && trace.trace_syscalls)
2859 record_opts__parse_callchain(&trace.opts, &callchain_param, "dwarf", false);
2860#endif
2861
2862 if (callchain_param.enabled) {
2863 if (!mmap_pages_user_set && geteuid() == 0)
2864 trace.opts.mmap_pages = perf_event_mlock_kb_in_pages() * 4;
2865
2866 symbol_conf.use_callchain = true;
2867 }
2868
3166 if (trace.evlist->nr_entries > 0) 2869 if (trace.evlist->nr_entries > 0)
3167 evlist__set_evsel_handler(trace.evlist, trace__event_handler); 2870 evlist__set_evsel_handler(trace.evlist, trace__event_handler);
3168 2871
@@ -3179,6 +2882,11 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3179 return -1; 2882 return -1;
3180 } 2883 }
3181 2884
2885 if (!trace.trace_syscalls && ev_qualifier_str) {
2886 pr_err("The -e option can't be used with --no-syscalls.\n");
2887 goto out;
2888 }
2889
3182 if (output_name != NULL) { 2890 if (output_name != NULL) {
3183 err = trace__open_output(&trace, output_name); 2891 err = trace__open_output(&trace, output_name);
3184 if (err < 0) { 2892 if (err < 0) {
@@ -3187,6 +2895,8 @@ int cmd_trace(int argc, const char **argv, const char *prefix __maybe_unused)
3187 } 2895 }
3188 } 2896 }
3189 2897
2898 trace.open_id = syscalltbl__id(trace.sctbl, "open");
2899
3190 if (ev_qualifier_str != NULL) { 2900 if (ev_qualifier_str != NULL) {
3191 const char *s = ev_qualifier_str; 2901 const char *s = ev_qualifier_str;
3192 struct strlist_config slist_config = { 2902 struct strlist_config slist_config = {
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index 6461e02ab940..55daefff0d54 100644
--- a/tools/perf/jvmti/jvmti_agent.c
+++ b/tools/perf/jvmti/jvmti_agent.c
@@ -59,7 +59,6 @@ static int get_e_machine(struct jitheader *hdr)
59 ssize_t sret; 59 ssize_t sret;
60 char id[16]; 60 char id[16];
61 int fd, ret = -1; 61 int fd, ret = -1;
62 int m = -1;
63 struct { 62 struct {
64 uint16_t e_type; 63 uint16_t e_type;
65 uint16_t e_machine; 64 uint16_t e_machine;
@@ -81,17 +80,29 @@ static int get_e_machine(struct jitheader *hdr)
81 if (sret != sizeof(info)) 80 if (sret != sizeof(info))
82 goto error; 81 goto error;
83 82
84 m = info.e_machine; 83 hdr->elf_mach = info.e_machine;
85 if (m < 0)
86 m = 0; /* ELF EM_NONE */
87
88 hdr->elf_mach = m;
89 ret = 0; 84 ret = 0;
90error: 85error:
91 close(fd); 86 close(fd);
92 return ret; 87 return ret;
93} 88}
94 89
90static int use_arch_timestamp;
91
92static inline uint64_t
93get_arch_timestamp(void)
94{
95#if defined(__i386__) || defined(__x86_64__)
96 unsigned int low, high;
97
98 asm volatile("rdtsc" : "=a" (low), "=d" (high));
99
100 return low | ((uint64_t)high) << 32;
101#else
102 return 0;
103#endif
104}
105
95#define NSEC_PER_SEC 1000000000 106#define NSEC_PER_SEC 1000000000
96static int perf_clk_id = CLOCK_MONOTONIC; 107static int perf_clk_id = CLOCK_MONOTONIC;
97 108
@@ -107,6 +118,9 @@ perf_get_timestamp(void)
107 struct timespec ts; 118 struct timespec ts;
108 int ret; 119 int ret;
109 120
121 if (use_arch_timestamp)
122 return get_arch_timestamp();
123
110 ret = clock_gettime(perf_clk_id, &ts); 124 ret = clock_gettime(perf_clk_id, &ts);
111 if (ret) 125 if (ret)
112 return 0; 126 return 0;
@@ -203,6 +217,17 @@ perf_close_marker_file(void)
203 munmap(marker_addr, pgsz); 217 munmap(marker_addr, pgsz);
204} 218}
205 219
220static void
221init_arch_timestamp(void)
222{
223 char *str = getenv("JITDUMP_USE_ARCH_TIMESTAMP");
224
225 if (!str || !*str || !strcmp(str, "0"))
226 return;
227
228 use_arch_timestamp = 1;
229}
230
206void *jvmti_open(void) 231void *jvmti_open(void)
207{ 232{
208 int pad_cnt; 233 int pad_cnt;
@@ -211,11 +236,17 @@ void *jvmti_open(void)
211 int fd; 236 int fd;
212 FILE *fp; 237 FILE *fp;
213 238
239 init_arch_timestamp();
240
214 /* 241 /*
215 * check if clockid is supported 242 * check if clockid is supported
216 */ 243 */
217 if (!perf_get_timestamp()) 244 if (!perf_get_timestamp()) {
218 warnx("jvmti: kernel does not support %d clock id", perf_clk_id); 245 if (use_arch_timestamp)
246 warnx("jvmti: arch timestamp not supported");
247 else
248 warnx("jvmti: kernel does not support %d clock id", perf_clk_id);
249 }
219 250
220 memset(&header, 0, sizeof(header)); 251 memset(&header, 0, sizeof(header));
221 252
@@ -263,6 +294,9 @@ void *jvmti_open(void)
263 294
264 header.timestamp = perf_get_timestamp(); 295 header.timestamp = perf_get_timestamp();
265 296
297 if (use_arch_timestamp)
298 header.flags |= JITDUMP_FLAGS_ARCH_TIMESTAMP;
299
266 if (!fwrite(&header, sizeof(header), 1, fp)) { 300 if (!fwrite(&header, sizeof(header), 1, fp)) {
267 warn("jvmti: cannot write dumpfile header"); 301 warn("jvmti: cannot write dumpfile header");
268 goto error; 302 goto error;
@@ -452,10 +486,11 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
452 if (sret != 1) 486 if (sret != 1)
453 goto error; 487 goto error;
454 } 488 }
455 if (padding_count) 489 if (padding_count) {
456 sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp); 490 sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp);
457 if (sret != 1) 491 if (sret != 1)
458 goto error; 492 goto error;
493 }
459 494
460 funlockfile(fp); 495 funlockfile(fp);
461 return 0; 496 return 0;
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 83a25cef82fd..7ed72a475c57 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -5,35 +5,18 @@
5#include <sys/types.h> 5#include <sys/types.h>
6#include <sys/syscall.h> 6#include <sys/syscall.h>
7#include <linux/types.h> 7#include <linux/types.h>
8#include <linux/compiler.h>
8#include <linux/perf_event.h> 9#include <linux/perf_event.h>
9#include <asm/barrier.h> 10#include <asm/barrier.h>
10 11
11#if defined(__i386__) 12#if defined(__i386__)
12#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 13#define cpu_relax() asm volatile("rep; nop" ::: "memory");
13#define CPUINFO_PROC {"model name"} 14#define CPUINFO_PROC {"model name"}
14#ifndef __NR_perf_event_open
15# define __NR_perf_event_open 336
16#endif
17#ifndef __NR_futex
18# define __NR_futex 240
19#endif
20#ifndef __NR_gettid
21# define __NR_gettid 224
22#endif
23#endif 15#endif
24 16
25#if defined(__x86_64__) 17#if defined(__x86_64__)
26#define cpu_relax() asm volatile("rep; nop" ::: "memory"); 18#define cpu_relax() asm volatile("rep; nop" ::: "memory");
27#define CPUINFO_PROC {"model name"} 19#define CPUINFO_PROC {"model name"}
28#ifndef __NR_perf_event_open
29# define __NR_perf_event_open 298
30#endif
31#ifndef __NR_futex
32# define __NR_futex 202
33#endif
34#ifndef __NR_gettid
35# define __NR_gettid 186
36#endif
37#endif 20#endif
38 21
39#ifdef __powerpc__ 22#ifdef __powerpc__
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index aaee0a782747..64c06961bfe4 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -10,13 +10,14 @@
10 10
11#include "util/env.h" 11#include "util/env.h"
12#include <subcmd/exec-cmd.h> 12#include <subcmd/exec-cmd.h>
13#include "util/cache.h" 13#include "util/config.h"
14#include "util/quote.h" 14#include "util/quote.h"
15#include <subcmd/run-command.h> 15#include <subcmd/run-command.h>
16#include "util/parse-events.h" 16#include "util/parse-events.h"
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>
@@ -138,8 +139,6 @@ struct option options[] = {
138 OPT_ARGUMENT("html-path", "html-path"), 139 OPT_ARGUMENT("html-path", "html-path"),
139 OPT_ARGUMENT("paginate", "paginate"), 140 OPT_ARGUMENT("paginate", "paginate"),
140 OPT_ARGUMENT("no-pager", "no-pager"), 141 OPT_ARGUMENT("no-pager", "no-pager"),
141 OPT_ARGUMENT("perf-dir", "perf-dir"),
142 OPT_ARGUMENT("work-tree", "work-tree"),
143 OPT_ARGUMENT("debugfs-dir", "debugfs-dir"), 142 OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
144 OPT_ARGUMENT("buildid-dir", "buildid-dir"), 143 OPT_ARGUMENT("buildid-dir", "buildid-dir"),
145 OPT_ARGUMENT("list-cmds", "list-cmds"), 144 OPT_ARGUMENT("list-cmds", "list-cmds"),
@@ -199,35 +198,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
199 use_pager = 0; 198 use_pager = 0;
200 if (envchanged) 199 if (envchanged)
201 *envchanged = 1; 200 *envchanged = 1;
202 } else if (!strcmp(cmd, "--perf-dir")) {
203 if (*argc < 2) {
204 fprintf(stderr, "No directory given for --perf-dir.\n");
205 usage(perf_usage_string);
206 }
207 setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1);
208 if (envchanged)
209 *envchanged = 1;
210 (*argv)++;
211 (*argc)--;
212 handled++;
213 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
214 setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
215 if (envchanged)
216 *envchanged = 1;
217 } else if (!strcmp(cmd, "--work-tree")) {
218 if (*argc < 2) {
219 fprintf(stderr, "No directory given for --work-tree.\n");
220 usage(perf_usage_string);
221 }
222 setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
223 if (envchanged)
224 *envchanged = 1;
225 (*argv)++;
226 (*argc)--;
227 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
228 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
229 if (envchanged)
230 *envchanged = 1;
231 } else if (!strcmp(cmd, "--debugfs-dir")) { 201 } else if (!strcmp(cmd, "--debugfs-dir")) {
232 if (*argc < 2) { 202 if (*argc < 2) {
233 fprintf(stderr, "No directory given for --debugfs-dir.\n"); 203 fprintf(stderr, "No directory given for --debugfs-dir.\n");
@@ -308,9 +278,11 @@ static int handle_alias(int *argcp, const char ***argv)
308 if (*argcp > 1) { 278 if (*argcp > 1) {
309 struct strbuf buf; 279 struct strbuf buf;
310 280
311 strbuf_init(&buf, PATH_MAX); 281 if (strbuf_init(&buf, PATH_MAX) < 0 ||
312 strbuf_addstr(&buf, alias_string); 282 strbuf_addstr(&buf, alias_string) < 0 ||
313 sq_quote_argv(&buf, (*argv) + 1, PATH_MAX); 283 sq_quote_argv(&buf, (*argv) + 1,
284 PATH_MAX) < 0)
285 die("Failed to allocate memory.");
314 free(alias_string); 286 free(alias_string);
315 alias_string = buf.buf; 287 alias_string = buf.buf;
316 } 288 }
@@ -360,11 +332,6 @@ const char perf_version_string[] = PERF_VERSION;
360 332
361#define RUN_SETUP (1<<0) 333#define RUN_SETUP (1<<0)
362#define USE_PAGER (1<<1) 334#define USE_PAGER (1<<1)
363/*
364 * require working tree to be present -- anything uses this needs
365 * RUN_SETUP for reading from the configuration file.
366 */
367#define NEED_WORK_TREE (1<<2)
368 335
369static int run_builtin(struct cmd_struct *p, int argc, const char **argv) 336static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
370{ 337{
@@ -388,6 +355,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
388 355
389 perf_env__set_cmdline(&perf_env, argc, argv); 356 perf_env__set_cmdline(&perf_env, argc, argv);
390 status = p->fn(argc, argv, prefix); 357 status = p->fn(argc, argv, prefix);
358 perf_config__exit();
391 exit_browser(status); 359 exit_browser(status);
392 perf_env__exit(&perf_env); 360 perf_env__exit(&perf_env);
393 bpf__clear(); 361 bpf__clear();
@@ -406,7 +374,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
406 /* Check for ENOSPC and EIO errors.. */ 374 /* Check for ENOSPC and EIO errors.. */
407 if (fflush(stdout)) { 375 if (fflush(stdout)) {
408 fprintf(stderr, "write failure on standard output: %s", 376 fprintf(stderr, "write failure on standard output: %s",
409 strerror_r(errno, sbuf, sizeof(sbuf))); 377 str_error_r(errno, sbuf, sizeof(sbuf)));
410 goto out; 378 goto out;
411 } 379 }
412 if (ferror(stdout)) { 380 if (ferror(stdout)) {
@@ -415,7 +383,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
415 } 383 }
416 if (fclose(stdout)) { 384 if (fclose(stdout)) {
417 fprintf(stderr, "close failed on standard output: %s", 385 fprintf(stderr, "close failed on standard output: %s",
418 strerror_r(errno, sbuf, sizeof(sbuf))); 386 str_error_r(errno, sbuf, sizeof(sbuf)));
419 goto out; 387 goto out;
420 } 388 }
421 status = 0; 389 status = 0;
@@ -529,10 +497,21 @@ void pthread__unblock_sigwinch(void)
529 pthread_sigmask(SIG_UNBLOCK, &set, NULL); 497 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
530} 498}
531 499
500#ifdef _SC_LEVEL1_DCACHE_LINESIZE
501#define cache_line_size(cacheline_sizep) *cacheline_sizep = sysconf(_SC_LEVEL1_DCACHE_LINESIZE)
502#else
503static void cache_line_size(int *cacheline_sizep)
504{
505 if (sysfs__read_int("devices/system/cpu/cpu0/cache/index0/coherency_line_size", cacheline_sizep))
506 pr_debug("cannot determine cache line size");
507}
508#endif
509
532int main(int argc, const char **argv) 510int main(int argc, const char **argv)
533{ 511{
534 const char *cmd; 512 const char *cmd;
535 char sbuf[STRERR_BUFSIZE]; 513 char sbuf[STRERR_BUFSIZE];
514 int value;
536 515
537 /* libsubcmd init */ 516 /* libsubcmd init */
538 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT); 517 exec_cmd_init("perf", PREFIX, PERF_EXEC_PATH, EXEC_PATH_ENVIRONMENT);
@@ -540,7 +519,13 @@ int main(int argc, const char **argv)
540 519
541 /* The page_size is placed in util object. */ 520 /* The page_size is placed in util object. */
542 page_size = sysconf(_SC_PAGE_SIZE); 521 page_size = sysconf(_SC_PAGE_SIZE);
543 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); 522 cache_line_size(&cacheline_size);
523
524 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
525 sysctl_perf_event_max_stack = value;
526
527 if (sysctl__read_int("kernel/perf_event_max_contexts_per_stack", &value) == 0)
528 sysctl_perf_event_max_contexts_per_stack = value;
544 529
545 cmd = extract_argv0_path(argv[0]); 530 cmd = extract_argv0_path(argv[0]);
546 if (!cmd) 531 if (!cmd)
@@ -548,7 +533,9 @@ int main(int argc, const char **argv)
548 533
549 srandom(time(NULL)); 534 srandom(time(NULL));
550 535
536 perf_config__init();
551 perf_config(perf_default_config, NULL); 537 perf_config(perf_default_config, NULL);
538 set_buildid_dir(NULL);
552 539
553 /* get debugfs/tracefs mount point from /proc/mounts */ 540 /* get debugfs/tracefs mount point from /proc/mounts */
554 tracing_path_mount(); 541 tracing_path_mount();
@@ -572,7 +559,6 @@ int main(int argc, const char **argv)
572 } 559 }
573 if (!prefixcmp(cmd, "trace")) { 560 if (!prefixcmp(cmd, "trace")) {
574#ifdef HAVE_LIBAUDIT_SUPPORT 561#ifdef HAVE_LIBAUDIT_SUPPORT
575 set_buildid_dir(NULL);
576 setup_path(); 562 setup_path();
577 argv[0] = "trace"; 563 argv[0] = "trace";
578 return cmd_trace(argc, argv, NULL); 564 return cmd_trace(argc, argv, NULL);
@@ -587,7 +573,6 @@ int main(int argc, const char **argv)
587 argc--; 573 argc--;
588 handle_options(&argv, &argc, NULL); 574 handle_options(&argv, &argc, NULL);
589 commit_pager_choice(); 575 commit_pager_choice();
590 set_buildid_dir(NULL);
591 576
592 if (argc > 0) { 577 if (argc > 0) {
593 if (!prefixcmp(argv[0], "--")) 578 if (!prefixcmp(argv[0], "--"))
@@ -640,7 +625,7 @@ int main(int argc, const char **argv)
640 } 625 }
641 626
642 fprintf(stderr, "Failed to run command '%s': %s\n", 627 fprintf(stderr, "Failed to run command '%s': %s\n",
643 cmd, strerror_r(errno, sbuf, sizeof(sbuf))); 628 cmd, str_error_r(errno, sbuf, sizeof(sbuf)));
644out: 629out:
645 return 1; 630 return 1;
646} 631}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index 5381a01c0610..cb0f1356ff81 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -52,7 +52,7 @@ struct record_opts {
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; 55 bool sample_cpu;
56 bool period; 56 bool period;
57 bool running_time; 57 bool running_time;
58 bool full_auxtrace; 58 bool full_auxtrace;
@@ -60,6 +60,8 @@ struct record_opts {
60 bool record_switch_events; 60 bool record_switch_events;
61 bool all_kernel; 61 bool all_kernel;
62 bool all_user; 62 bool all_user;
63 bool tail_synthesize;
64 bool overwrite;
63 unsigned int freq; 65 unsigned int freq;
64 unsigned int mmap_pages; 66 unsigned int mmap_pages;
65 unsigned int auxtrace_mmap_pages; 67 unsigned int auxtrace_mmap_pages;
diff --git a/tools/perf/python/tracepoint.py b/tools/perf/python/tracepoint.py
new file mode 100755
index 000000000000..eb4dbed57de7
--- /dev/null
+++ b/tools/perf/python/tracepoint.py
@@ -0,0 +1,47 @@
1#! /usr/bin/python
2# -*- python -*-
3# -*- coding: utf-8 -*-
4
5import perf
6
7class tracepoint(perf.evsel):
8 def __init__(self, sys, name):
9 config = perf.tracepoint(sys, name)
10 perf.evsel.__init__(self,
11 type = perf.TYPE_TRACEPOINT,
12 config = config,
13 freq = 0, sample_period = 1, wakeup_events = 1,
14 sample_type = perf.SAMPLE_PERIOD | perf.SAMPLE_TID | perf.SAMPLE_CPU | perf.SAMPLE_RAW | perf.SAMPLE_TIME)
15
16def main():
17 tp = tracepoint("sched", "sched_switch")
18 cpus = perf.cpu_map()
19 threads = perf.thread_map(-1)
20
21 evlist = perf.evlist(cpus, threads)
22 evlist.add(tp)
23 evlist.open()
24 evlist.mmap()
25
26 while True:
27 evlist.poll(timeout = -1)
28 for cpu in cpus:
29 event = evlist.read_on_cpu(cpu)
30 if not event:
31 continue
32
33 if not isinstance(event, perf.sample_event):
34 continue
35
36 print "time %u prev_comm=%s prev_pid=%d prev_prio=%d prev_state=0x%x ==> next_comm=%s next_pid=%d next_prio=%d" % (
37 event.sample_time,
38 event.prev_comm,
39 event.prev_pid,
40 event.prev_prio,
41 event.prev_state,
42 event.next_comm,
43 event.next_pid,
44 event.next_prio)
45
46if __name__ == '__main__':
47 main()
diff --git a/tools/perf/scripts/perl/Perf-Trace-Util/Build b/tools/perf/scripts/perl/Perf-Trace-Util/Build
index 928e110179cb..34faecf774ae 100644
--- a/tools/perf/scripts/perl/Perf-Trace-Util/Build
+++ b/tools/perf/scripts/perl/Perf-Trace-Util/Build
@@ -1,3 +1,5 @@
1libperf-y += Context.o 1libperf-y += Context.o
2 2
3CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs -Wno-undef -Wno-switch-default 3CFLAGS_Context.o += $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes
4CFLAGS_Context.o += -Wno-unused-parameter -Wno-nested-externs -Wno-undef
5CFLAGS_Context.o += -Wno-switch-default -Wno-shadow
diff --git a/tools/perf/scripts/python/bin/stackcollapse-record b/tools/perf/scripts/python/bin/stackcollapse-record
new file mode 100755
index 000000000000..9d8f9f0f3a17
--- /dev/null
+++ b/tools/perf/scripts/python/bin/stackcollapse-record
@@ -0,0 +1,8 @@
1#!/bin/sh
2
3#
4# stackcollapse.py can cover all type of perf samples including
5# the tracepoints, so no special record requirements, just record what
6# you want to analyze.
7#
8perf record "$@"
diff --git a/tools/perf/scripts/python/bin/stackcollapse-report b/tools/perf/scripts/python/bin/stackcollapse-report
new file mode 100755
index 000000000000..356b9656393d
--- /dev/null
+++ b/tools/perf/scripts/python/bin/stackcollapse-report
@@ -0,0 +1,3 @@
1#!/bin/sh
2# description: produce callgraphs in short form for scripting use
3perf script -s "$PERF_EXEC_PATH"/scripts/python/stackcollapse.py -- "$@"
diff --git a/tools/perf/scripts/python/export-to-postgresql.py b/tools/perf/scripts/python/export-to-postgresql.py
index 1b02cdc0cab6..7656ff8aa066 100644
--- a/tools/perf/scripts/python/export-to-postgresql.py
+++ b/tools/perf/scripts/python/export-to-postgresql.py
@@ -34,10 +34,9 @@ import datetime
34# 34#
35# ubuntu: 35# ubuntu:
36# 36#
37# $ sudo apt-get install postgresql 37# $ sudo apt-get install postgresql python-pyside.qtsql libqt4-sql-psql
38# $ sudo su - postgres 38# $ 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'] + \
224 223
225perf_db_export_mode = True 224perf_db_export_mode = True
226perf_db_export_calls = False 225perf_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"):
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 = True 253 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:
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 '
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:
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")
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():
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 = 0 569unhandled_count = 0
@@ -571,8 +579,9 @@ def trace_end():
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():
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():
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():
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):
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):
diff --git a/tools/perf/scripts/python/netdev-times.py b/tools/perf/scripts/python/netdev-times.py
index 4d21ef2d601d..4c6f09ac7d12 100644
--- a/tools/perf/scripts/python/netdev-times.py
+++ b/tools/perf/scripts/python/netdev-times.py
@@ -252,9 +252,10 @@ def irq__irq_handler_exit(name, context, cpu, sec, nsec, pid, comm, callchain, i
252 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret) 252 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, irq, ret)
253 all_event_list.append(event_info) 253 all_event_list.append(event_info)
254 254
255def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi, dev_name): 255def napi__napi_poll(name, context, cpu, sec, nsec, pid, comm, callchain, napi,
256 dev_name, work=None, budget=None):
256 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm, 257 event_info = (name, context, cpu, nsecs(sec, nsec), pid, comm,
257 napi, dev_name) 258 napi, dev_name, work, budget)
258 all_event_list.append(event_info) 259 all_event_list.append(event_info)
259 260
260def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr, 261def net__netif_receive_skb(name, context, cpu, sec, nsec, pid, comm, callchain, skbaddr,
@@ -354,11 +355,13 @@ def handle_irq_softirq_exit(event_info):
354 receive_hunk_list.append(rec_data) 355 receive_hunk_list.append(rec_data)
355 356
356def handle_napi_poll(event_info): 357def handle_napi_poll(event_info):
357 (name, context, cpu, time, pid, comm, napi, dev_name) = event_info 358 (name, context, cpu, time, pid, comm, napi, dev_name,
359 work, budget) = event_info
358 if cpu in net_rx_dic.keys(): 360 if cpu in net_rx_dic.keys():
359 event_list = net_rx_dic[cpu]['event_list'] 361 event_list = net_rx_dic[cpu]['event_list']
360 rec_data = {'event_name':'napi_poll', 362 rec_data = {'event_name':'napi_poll',
361 'dev':dev_name, 'event_t':time} 363 'dev':dev_name, 'event_t':time,
364 'work':work, 'budget':budget}
362 event_list.append(rec_data) 365 event_list.append(rec_data)
363 366
364def handle_netif_rx(event_info): 367def handle_netif_rx(event_info):
diff --git a/tools/perf/scripts/python/stackcollapse.py b/tools/perf/scripts/python/stackcollapse.py
new file mode 100755
index 000000000000..5a605f70ef32
--- /dev/null
+++ b/tools/perf/scripts/python/stackcollapse.py
@@ -0,0 +1,125 @@
1# stackcollapse.py - format perf samples with one line per distinct call stack
2#
3# This script's output has two space-separated fields. The first is a semicolon
4# separated stack including the program name (from the "comm" field) and the
5# function names from the call stack. The second is a count:
6#
7# swapper;start_kernel;rest_init;cpu_idle;default_idle;native_safe_halt 2
8#
9# The file is sorted according to the first field.
10#
11# Input may be created and processed using:
12#
13# perf record -a -g -F 99 sleep 60
14# perf script report stackcollapse > out.stacks-folded
15#
16# (perf script record stackcollapse works too).
17#
18# Written by Paolo Bonzini <pbonzini@redhat.com>
19# Based on Brendan Gregg's stackcollapse-perf.pl script.
20
21import os
22import sys
23from collections import defaultdict
24from optparse import OptionParser, make_option
25
26sys.path.append(os.environ['PERF_EXEC_PATH'] + \
27 '/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
28
29from perf_trace_context import *
30from Core import *
31from EventClass import *
32
33# command line parsing
34
35option_list = [
36 # formatting options for the bottom entry of the stack
37 make_option("--include-tid", dest="include_tid",
38 action="store_true", default=False,
39 help="include thread id in stack"),
40 make_option("--include-pid", dest="include_pid",
41 action="store_true", default=False,
42 help="include process id in stack"),
43 make_option("--no-comm", dest="include_comm",
44 action="store_false", default=True,
45 help="do not separate stacks according to comm"),
46 make_option("--tidy-java", dest="tidy_java",
47 action="store_true", default=False,
48 help="beautify Java signatures"),
49 make_option("--kernel", dest="annotate_kernel",
50 action="store_true", default=False,
51 help="annotate kernel functions with _[k]")
52]
53
54parser = OptionParser(option_list=option_list)
55(opts, args) = parser.parse_args()
56
57if len(args) != 0:
58 parser.error("unexpected command line argument")
59if opts.include_tid and not opts.include_comm:
60 parser.error("requesting tid but not comm is invalid")
61if opts.include_pid and not opts.include_comm:
62 parser.error("requesting pid but not comm is invalid")
63
64# event handlers
65
66lines = defaultdict(lambda: 0)
67
68def process_event(param_dict):
69 def tidy_function_name(sym, dso):
70 if sym is None:
71 sym = '[unknown]'
72
73 sym = sym.replace(';', ':')
74 if opts.tidy_java:
75 # the original stackcollapse-perf.pl script gives the
76 # example of converting this:
77 # Lorg/mozilla/javascript/MemberBox;.<init>(Ljava/lang/reflect/Method;)V
78 # to this:
79 # org/mozilla/javascript/MemberBox:.init
80 sym = sym.replace('<', '')
81 sym = sym.replace('>', '')
82 if sym[0] == 'L' and sym.find('/'):
83 sym = sym[1:]
84 try:
85 sym = sym[:sym.index('(')]
86 except ValueError:
87 pass
88
89 if opts.annotate_kernel and dso == '[kernel.kallsyms]':
90 return sym + '_[k]'
91 else:
92 return sym
93
94 stack = list()
95 if 'callchain' in param_dict:
96 for entry in param_dict['callchain']:
97 entry.setdefault('sym', dict())
98 entry['sym'].setdefault('name', None)
99 entry.setdefault('dso', None)
100 stack.append(tidy_function_name(entry['sym']['name'],
101 entry['dso']))
102 else:
103 param_dict.setdefault('symbol', None)
104 param_dict.setdefault('dso', None)
105 stack.append(tidy_function_name(param_dict['symbol'],
106 param_dict['dso']))
107
108 if opts.include_comm:
109 comm = param_dict["comm"].replace(' ', '_')
110 sep = "-"
111 if opts.include_pid:
112 comm = comm + sep + str(param_dict['sample']['pid'])
113 sep = "/"
114 if opts.include_tid:
115 comm = comm + sep + str(param_dict['sample']['tid'])
116 stack.append(comm)
117
118 stack_string = ';'.join(reversed(stack))
119 lines[stack_string] = lines[stack_string] + 1
120
121def trace_end():
122 list = lines.keys()
123 list.sort()
124 for stack in list:
125 print "%s %d" % (stack, lines[stack])
diff --git a/tools/perf/tests/Build b/tools/perf/tests/Build
index 1ba628ed049a..dc51bc570e51 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -37,6 +37,11 @@ perf-y += topology.o
37perf-y += cpumap.o 37perf-y += cpumap.o
38perf-y += stat.o 38perf-y += stat.o
39perf-y += event_update.o 39perf-y += event_update.o
40perf-y += event-times.o
41perf-y += backward-ring-buffer.o
42perf-y += sdt.o
43perf-y += is_printable_array.o
44perf-y += bitmap.o
40 45
41$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build 46$(OUTPUT)tests/llvm-src-base.c: tests/bpf-script-example.c tests/Build
42 $(call rule_mkdir) 47 $(call rule_mkdir)
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
new file mode 100644
index 000000000000..615780cbfe1d
--- /dev/null
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -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_mmap__read_catchup(&evlist->backward_mmap[i]);
35 while ((event = perf_mmap__read_backward(&evlist->backward_mmap[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 str_error_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 /*
112 * Set backward bit, ring buffer should be writing from end. Record
113 * it in aux evlist
114 */
115 err = parse_events(evlist, "syscalls:sys_enter_prctl/overwrite/", &parse_error);
116 if (err) {
117 pr_debug("Failed to parse tracepoint event, try use root\n");
118 ret = TEST_SKIP;
119 goto out_delete_evlist;
120 }
121
122 perf_evlist__config(evlist, &opts, NULL);
123
124 err = perf_evlist__open(evlist);
125 if (err < 0) {
126 pr_debug("perf_evlist__open: %s\n",
127 str_error_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}
diff --git a/tools/perf/tests/bitmap.c b/tools/perf/tests/bitmap.c
new file mode 100644
index 000000000000..9abe6c13090f
--- /dev/null
+++ b/tools/perf/tests/bitmap.c
@@ -0,0 +1,53 @@
1#include <linux/compiler.h>
2#include <linux/bitmap.h>
3#include "tests.h"
4#include "cpumap.h"
5#include "debug.h"
6
7#define NBITS 100
8
9static unsigned long *get_bitmap(const char *str, int nbits)
10{
11 struct cpu_map *map = cpu_map__new(str);
12 unsigned long *bm = NULL;
13 int i;
14
15 bm = bitmap_alloc(nbits);
16
17 if (map && bm) {
18 bitmap_zero(bm, nbits);
19
20 for (i = 0; i < map->nr; i++)
21 set_bit(map->map[i], bm);
22 }
23
24 if (map)
25 cpu_map__put(map);
26 return bm;
27}
28
29static int test_bitmap(const char *str)
30{
31 unsigned long *bm = get_bitmap(str, NBITS);
32 char buf[100];
33 int ret;
34
35 bitmap_scnprintf(bm, NBITS, buf, sizeof(buf));
36 pr_debug("bitmap: %s\n", buf);
37
38 ret = !strcmp(buf, str);
39 free(bm);
40 return ret;
41}
42
43int test__bitmap_print(int subtest __maybe_unused)
44{
45 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1"));
46 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,5"));
47 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3,5,7,9,11,13,15,17,19,21-40"));
48 TEST_ASSERT_VAL("failed to convert map", test_bitmap("2-5"));
49 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37"));
50 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1,3-6,8-10,24,35-37"));
51 TEST_ASSERT_VAL("failed to convert map", test_bitmap("1-10,12-20,22-30,32-40"));
52 return 0;
53}
diff --git a/tools/perf/tests/bpf-script-example.c b/tools/perf/tests/bpf-script-example.c
index 0ec9c2c03164..268e5f8e4aa2 100644
--- a/tools/perf/tests/bpf-script-example.c
+++ b/tools/perf/tests/bpf-script-example.c
@@ -31,8 +31,8 @@ struct bpf_map_def SEC("maps") flip_table = {
31 .max_entries = 1, 31 .max_entries = 1,
32}; 32};
33 33
34SEC("func=sys_epoll_pwait") 34SEC("func=SyS_epoll_wait")
35int bpf_func__sys_epoll_pwait(void *ctx) 35int bpf_func__SyS_epoll_wait(void *ctx)
36{ 36{
37 int ind =0; 37 int ind =0;
38 int *flag = bpf_map_lookup_elem(&flip_table, &ind); 38 int *flag = bpf_map_lookup_elem(&flip_table, &ind);
diff --git a/tools/perf/tests/bpf.c b/tools/perf/tests/bpf.c
index 199501c71e27..fc54064b9186 100644
--- a/tools/perf/tests/bpf.c
+++ b/tools/perf/tests/bpf.c
@@ -13,13 +13,13 @@
13 13
14#ifdef HAVE_LIBBPF_SUPPORT 14#ifdef HAVE_LIBBPF_SUPPORT
15 15
16static int epoll_pwait_loop(void) 16static int epoll_wait_loop(void)
17{ 17{
18 int i; 18 int i;
19 19
20 /* Should fail NR_ITERS times */ 20 /* Should fail NR_ITERS times */
21 for (i = 0; i < NR_ITERS; i++) 21 for (i = 0; i < NR_ITERS; i++)
22 epoll_pwait(-(i + 1), NULL, 0, 0, NULL); 22 epoll_wait(-(i + 1), NULL, 0, 0);
23 return 0; 23 return 0;
24} 24}
25 25
@@ -61,7 +61,7 @@ static struct {
61 "[basic_bpf_test]", 61 "[basic_bpf_test]",
62 "fix 'perf test LLVM' first", 62 "fix 'perf test LLVM' first",
63 "load bpf object failed", 63 "load bpf object failed",
64 &epoll_pwait_loop, 64 &epoll_wait_loop,
65 (NR_ITERS + 1) / 2, 65 (NR_ITERS + 1) / 2,
66 }, 66 },
67#ifdef HAVE_BPF_PROLOGUE 67#ifdef HAVE_BPF_PROLOGUE
@@ -138,19 +138,19 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
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) {
145 pr_debug("perf_evlist__open: %s\n", 145 pr_debug("perf_evlist__open: %s\n",
146 strerror_r(errno, sbuf, sizeof(sbuf))); 146 str_error_r(errno, sbuf, sizeof(sbuf)));
147 goto out_delete_evlist; 147 goto out_delete_evlist;
148 } 148 }
149 149
150 err = perf_evlist__mmap(evlist, opts.mmap_pages, false); 150 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
151 if (err < 0) { 151 if (err < 0) {
152 pr_debug("perf_evlist__mmap: %s\n", 152 pr_debug("perf_evlist__mmap: %s\n",
153 strerror_r(errno, sbuf, sizeof(sbuf))); 153 str_error_r(errno, sbuf, sizeof(sbuf)));
154 goto out_delete_evlist; 154 goto out_delete_evlist;
155 } 155 }
156 156
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index f2b1dcac45d3..778668a2a966 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -14,6 +14,8 @@
14#include <subcmd/parse-options.h> 14#include <subcmd/parse-options.h>
15#include "symbol.h" 15#include "symbol.h"
16 16
17static bool dont_fork;
18
17struct test __weak arch_tests[] = { 19struct test __weak arch_tests[] = {
18 { 20 {
19 .func = NULL, 21 .func = NULL,
@@ -204,6 +206,30 @@ static struct test generic_tests[] = {
204 .func = test__event_update, 206 .func = test__event_update,
205 }, 207 },
206 { 208 {
209 .desc = "Test events times",
210 .func = test__event_times,
211 },
212 {
213 .desc = "Test backward reading from ring buffer",
214 .func = test__backward_ring_buffer,
215 },
216 {
217 .desc = "Test cpu map print",
218 .func = test__cpu_map_print,
219 },
220 {
221 .desc = "Test SDT event probing",
222 .func = test__sdt_event,
223 },
224 {
225 .desc = "Test is_printable_array function",
226 .func = test__is_printable_array,
227 },
228 {
229 .desc = "Test bitmap print",
230 .func = test__bitmap_print,
231 },
232 {
207 .func = NULL, 233 .func = NULL,
208 }, 234 },
209}; 235};
@@ -239,44 +265,51 @@ static bool perf_test__matches(struct test *test, int curr, int argc, const char
239 265
240static int run_test(struct test *test, int subtest) 266static int run_test(struct test *test, int subtest)
241{ 267{
242 int status, err = -1, child = fork(); 268 int status, err = -1, child = dont_fork ? 0 : fork();
243 char sbuf[STRERR_BUFSIZE]; 269 char sbuf[STRERR_BUFSIZE];
244 270
245 if (child < 0) { 271 if (child < 0) {
246 pr_err("failed to fork test: %s\n", 272 pr_err("failed to fork test: %s\n",
247 strerror_r(errno, sbuf, sizeof(sbuf))); 273 str_error_r(errno, sbuf, sizeof(sbuf)));
248 return -1; 274 return -1;
249 } 275 }
250 276
251 if (!child) { 277 if (!child) {
252 pr_debug("test child forked, pid %d\n", getpid()); 278 if (!dont_fork) {
253 if (!verbose) { 279 pr_debug("test child forked, pid %d\n", getpid());
254 int nullfd = open("/dev/null", O_WRONLY); 280
255 if (nullfd >= 0) { 281 if (!verbose) {
256 close(STDERR_FILENO); 282 int nullfd = open("/dev/null", O_WRONLY);
257 close(STDOUT_FILENO); 283
258 284 if (nullfd >= 0) {
259 dup2(nullfd, STDOUT_FILENO); 285 close(STDERR_FILENO);
260 dup2(STDOUT_FILENO, STDERR_FILENO); 286 close(STDOUT_FILENO);
261 close(nullfd); 287
288 dup2(nullfd, STDOUT_FILENO);
289 dup2(STDOUT_FILENO, STDERR_FILENO);
290 close(nullfd);
291 }
292 } else {
293 signal(SIGSEGV, sighandler_dump_stack);
294 signal(SIGFPE, sighandler_dump_stack);
262 } 295 }
263 } else {
264 signal(SIGSEGV, sighandler_dump_stack);
265 signal(SIGFPE, sighandler_dump_stack);
266 } 296 }
267 297
268 err = test->func(subtest); 298 err = test->func(subtest);
269 exit(err); 299 if (!dont_fork)
300 exit(err);
270 } 301 }
271 302
272 wait(&status); 303 if (!dont_fork) {
304 wait(&status);
273 305
274 if (WIFEXITED(status)) { 306 if (WIFEXITED(status)) {
275 err = (signed char)WEXITSTATUS(status); 307 err = (signed char)WEXITSTATUS(status);
276 pr_debug("test child finished with %d\n", err); 308 pr_debug("test child finished with %d\n", err);
277 } else if (WIFSIGNALED(status)) { 309 } else if (WIFSIGNALED(status)) {
278 err = -1; 310 err = -1;
279 pr_debug("test child interrupted\n"); 311 pr_debug("test child interrupted\n");
312 }
280 } 313 }
281 314
282 return err; 315 return err;
@@ -417,6 +450,8 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
417 OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), 450 OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
418 OPT_INCR('v', "verbose", &verbose, 451 OPT_INCR('v', "verbose", &verbose,
419 "be more verbose (show symbol address, etc)"), 452 "be more verbose (show symbol address, etc)"),
453 OPT_BOOLEAN('F', "dont-fork", &dont_fork,
454 "Do not fork for testcase"),
420 OPT_END() 455 OPT_END()
421 }; 456 };
422 const char * const test_subcommands[] = { "list", NULL }; 457 const char * const test_subcommands[] = { "list", NULL };
diff --git a/tools/perf/tests/code-reading.c b/tools/perf/tests/code-reading.c
index abd3f0ec0c0b..2af156a8d4e5 100644
--- a/tools/perf/tests/code-reading.c
+++ b/tools/perf/tests/code-reading.c
@@ -33,44 +33,86 @@ static unsigned int hex(char c)
33 return c - 'A' + 10; 33 return c - 'A' + 10;
34} 34}
35 35
36static size_t read_objdump_line(const char *line, size_t line_len, void *buf, 36static size_t read_objdump_chunk(const char **line, unsigned char **buf,
37 size_t len) 37 size_t *buf_len)
38{ 38{
39 const char *p; 39 size_t bytes_read = 0;
40 size_t i, j = 0; 40 unsigned char *chunk_start = *buf;
41
42 /* Skip to a colon */
43 p = strchr(line, ':');
44 if (!p)
45 return 0;
46 i = p + 1 - line;
47 41
48 /* Read bytes */ 42 /* Read bytes */
49 while (j < len) { 43 while (*buf_len > 0) {
50 char c1, c2; 44 char c1, c2;
51 45
52 /* Skip spaces */
53 for (; i < line_len; i++) {
54 if (!isspace(line[i]))
55 break;
56 }
57 /* Get 2 hex digits */ 46 /* Get 2 hex digits */
58 if (i >= line_len || !isxdigit(line[i])) 47 c1 = *(*line)++;
48 if (!isxdigit(c1))
59 break; 49 break;
60 c1 = line[i++]; 50 c2 = *(*line)++;
61 if (i >= line_len || !isxdigit(line[i])) 51 if (!isxdigit(c2))
62 break; 52 break;
63 c2 = line[i++]; 53
64 /* Followed by a space */ 54 /* Store byte and advance buf */
65 if (i < line_len && line[i] && !isspace(line[i])) 55 **buf = (hex(c1) << 4) | hex(c2);
56 (*buf)++;
57 (*buf_len)--;
58 bytes_read++;
59
60 /* End of chunk? */
61 if (isspace(**line))
66 break; 62 break;
67 /* Store byte */
68 *(unsigned char *)buf = (hex(c1) << 4) | hex(c2);
69 buf += 1;
70 j++;
71 } 63 }
64
65 /*
66 * objdump will display raw insn as LE if code endian
67 * is LE and bytes_per_chunk > 1. In that case reverse
68 * the chunk we just read.
69 *
70 * see disassemble_bytes() at binutils/objdump.c for details
71 * how objdump chooses display endian)
72 */
73 if (bytes_read > 1 && !bigendian()) {
74 unsigned char *chunk_end = chunk_start + bytes_read - 1;
75 unsigned char tmp;
76
77 while (chunk_start < chunk_end) {
78 tmp = *chunk_start;
79 *chunk_start = *chunk_end;
80 *chunk_end = tmp;
81 chunk_start++;
82 chunk_end--;
83 }
84 }
85
86 return bytes_read;
87}
88
89static size_t read_objdump_line(const char *line, unsigned char *buf,
90 size_t buf_len)
91{
92 const char *p;
93 size_t ret, bytes_read = 0;
94
95 /* Skip to a colon */
96 p = strchr(line, ':');
97 if (!p)
98 return 0;
99 p++;
100
101 /* Skip initial spaces */
102 while (*p) {
103 if (!isspace(*p))
104 break;
105 p++;
106 }
107
108 do {
109 ret = read_objdump_chunk(&p, &buf, &buf_len);
110 bytes_read += ret;
111 p++;
112 } while (ret > 0);
113
72 /* return number of successfully read bytes */ 114 /* return number of successfully read bytes */
73 return j; 115 return bytes_read;
74} 116}
75 117
76static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr) 118static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
@@ -95,7 +137,7 @@ static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
95 } 137 }
96 138
97 /* read objdump data into temporary buffer */ 139 /* read objdump data into temporary buffer */
98 read_bytes = read_objdump_line(line, ret, tmp, sizeof(tmp)); 140 read_bytes = read_objdump_line(line, tmp, sizeof(tmp));
99 if (!read_bytes) 141 if (!read_bytes)
100 continue; 142 continue;
101 143
@@ -152,7 +194,7 @@ static int read_via_objdump(const char *filename, u64 addr, void *buf,
152 194
153 ret = read_objdump_output(f, buf, &len, addr); 195 ret = read_objdump_output(f, buf, &len, addr);
154 if (len) { 196 if (len) {
155 pr_debug("objdump read too few bytes\n"); 197 pr_debug("objdump read too few bytes: %zd\n", len);
156 if (!ret) 198 if (!ret)
157 ret = len; 199 ret = len;
158 } 200 }
@@ -532,7 +574,7 @@ static int do_test_code_reading(bool try_kcore)
532 goto out_put; 574 goto out_put;
533 } 575 }
534 576
535 perf_evlist__config(evlist, &opts); 577 perf_evlist__config(evlist, &opts, NULL);
536 578
537 evsel = perf_evlist__first(evlist); 579 evsel = perf_evlist__first(evlist);
538 580
diff --git a/tools/perf/tests/cpumap.c b/tools/perf/tests/cpumap.c
index 4cb6418a8ffc..f168a85992d0 100644
--- a/tools/perf/tests/cpumap.c
+++ b/tools/perf/tests/cpumap.c
@@ -1,5 +1,12 @@
1#include "tests.h" 1#include "tests.h"
2#include <stdio.h>
2#include "cpumap.h" 3#include "cpumap.h"
4#include "event.h"
5#include <string.h>
6#include <linux/bitops.h>
7#include "debug.h"
8
9struct machine;
3 10
4static int process_event_mask(struct perf_tool *tool __maybe_unused, 11static int process_event_mask(struct perf_tool *tool __maybe_unused,
5 union perf_event *event, 12 union perf_event *event,
@@ -86,3 +93,27 @@ int test__cpu_map_synthesize(int subtest __maybe_unused)
86 cpu_map__put(cpus); 93 cpu_map__put(cpus);
87 return 0; 94 return 0;
88} 95}
96
97static int cpu_map_print(const char *str)
98{
99 struct cpu_map *map = cpu_map__new(str);
100 char buf[100];
101
102 if (!map)
103 return -1;
104
105 cpu_map__snprint(map, buf, sizeof(buf));
106 return !strcmp(buf, str);
107}
108
109int test__cpu_map_print(int subtest __maybe_unused)
110{
111 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1"));
112 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,5"));
113 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,3,5,7,9,11,13,15,17,19,21-40"));
114 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("2-5"));
115 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,3-6,8-10,24,35-37"));
116 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1,3-6,8-10,24,35-37"));
117 TEST_ASSERT_VAL("failed to convert map", cpu_map_print("1-10,12-20,22-30,32-40"));
118 return 0;
119}
diff --git a/tools/perf/tests/dso-data.c b/tools/perf/tests/dso-data.c
index dc673ff7c437..13725e09ba22 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -202,7 +202,7 @@ static int dsos__create(int cnt, int size)
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++) {
@@ -251,6 +251,9 @@ int test__dso_data_cache(int subtest __maybe_unused)
251 long nr_end, nr = open_files_cnt(); 251 long nr_end, nr = open_files_cnt();
252 int dso_cnt, limit, i, fd; 252 int dso_cnt, limit, i, fd;
253 253
254 /* Rest the internal dso open counter limit. */
255 reset_fd_limit();
256
254 memset(&machine, 0, sizeof(machine)); 257 memset(&machine, 0, sizeof(machine));
255 258
256 /* set as system limit */ 259 /* set as system limit */
@@ -312,6 +315,9 @@ int test__dso_data_reopen(int subtest __maybe_unused)
312#define dso_1 (dsos[1]) 315#define dso_1 (dsos[1])
313#define dso_2 (dsos[2]) 316#define dso_2 (dsos[2])
314 317
318 /* Rest the internal dso open counter limit. */
319 reset_fd_limit();
320
315 memset(&machine, 0, sizeof(machine)); 321 memset(&machine, 0, sizeof(machine));
316 322
317 /* 323 /*
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
new file mode 100644
index 000000000000..19ef77bd6eb4
--- /dev/null
+++ b/tools/perf/tests/event-times.c
@@ -0,0 +1,235 @@
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 str_error_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 perf_evlist__delete(evlist);
204 return !err ? TEST_OK : TEST_FAIL;
205}
206
207/*
208 * This test creates software event 'cpu-clock'
209 * attaches it in several ways (explained below)
210 * and checks that enabled and running times
211 * match.
212 */
213int test__event_times(int subtest __maybe_unused)
214{
215 int err, ret = 0;
216
217#define _T(attach, detach) \
218 err = test_times(attach, detach); \
219 if (err && (ret == TEST_OK || ret == TEST_SKIP)) \
220 ret = err;
221
222 /* attach on newly spawned process after exec */
223 _T(attach__enable_on_exec, detach__enable_on_exec)
224 /* attach on current process as enabled */
225 _T(attach__current_enabled, detach__disable)
226 /* attach on current process as disabled */
227 _T(attach__current_disabled, detach__disable)
228 /* attach on cpu as disabled */
229 _T(attach__cpu_disabled, detach__disable)
230 /* attach on cpu as enabled */
231 _T(attach__cpu_enabled, detach__disable)
232
233#undef _T
234 return ret;
235}
diff --git a/tools/perf/tests/event_update.c b/tools/perf/tests/event_update.c
index 012eab5d1df1..63ecf21750eb 100644
--- a/tools/perf/tests/event_update.c
+++ b/tools/perf/tests/event_update.c
@@ -30,7 +30,7 @@ static int process_event_scale(struct perf_tool *tool __maybe_unused,
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
diff --git a/tools/perf/tests/evsel-roundtrip-name.c b/tools/perf/tests/evsel-roundtrip-name.c
index 2de4a4f2c3ed..60926a1f6fd7 100644
--- a/tools/perf/tests/evsel-roundtrip-name.c
+++ b/tools/perf/tests/evsel-roundtrip-name.c
@@ -80,7 +80,7 @@ static int __perf_evsel__name_array_test(const char *names[], int nr_names)
80 } 80 }
81 81
82 err = 0; 82 err = 0;
83 evlist__for_each(evlist, evsel) { 83 evlist__for_each_entry(evlist, evsel) {
84 if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) { 84 if (strcmp(perf_evsel__name(evsel), names[evsel->idx])) {
85 --err; 85 --err;
86 pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]); 86 pr_debug("%s != %s\n", perf_evsel__name(evsel), names[evsel->idx]);
diff --git a/tools/perf/tests/fdarray.c b/tools/perf/tests/fdarray.c
index c809463edbe5..a2b5ff9bf83d 100644
--- a/tools/perf/tests/fdarray.c
+++ b/tools/perf/tests/fdarray.c
@@ -1,4 +1,5 @@
1#include <api/fd/array.h> 1#include <api/fd/array.h>
2#include <poll.h>
2#include "util/debug.h" 3#include "util/debug.h"
3#include "tests/tests.h" 4#include "tests/tests.h"
4 5
@@ -36,7 +37,7 @@ int test__fdarray__filter(int subtest __maybe_unused)
36 } 37 }
37 38
38 fdarray__init_revents(fda, POLLIN); 39 fdarray__init_revents(fda, POLLIN);
39 nr_fds = fdarray__filter(fda, POLLHUP, NULL); 40 nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL);
40 if (nr_fds != fda->nr_alloc) { 41 if (nr_fds != fda->nr_alloc) {
41 pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything", 42 pr_debug("\nfdarray__filter()=%d != %d shouldn't have filtered anything",
42 nr_fds, fda->nr_alloc); 43 nr_fds, fda->nr_alloc);
@@ -44,7 +45,7 @@ int test__fdarray__filter(int subtest __maybe_unused)
44 } 45 }
45 46
46 fdarray__init_revents(fda, POLLHUP); 47 fdarray__init_revents(fda, POLLHUP);
47 nr_fds = fdarray__filter(fda, POLLHUP, NULL); 48 nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL);
48 if (nr_fds != 0) { 49 if (nr_fds != 0) {
49 pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds", 50 pr_debug("\nfdarray__filter()=%d != %d, should have filtered all fds",
50 nr_fds, fda->nr_alloc); 51 nr_fds, fda->nr_alloc);
@@ -57,7 +58,7 @@ int test__fdarray__filter(int subtest __maybe_unused)
57 58
58 pr_debug("\nfiltering all but fda->entries[2]:"); 59 pr_debug("\nfiltering all but fda->entries[2]:");
59 fdarray__fprintf_prefix(fda, "before", stderr); 60 fdarray__fprintf_prefix(fda, "before", stderr);
60 nr_fds = fdarray__filter(fda, POLLHUP, NULL); 61 nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL);
61 fdarray__fprintf_prefix(fda, " after", stderr); 62 fdarray__fprintf_prefix(fda, " after", stderr);
62 if (nr_fds != 1) { 63 if (nr_fds != 1) {
63 pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds); 64 pr_debug("\nfdarray__filter()=%d != 1, should have left just one event", nr_fds);
@@ -78,7 +79,7 @@ int test__fdarray__filter(int subtest __maybe_unused)
78 79
79 pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):"); 80 pr_debug("\nfiltering all but (fda->entries[0], fda->entries[3]):");
80 fdarray__fprintf_prefix(fda, "before", stderr); 81 fdarray__fprintf_prefix(fda, "before", stderr);
81 nr_fds = fdarray__filter(fda, POLLHUP, NULL); 82 nr_fds = fdarray__filter(fda, POLLHUP, NULL, NULL);
82 fdarray__fprintf_prefix(fda, " after", stderr); 83 fdarray__fprintf_prefix(fda, " after", stderr);
83 if (nr_fds != 2) { 84 if (nr_fds != 2) {
84 pr_debug("\nfdarray__filter()=%d != 2, should have left just two events", 85 pr_debug("\nfdarray__filter()=%d != 2, should have left just two events",
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c
index f55f4bd47932..6b21746d6eec 100644
--- a/tools/perf/tests/hists_common.c
+++ b/tools/perf/tests/hists_common.c
@@ -161,7 +161,7 @@ void print_hists_in(struct hists *hists)
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 else 166 else
167 root = hists->entries_in; 167 root = hists->entries_in;
diff --git a/tools/perf/tests/hists_cumulate.c b/tools/perf/tests/hists_cumulate.c
index ed5aa9eaeb6c..9fd54b79a788 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -101,7 +101,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
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)
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 else 131 else
132 root_in = hists->entries_in; 132 root_in = hists->entries_in;
@@ -216,6 +216,8 @@ static int do_test(struct hists *hists, struct result *expected, size_t nr_expec
216 216
217 /* check callchain entries */ 217 /* check callchain entries */
218 root = &he->callchain->node.rb_root; 218 root = &he->callchain->node.rb_root;
219
220 TEST_ASSERT_VAL("callchains expected", !RB_EMPTY_ROOT(root));
219 cnode = rb_entry(rb_first(root), struct callchain_node, rb_node); 221 cnode = rb_entry(rb_first(root), struct callchain_node, rb_node);
220 222
221 c = 0; 223 c = 0;
@@ -666,6 +668,8 @@ static int test4(struct perf_evsel *evsel, struct machine *machine)
666 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 668 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
667 669
668 setup_sorting(NULL); 670 setup_sorting(NULL);
671
672 callchain_param = callchain_param_default;
669 callchain_register_param(&callchain_param); 673 callchain_register_param(&callchain_param);
670 674
671 err = add_hist_entries(hists, machine); 675 err = add_hist_entries(hists, machine);
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c
index b825d24f8186..62efb14f3a5a 100644
--- a/tools/perf/tests/hists_filter.c
+++ b/tools/perf/tests/hists_filter.c
@@ -56,7 +56,7 @@ static int add_hist_entries(struct perf_evlist *evlist,
56 * (perf [perf] main) will be collapsed to an existing entry 56 * (perf [perf] main) will be collapsed to an existing entry
57 * so total 9 entries will be in the tree. 57 * so total 9 entries will be in the tree.
58 */ 58 */
59 evlist__for_each(evlist, evsel) { 59 evlist__for_each_entry(evlist, evsel) {
60 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { 60 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
61 struct hist_entry_iter iter = { 61 struct hist_entry_iter iter = {
62 .evsel = evsel, 62 .evsel = evsel,
@@ -81,7 +81,7 @@ static int add_hist_entries(struct perf_evlist *evlist,
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 }
@@ -136,7 +136,7 @@ int test__hists_filter(int subtest __maybe_unused)
136 if (err < 0) 136 if (err < 0)
137 goto out; 137 goto out;
138 138
139 evlist__for_each(evlist, evsel) { 139 evlist__for_each_entry(evlist, evsel) {
140 struct hists *hists = evsel__hists(evsel); 140 struct hists *hists = evsel__hists(evsel);
141 141
142 hists__collapse_resort(hists, NULL); 142 hists__collapse_resort(hists, NULL);
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c
index 358324e47805..eddc7407ff8a 100644
--- a/tools/perf/tests/hists_link.c
+++ b/tools/perf/tests/hists_link.c
@@ -72,7 +72,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
72 * However the second evsel also has a collapsed entry for 72 * However the second evsel also has a collapsed entry for
73 * "bash [libc] malloc" so total 9 entries will be in the tree. 73 * "bash [libc] malloc" so total 9 entries will be in the tree.
74 */ 74 */
75 evlist__for_each(evlist, evsel) { 75 evlist__for_each_entry(evlist, evsel) {
76 struct hists *hists = evsel__hists(evsel); 76 struct hists *hists = evsel__hists(evsel);
77 77
78 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) { 78 for (k = 0; k < ARRAY_SIZE(fake_common_samples); k++) {
@@ -84,7 +84,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
84 if (machine__resolve(machine, &al, &sample) < 0) 84 if (machine__resolve(machine, &al, &sample) < 0)
85 goto out; 85 goto out;
86 86
87 he = __hists__add_entry(hists, &al, NULL, 87 he = hists__add_entry(hists, &al, NULL,
88 NULL, NULL, &sample, true); 88 NULL, NULL, &sample, true);
89 if (he == NULL) { 89 if (he == NULL) {
90 addr_location__put(&al); 90 addr_location__put(&al);
@@ -103,7 +103,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine)
103 if (machine__resolve(machine, &al, &sample) < 0) 103 if (machine__resolve(machine, &al, &sample) < 0)
104 goto out; 104 goto out;
105 105
106 he = __hists__add_entry(hists, &al, NULL, 106 he = hists__add_entry(hists, &al, NULL,
107 NULL, NULL, &sample, true); 107 NULL, NULL, &sample, true);
108 if (he == NULL) { 108 if (he == NULL) {
109 addr_location__put(&al); 109 addr_location__put(&al);
@@ -145,7 +145,7 @@ static int __validate_match(struct hists *hists)
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 else 150 else
151 root = hists->entries_in; 151 root = hists->entries_in;
@@ -197,7 +197,7 @@ static int __validate_link(struct hists *hists, int idx)
197 * and some entries will have no pair. However every entry 197 * 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 else 202 else
203 root = hists->entries_in; 203 root = hists->entries_in;
@@ -301,7 +301,7 @@ int test__hists_link(int subtest __maybe_unused)
301 if (err < 0) 301 if (err < 0)
302 goto out; 302 goto out;
303 303
304 evlist__for_each(evlist, evsel) { 304 evlist__for_each_entry(evlist, evsel) {
305 hists = evsel__hists(evsel); 305 hists = evsel__hists(evsel);
306 hists__collapse_resort(hists, NULL); 306 hists__collapse_resort(hists, NULL);
307 307
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c
index d3556fbe8c5c..63c5efaba1b5 100644
--- a/tools/perf/tests/hists_output.c
+++ b/tools/perf/tests/hists_output.c
@@ -67,7 +67,7 @@ static int add_hist_entries(struct hists *hists, struct machine *machine)
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)
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 else 97 else
98 root_in = hists->entries_in; 98 root_in = hists->entries_in;
diff --git a/tools/perf/tests/is_printable_array.c b/tools/perf/tests/is_printable_array.c
new file mode 100644
index 000000000000..42e13393e502
--- /dev/null
+++ b/tools/perf/tests/is_printable_array.c
@@ -0,0 +1,36 @@
1#include <linux/compiler.h>
2#include "tests.h"
3#include "debug.h"
4#include "util.h"
5
6int test__is_printable_array(int subtest __maybe_unused)
7{
8 char buf1[] = { 'k', 'r', 4, 'v', 'a', 0 };
9 char buf2[] = { 'k', 'r', 'a', 'v', 4, 0 };
10 struct {
11 char *buf;
12 unsigned int len;
13 int ret;
14 } t[] = {
15 { (char *) "krava", sizeof("krava"), 1 },
16 { (char *) "krava", sizeof("krava") - 1, 0 },
17 { (char *) "", sizeof(""), 1 },
18 { (char *) "", 0, 0 },
19 { NULL, 0, 0 },
20 { buf1, sizeof(buf1), 0 },
21 { buf2, sizeof(buf2), 0 },
22 };
23 unsigned int i;
24
25 for (i = 0; i < ARRAY_SIZE(t); i++) {
26 int ret;
27
28 ret = is_printable_array((char *) t[i].buf, t[i].len);
29 if (ret != t[i].ret) {
30 pr_err("failed: test %u\n", i);
31 return TEST_FAIL;
32 }
33 }
34
35 return TEST_OK;
36}
diff --git a/tools/perf/tests/keep-tracking.c b/tools/perf/tests/keep-tracking.c
index ddb78fae064a..614e45a3c603 100644
--- a/tools/perf/tests/keep-tracking.c
+++ b/tools/perf/tests/keep-tracking.c
@@ -80,7 +80,7 @@ int test__keep_tracking(int subtest __maybe_unused)
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
diff --git a/tools/perf/tests/kmod-path.c b/tools/perf/tests/kmod-path.c
index d2af78193153..76f41f249944 100644
--- a/tools/perf/tests/kmod-path.c
+++ b/tools/perf/tests/kmod-path.c
@@ -1,4 +1,5 @@
1#include <stdbool.h> 1#include <stdbool.h>
2#include <stdlib.h>
2#include "tests.h" 3#include "tests.h"
3#include "dso.h" 4#include "dso.h"
4#include "debug.h" 5#include "debug.h"
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index cff564fb4b66..b798a4bfd238 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -5,6 +5,7 @@
5#include "llvm.h" 5#include "llvm.h"
6#include "tests.h" 6#include "tests.h"
7#include "debug.h" 7#include "debug.h"
8#include "util.h"
8 9
9#ifdef HAVE_LIBBPF_SUPPORT 10#ifdef HAVE_LIBBPF_SUPPORT
10static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz) 11static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index cac15d93aea6..143f4d549769 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -81,6 +81,8 @@ make_no_libbionic := NO_LIBBIONIC=1
81make_no_auxtrace := NO_AUXTRACE=1 81make_no_auxtrace := NO_AUXTRACE=1
82make_no_libbpf := NO_LIBBPF=1 82make_no_libbpf := NO_LIBBPF=1
83make_no_libcrypto := NO_LIBCRYPTO=1 83make_no_libcrypto := NO_LIBCRYPTO=1
84make_with_babeltrace:= LIBBABELTRACE=1
85make_no_sdt := NO_SDT=1
84make_tags := tags 86make_tags := tags
85make_cscope := cscope 87make_cscope := cscope
86make_help := help 88make_help := help
@@ -104,7 +106,7 @@ make_minimal := NO_LIBPERL=1 NO_LIBPYTHON=1 NO_NEWT=1 NO_GTK2=1
104make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1 106make_minimal += NO_DEMANGLE=1 NO_LIBELF=1 NO_LIBUNWIND=1 NO_BACKTRACE=1
105make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1 107make_minimal += NO_LIBNUMA=1 NO_LIBAUDIT=1 NO_LIBBIONIC=1
106make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1 108make_minimal += NO_LIBDW_DWARF_UNWIND=1 NO_AUXTRACE=1 NO_LIBBPF=1
107make_minimal += NO_LIBCRYPTO=1 109make_minimal += NO_LIBCRYPTO=1 NO_SDT=1
108 110
109# $(run) contains all available tests 111# $(run) contains all available tests
110run := make_pure 112run := make_pure
@@ -136,6 +138,7 @@ run += make_no_libaudit
136run += make_no_libbionic 138run += make_no_libbionic
137run += make_no_auxtrace 139run += make_no_auxtrace
138run += make_no_libbpf 140run += make_no_libbpf
141run += make_with_babeltrace
139run += make_help 142run += make_help
140run += make_doc 143run += make_doc
141run += make_perf_o 144run += make_perf_o
diff --git a/tools/perf/tests/mmap-basic.c b/tools/perf/tests/mmap-basic.c
index 359e98fcd94c..634bce9caebd 100644
--- a/tools/perf/tests/mmap-basic.c
+++ b/tools/perf/tests/mmap-basic.c
@@ -1,3 +1,6 @@
1/* For the CLR_() macros */
2#include <pthread.h>
3
1#include "evlist.h" 4#include "evlist.h"
2#include "evsel.h" 5#include "evsel.h"
3#include "thread_map.h" 6#include "thread_map.h"
@@ -49,7 +52,7 @@ int test__basic_mmap(int subtest __maybe_unused)
49 sched_setaffinity(0, sizeof(cpu_set), &cpu_set); 52 sched_setaffinity(0, sizeof(cpu_set), &cpu_set);
50 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 53 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
51 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 54 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
52 cpus->map[0], strerror_r(errno, sbuf, sizeof(sbuf))); 55 cpus->map[0], str_error_r(errno, sbuf, sizeof(sbuf)));
53 goto out_free_cpus; 56 goto out_free_cpus;
54 } 57 }
55 58
@@ -79,7 +82,7 @@ int test__basic_mmap(int subtest __maybe_unused)
79 if (perf_evsel__open(evsels[i], cpus, threads) < 0) { 82 if (perf_evsel__open(evsels[i], cpus, threads) < 0) {
80 pr_debug("failed to open counter: %s, " 83 pr_debug("failed to open counter: %s, "
81 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 84 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
82 strerror_r(errno, sbuf, sizeof(sbuf))); 85 str_error_r(errno, sbuf, sizeof(sbuf)));
83 goto out_delete_evlist; 86 goto out_delete_evlist;
84 } 87 }
85 88
@@ -89,7 +92,7 @@ int test__basic_mmap(int subtest __maybe_unused)
89 92
90 if (perf_evlist__mmap(evlist, 128, true) < 0) { 93 if (perf_evlist__mmap(evlist, 128, true) < 0) {
91 pr_debug("failed to mmap events: %d (%s)\n", errno, 94 pr_debug("failed to mmap events: %d (%s)\n", errno,
92 strerror_r(errno, sbuf, sizeof(sbuf))); 95 str_error_r(errno, sbuf, sizeof(sbuf)));
93 goto out_delete_evlist; 96 goto out_delete_evlist;
94 } 97 }
95 98
@@ -126,7 +129,7 @@ int test__basic_mmap(int subtest __maybe_unused)
126 } 129 }
127 130
128 err = 0; 131 err = 0;
129 evlist__for_each(evlist, evsel) { 132 evlist__for_each_entry(evlist, evsel) {
130 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) { 133 if (nr_events[evsel->idx] != expected_nr_events[evsel->idx]) {
131 pr_debug("expected %d %s events, got %d\n", 134 pr_debug("expected %d %s events, got %d\n",
132 expected_nr_events[evsel->idx], 135 expected_nr_events[evsel->idx],
diff --git a/tools/perf/tests/openat-syscall-all-cpus.c b/tools/perf/tests/openat-syscall-all-cpus.c
index 53c2273e8859..c8d9592eb142 100644
--- a/tools/perf/tests/openat-syscall-all-cpus.c
+++ b/tools/perf/tests/openat-syscall-all-cpus.c
@@ -1,3 +1,6 @@
1/* For the CPU_* macros */
2#include <pthread.h>
3
1#include <api/fs/fs.h> 4#include <api/fs/fs.h>
2#include <linux/err.h> 5#include <linux/err.h>
3#include "evsel.h" 6#include "evsel.h"
@@ -41,7 +44,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
41 if (perf_evsel__open(evsel, cpus, threads) < 0) { 44 if (perf_evsel__open(evsel, cpus, threads) < 0) {
42 pr_debug("failed to open counter: %s, " 45 pr_debug("failed to open counter: %s, "
43 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 46 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
44 strerror_r(errno, sbuf, sizeof(sbuf))); 47 str_error_r(errno, sbuf, sizeof(sbuf)));
45 goto out_evsel_delete; 48 goto out_evsel_delete;
46 } 49 }
47 50
@@ -62,7 +65,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
62 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) { 65 if (sched_setaffinity(0, sizeof(cpu_set), &cpu_set) < 0) {
63 pr_debug("sched_setaffinity() failed on CPU %d: %s ", 66 pr_debug("sched_setaffinity() failed on CPU %d: %s ",
64 cpus->map[cpu], 67 cpus->map[cpu],
65 strerror_r(errno, sbuf, sizeof(sbuf))); 68 str_error_r(errno, sbuf, sizeof(sbuf)));
66 goto out_close_fd; 69 goto out_close_fd;
67 } 70 }
68 for (i = 0; i < ncalls; ++i) { 71 for (i = 0; i < ncalls; ++i) {
@@ -73,7 +76,7 @@ int test__openat_syscall_event_on_all_cpus(int subtest __maybe_unused)
73 } 76 }
74 77
75 /* 78 /*
76 * Here we need to explicitely preallocate the counts, as if 79 * Here we need to explicitly preallocate the counts, as if
77 * we use the auto allocation it will allocate just for 1 cpu, 80 * we use the auto allocation it will allocate just for 1 cpu,
78 * as we start by cpu 0. 81 * as we start by cpu 0.
79 */ 82 */
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index eb99a105f31c..f52239fed361 100644
--- a/tools/perf/tests/openat-syscall-tp-fields.c
+++ b/tools/perf/tests/openat-syscall-tp-fields.c
@@ -6,6 +6,13 @@
6#include "tests.h" 6#include "tests.h"
7#include "debug.h" 7#include "debug.h"
8 8
9#ifndef O_DIRECTORY
10#define O_DIRECTORY 00200000
11#endif
12#ifndef AT_FDCWD
13#define AT_FDCWD -100
14#endif
15
9int test__syscall_openat_tp_fields(int subtest __maybe_unused) 16int test__syscall_openat_tp_fields(int subtest __maybe_unused)
10{ 17{
11 struct record_opts opts = { 18 struct record_opts opts = {
@@ -44,21 +51,21 @@ int test__syscall_openat_tp_fields(int subtest __maybe_unused)
44 goto out_delete_evlist; 51 goto out_delete_evlist;
45 } 52 }
46 53
47 perf_evsel__config(evsel, &opts); 54 perf_evsel__config(evsel, &opts, NULL);
48 55
49 thread_map__set_pid(evlist->threads, 0, getpid()); 56 thread_map__set_pid(evlist->threads, 0, getpid());
50 57
51 err = perf_evlist__open(evlist); 58 err = perf_evlist__open(evlist);
52 if (err < 0) { 59 if (err < 0) {
53 pr_debug("perf_evlist__open: %s\n", 60 pr_debug("perf_evlist__open: %s\n",
54 strerror_r(errno, sbuf, sizeof(sbuf))); 61 str_error_r(errno, sbuf, sizeof(sbuf)));
55 goto out_delete_evlist; 62 goto out_delete_evlist;
56 } 63 }
57 64
58 err = perf_evlist__mmap(evlist, UINT_MAX, false); 65 err = perf_evlist__mmap(evlist, UINT_MAX, false);
59 if (err < 0) { 66 if (err < 0) {
60 pr_debug("perf_evlist__mmap: %s\n", 67 pr_debug("perf_evlist__mmap: %s\n",
61 strerror_r(errno, sbuf, sizeof(sbuf))); 68 str_error_r(errno, sbuf, sizeof(sbuf)));
62 goto out_delete_evlist; 69 goto out_delete_evlist;
63 } 70 }
64 71
diff --git a/tools/perf/tests/openat-syscall.c b/tools/perf/tests/openat-syscall.c
index 1184f9ba6499..d7414128d7fe 100644
--- a/tools/perf/tests/openat-syscall.c
+++ b/tools/perf/tests/openat-syscall.c
@@ -29,7 +29,7 @@ int test__openat_syscall_event(int subtest __maybe_unused)
29 if (perf_evsel__open_per_thread(evsel, threads) < 0) { 29 if (perf_evsel__open_per_thread(evsel, threads) < 0) {
30 pr_debug("failed to open counter: %s, " 30 pr_debug("failed to open counter: %s, "
31 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 31 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
32 strerror_r(errno, sbuf, sizeof(sbuf))); 32 str_error_r(errno, sbuf, sizeof(sbuf)));
33 goto out_evsel_delete; 33 goto out_evsel_delete;
34 } 34 }
35 35
diff --git a/tools/perf/tests/parse-events.c b/tools/perf/tests/parse-events.c
index 7865f68dc0d8..20c2e641c422 100644
--- a/tools/perf/tests/parse-events.c
+++ b/tools/perf/tests/parse-events.c
@@ -32,7 +32,7 @@ static int test__checkevent_tracepoint_multi(struct perf_evlist *evlist)
32 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); 32 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
33 TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups); 33 TEST_ASSERT_VAL("wrong number of groups", 0 == evlist->nr_groups);
34 34
35 evlist__for_each(evlist, evsel) { 35 evlist__for_each_entry(evlist, evsel) {
36 TEST_ASSERT_VAL("wrong type", 36 TEST_ASSERT_VAL("wrong type",
37 PERF_TYPE_TRACEPOINT == evsel->attr.type); 37 PERF_TYPE_TRACEPOINT == evsel->attr.type);
38 TEST_ASSERT_VAL("wrong sample_type", 38 TEST_ASSERT_VAL("wrong sample_type",
@@ -207,7 +207,7 @@ test__checkevent_tracepoint_multi_modifier(struct perf_evlist *evlist)
207 207
208 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1); 208 TEST_ASSERT_VAL("wrong number of entries", evlist->nr_entries > 1);
209 209
210 evlist__for_each(evlist, evsel) { 210 evlist__for_each_entry(evlist, evsel) {
211 TEST_ASSERT_VAL("wrong exclude_user", 211 TEST_ASSERT_VAL("wrong exclude_user",
212 !evsel->attr.exclude_user); 212 !evsel->attr.exclude_user);
213 TEST_ASSERT_VAL("wrong exclude_kernel", 213 TEST_ASSERT_VAL("wrong exclude_kernel",
@@ -1783,8 +1783,8 @@ static int test_pmu_events(void)
1783 struct evlist_test e; 1783 struct evlist_test e;
1784 char name[MAX_NAME]; 1784 char name[MAX_NAME];
1785 1785
1786 if (!strcmp(ent->d_name, ".") || 1786 /* Names containing . are special and cannot be used directly */
1787 !strcmp(ent->d_name, "..")) 1787 if (strchr(ent->d_name, '.'))
1788 continue; 1788 continue;
1789 1789
1790 snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name); 1790 snprintf(name, MAX_NAME, "cpu/event=%s/u", ent->d_name);
diff --git a/tools/perf/tests/parse-no-sample-id-all.c b/tools/perf/tests/parse-no-sample-id-all.c
index 294c76b01b41..81c6eeaca0f5 100644
--- a/tools/perf/tests/parse-no-sample-id-all.c
+++ b/tools/perf/tests/parse-no-sample-id-all.c
@@ -44,8 +44,7 @@ static int process_events(union perf_event **events, size_t count)
44 for (i = 0; i < count && !err; i++) 44 for (i = 0; i < count && !err; i++)
45 err = process_event(&evlist, events[i]); 45 err = process_event(&evlist, events[i]);
46 46
47 if (evlist) 47 perf_evlist__delete(evlist);
48 perf_evlist__delete(evlist);
49 48
50 return err; 49 return err;
51} 50}
diff --git a/tools/perf/tests/perf-record.c b/tools/perf/tests/perf-record.c
index 1cc78cefe399..8f2e1de6d0ea 100644
--- a/tools/perf/tests/perf-record.c
+++ b/tools/perf/tests/perf-record.c
@@ -1,3 +1,6 @@
1/* For the CLR_() macros */
2#include <pthread.h>
3
1#include <sched.h> 4#include <sched.h>
2#include "evlist.h" 5#include "evlist.h"
3#include "evsel.h" 6#include "evsel.h"
@@ -99,12 +102,12 @@ int test__PERF_RECORD(int subtest __maybe_unused)
99 perf_evsel__set_sample_bit(evsel, CPU); 102 perf_evsel__set_sample_bit(evsel, CPU);
100 perf_evsel__set_sample_bit(evsel, TID); 103 perf_evsel__set_sample_bit(evsel, TID);
101 perf_evsel__set_sample_bit(evsel, TIME); 104 perf_evsel__set_sample_bit(evsel, TIME);
102 perf_evlist__config(evlist, &opts); 105 perf_evlist__config(evlist, &opts, NULL);
103 106
104 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask); 107 err = sched__get_first_possible_cpu(evlist->workload.pid, &cpu_mask);
105 if (err < 0) { 108 if (err < 0) {
106 pr_debug("sched__get_first_possible_cpu: %s\n", 109 pr_debug("sched__get_first_possible_cpu: %s\n",
107 strerror_r(errno, sbuf, sizeof(sbuf))); 110 str_error_r(errno, sbuf, sizeof(sbuf)));
108 goto out_delete_evlist; 111 goto out_delete_evlist;
109 } 112 }
110 113
@@ -115,7 +118,7 @@ int test__PERF_RECORD(int subtest __maybe_unused)
115 */ 118 */
116 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) { 119 if (sched_setaffinity(evlist->workload.pid, cpu_mask_size, &cpu_mask) < 0) {
117 pr_debug("sched_setaffinity: %s\n", 120 pr_debug("sched_setaffinity: %s\n",
118 strerror_r(errno, sbuf, sizeof(sbuf))); 121 str_error_r(errno, sbuf, sizeof(sbuf)));
119 goto out_delete_evlist; 122 goto out_delete_evlist;
120 } 123 }
121 124
@@ -126,7 +129,7 @@ int test__PERF_RECORD(int subtest __maybe_unused)
126 err = perf_evlist__open(evlist); 129 err = perf_evlist__open(evlist);
127 if (err < 0) { 130 if (err < 0) {
128 pr_debug("perf_evlist__open: %s\n", 131 pr_debug("perf_evlist__open: %s\n",
129 strerror_r(errno, sbuf, sizeof(sbuf))); 132 str_error_r(errno, sbuf, sizeof(sbuf)));
130 goto out_delete_evlist; 133 goto out_delete_evlist;
131 } 134 }
132 135
@@ -138,7 +141,7 @@ int test__PERF_RECORD(int subtest __maybe_unused)
138 err = perf_evlist__mmap(evlist, opts.mmap_pages, false); 141 err = perf_evlist__mmap(evlist, opts.mmap_pages, false);
139 if (err < 0) { 142 if (err < 0) {
140 pr_debug("perf_evlist__mmap: %s\n", 143 pr_debug("perf_evlist__mmap: %s\n",
141 strerror_r(errno, sbuf, sizeof(sbuf))); 144 str_error_r(errno, sbuf, sizeof(sbuf)));
142 goto out_delete_evlist; 145 goto out_delete_evlist;
143 } 146 }
144 147
diff --git a/tools/perf/tests/sdt.c b/tools/perf/tests/sdt.c
new file mode 100644
index 000000000000..f59d210e1baf
--- /dev/null
+++ b/tools/perf/tests/sdt.c
@@ -0,0 +1,115 @@
1#include <stdio.h>
2#include <sys/epoll.h>
3#include <util/util.h>
4#include <util/evlist.h>
5#include <linux/filter.h>
6#include "tests.h"
7#include "debug.h"
8#include "probe-file.h"
9#include "build-id.h"
10
11/* To test SDT event, we need libelf support to scan elf binary */
12#if defined(HAVE_SDT_EVENT) && defined(HAVE_LIBELF_SUPPORT)
13
14#include <sys/sdt.h>
15
16static int target_function(void)
17{
18 DTRACE_PROBE(perf, test_target);
19 return TEST_OK;
20}
21
22/* Copied from builtin-buildid-cache.c */
23static int build_id_cache__add_file(const char *filename)
24{
25 char sbuild_id[SBUILD_ID_SIZE];
26 u8 build_id[BUILD_ID_SIZE];
27 int err;
28
29 err = filename__read_build_id(filename, &build_id, sizeof(build_id));
30 if (err < 0) {
31 pr_debug("Failed to read build id of %s\n", filename);
32 return err;
33 }
34
35 build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
36 err = build_id_cache__add_s(sbuild_id, filename, false, false);
37 if (err < 0)
38 pr_debug("Failed to add build id cache of %s\n", filename);
39 return err;
40}
41
42static char *get_self_path(void)
43{
44 char *buf = calloc(PATH_MAX, sizeof(char));
45
46 if (buf && readlink("/proc/self/exe", buf, PATH_MAX) < 0) {
47 pr_debug("Failed to get correct path of perf\n");
48 free(buf);
49 return NULL;
50 }
51 return buf;
52}
53
54static int search_cached_probe(const char *target,
55 const char *group, const char *event)
56{
57 struct probe_cache *cache = probe_cache__new(target);
58 int ret = 0;
59
60 if (!cache) {
61 pr_debug("Failed to open probe cache of %s\n", target);
62 return -EINVAL;
63 }
64
65 if (!probe_cache__find_by_name(cache, group, event)) {
66 pr_debug("Failed to find %s:%s in the cache\n", group, event);
67 ret = -ENOENT;
68 }
69 probe_cache__delete(cache);
70
71 return ret;
72}
73
74int test__sdt_event(int subtests __maybe_unused)
75{
76 int ret = TEST_FAIL;
77 char __tempdir[] = "./test-buildid-XXXXXX";
78 char *tempdir = NULL, *myself = get_self_path();
79
80 if (myself == NULL || mkdtemp(__tempdir) == NULL) {
81 pr_debug("Failed to make a tempdir for build-id cache\n");
82 goto error;
83 }
84 /* Note that buildid_dir must be an absolute path */
85 tempdir = realpath(__tempdir, NULL);
86
87 /* At first, scan itself */
88 set_buildid_dir(tempdir);
89 if (build_id_cache__add_file(myself) < 0)
90 goto error_rmdir;
91
92 /* Open a cache and make sure the SDT is stored */
93 if (search_cached_probe(myself, "sdt_perf", "test_target") < 0)
94 goto error_rmdir;
95
96 /* TBD: probing on the SDT event and collect logs */
97
98 /* Call the target and get an event */
99 ret = target_function();
100
101error_rmdir:
102 /* Cleanup temporary buildid dir */
103 rm_rf(tempdir);
104error:
105 free(tempdir);
106 free(myself);
107 return ret;
108}
109#else
110int test__sdt_event(int subtests __maybe_unused)
111{
112 pr_debug("Skip SDT event test because SDT support is not compiled\n");
113 return TEST_SKIP;
114}
115#endif
diff --git a/tools/perf/tests/sw-clock.c b/tools/perf/tests/sw-clock.c
index 36e8ce1550e3..4c9fd046d57b 100644
--- a/tools/perf/tests/sw-clock.c
+++ b/tools/perf/tests/sw-clock.c
@@ -70,7 +70,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
70 70
71 err = -errno; 71 err = -errno;
72 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n", 72 pr_debug("Couldn't open evlist: %s\nHint: check %s, using %" PRIu64 " in this test.\n",
73 strerror_r(errno, sbuf, sizeof(sbuf)), 73 str_error_r(errno, sbuf, sizeof(sbuf)),
74 knob, (u64)attr.sample_freq); 74 knob, (u64)attr.sample_freq);
75 goto out_delete_evlist; 75 goto out_delete_evlist;
76 } 76 }
@@ -78,7 +78,7 @@ static int __test__sw_clock_freq(enum perf_sw_ids clock_id)
78 err = perf_evlist__mmap(evlist, 128, true); 78 err = perf_evlist__mmap(evlist, 128, true);
79 if (err < 0) { 79 if (err < 0) {
80 pr_debug("failed to mmap event: %d (%s)\n", errno, 80 pr_debug("failed to mmap event: %d (%s)\n", errno,
81 strerror_r(errno, sbuf, sizeof(sbuf))); 81 str_error_r(errno, sbuf, sizeof(sbuf)));
82 goto out_delete_evlist; 82 goto out_delete_evlist;
83 } 83 }
84 84
diff --git a/tools/perf/tests/switch-tracking.c b/tools/perf/tests/switch-tracking.c
index ebd80168d51e..7ddbe267d0ac 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -417,7 +417,7 @@ int test__switch_tracking(int subtest __maybe_unused)
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)) {
@@ -432,7 +432,7 @@ int test__switch_tracking(int subtest __maybe_unused)
432 } 432 }
433 433
434 /* Check non-tracking events are not tracking */ 434 /* Check non-tracking events are not tracking */
435 evlist__for_each(evlist, evsel) { 435 evlist__for_each_entry(evlist, evsel) {
436 if (evsel != tracking_evsel) { 436 if (evsel != tracking_evsel) {
437 if (evsel->attr.mmap || evsel->attr.comm) { 437 if (evsel->attr.mmap || evsel->attr.comm) {
438 pr_debug("Non-tracking event is tracking\n"); 438 pr_debug("Non-tracking event is tracking\n");
diff --git a/tools/perf/tests/task-exit.c b/tools/perf/tests/task-exit.c
index 2dfff7ac8ef3..01a5ba2788c6 100644
--- a/tools/perf/tests/task-exit.c
+++ b/tools/perf/tests/task-exit.c
@@ -91,13 +91,13 @@ int test__task_exit(int subtest __maybe_unused)
91 err = perf_evlist__open(evlist); 91 err = perf_evlist__open(evlist);
92 if (err < 0) { 92 if (err < 0) {
93 pr_debug("Couldn't open the evlist: %s\n", 93 pr_debug("Couldn't open the evlist: %s\n",
94 strerror_r(-err, sbuf, sizeof(sbuf))); 94 str_error_r(-err, sbuf, sizeof(sbuf)));
95 goto out_delete_evlist; 95 goto out_delete_evlist;
96 } 96 }
97 97
98 if (perf_evlist__mmap(evlist, 128, true) < 0) { 98 if (perf_evlist__mmap(evlist, 128, true) < 0) {
99 pr_debug("failed to mmap events: %d (%s)\n", errno, 99 pr_debug("failed to mmap events: %d (%s)\n", errno,
100 strerror_r(errno, sbuf, sizeof(sbuf))); 100 str_error_r(errno, sbuf, sizeof(sbuf)));
101 goto out_delete_evlist; 101 goto out_delete_evlist;
102 } 102 }
103 103
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 82b2b5e6ba7c..7c196c585472 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -85,6 +85,12 @@ int test__synthesize_stat_config(int subtest);
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);
90int test__cpu_map_print(int subtest);
91int test__sdt_event(int subtest);
92int test__is_printable_array(int subtest);
93int test__bitmap_print(int subtest);
88 94
89#if defined(__arm__) || defined(__aarch64__) 95#if defined(__arm__) || defined(__aarch64__)
90#ifdef HAVE_DWARF_UNWIND_SUPPORT 96#ifdef HAVE_DWARF_UNWIND_SUPPORT
diff --git a/tools/perf/tests/thread-map.c b/tools/perf/tests/thread-map.c
index fccde848fe9c..cee2a2cdc933 100644
--- a/tools/perf/tests/thread-map.c
+++ b/tools/perf/tests/thread-map.c
@@ -1,13 +1,20 @@
1#include <sys/types.h> 1#include <sys/types.h>
2#include <unistd.h> 2#include <unistd.h>
3#include <sys/prctl.h>
3#include "tests.h" 4#include "tests.h"
4#include "thread_map.h" 5#include "thread_map.h"
5#include "debug.h" 6#include "debug.h"
6 7
8#define NAME (const char *) "perf"
9#define NAMEUL (unsigned long) NAME
10
7int test__thread_map(int subtest __maybe_unused) 11int test__thread_map(int subtest __maybe_unused)
8{ 12{
9 struct thread_map *map; 13 struct thread_map *map;
10 14
15 TEST_ASSERT_VAL("failed to set process name",
16 !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0));
17
11 /* test map on current pid */ 18 /* test map on current pid */
12 map = thread_map__new_by_pid(getpid()); 19 map = thread_map__new_by_pid(getpid());
13 TEST_ASSERT_VAL("failed to alloc map", map); 20 TEST_ASSERT_VAL("failed to alloc map", map);
@@ -19,7 +26,7 @@ int test__thread_map(int subtest __maybe_unused)
19 thread_map__pid(map, 0) == getpid()); 26 thread_map__pid(map, 0) == getpid());
20 TEST_ASSERT_VAL("wrong comm", 27 TEST_ASSERT_VAL("wrong comm",
21 thread_map__comm(map, 0) && 28 thread_map__comm(map, 0) &&
22 !strcmp(thread_map__comm(map, 0), "perf")); 29 !strcmp(thread_map__comm(map, 0), NAME));
23 TEST_ASSERT_VAL("wrong refcnt", 30 TEST_ASSERT_VAL("wrong refcnt",
24 atomic_read(&map->refcnt) == 1); 31 atomic_read(&map->refcnt) == 1);
25 thread_map__put(map); 32 thread_map__put(map);
@@ -51,7 +58,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
51 58
52 TEST_ASSERT_VAL("wrong nr", map->nr == 1); 59 TEST_ASSERT_VAL("wrong nr", map->nr == 1);
53 TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid()); 60 TEST_ASSERT_VAL("wrong pid", map->entries[0].pid == (u64) getpid());
54 TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, "perf")); 61 TEST_ASSERT_VAL("wrong comm", !strcmp(map->entries[0].comm, NAME));
55 62
56 threads = thread_map__new_event(&event->thread_map); 63 threads = thread_map__new_event(&event->thread_map);
57 TEST_ASSERT_VAL("failed to alloc map", threads); 64 TEST_ASSERT_VAL("failed to alloc map", threads);
@@ -61,7 +68,7 @@ static int process_event(struct perf_tool *tool __maybe_unused,
61 thread_map__pid(threads, 0) == getpid()); 68 thread_map__pid(threads, 0) == getpid());
62 TEST_ASSERT_VAL("wrong comm", 69 TEST_ASSERT_VAL("wrong comm",
63 thread_map__comm(threads, 0) && 70 thread_map__comm(threads, 0) &&
64 !strcmp(thread_map__comm(threads, 0), "perf")); 71 !strcmp(thread_map__comm(threads, 0), NAME));
65 TEST_ASSERT_VAL("wrong refcnt", 72 TEST_ASSERT_VAL("wrong refcnt",
66 atomic_read(&threads->refcnt) == 1); 73 atomic_read(&threads->refcnt) == 1);
67 thread_map__put(threads); 74 thread_map__put(threads);
@@ -72,6 +79,9 @@ int test__thread_map_synthesize(int subtest __maybe_unused)
72{ 79{
73 struct thread_map *threads; 80 struct thread_map *threads;
74 81
82 TEST_ASSERT_VAL("failed to set process name",
83 !prctl(PR_SET_NAME, NAMEUL, 0, 0, 0));
84
75 /* test map on current pid */ 85 /* test map on current pid */
76 threads = thread_map__new_by_pid(getpid()); 86 threads = thread_map__new_by_pid(getpid());
77 TEST_ASSERT_VAL("failed to alloc map", threads); 87 TEST_ASSERT_VAL("failed to alloc map", threads);
diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux-kallsyms.c
index 630b0b409b97..e63abab7d5a1 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -54,8 +54,14 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
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:
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 } else 171 } else
diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c
new file mode 100644
index 000000000000..b08f21eb6f4d
--- /dev/null
+++ b/tools/perf/trace/beauty/eventfd.c
@@ -0,0 +1,36 @@
1#ifndef EFD_SEMAPHORE
2#define EFD_SEMAPHORE 1
3#endif
4
5#ifndef EFD_NONBLOCK
6#define EFD_NONBLOCK 00004000
7#endif
8
9#ifndef EFD_CLOEXEC
10#define EFD_CLOEXEC 02000000
11#endif
12
13static size_t syscall_arg__scnprintf_eventfd_flags(char *bf, size_t size, struct syscall_arg *arg)
14{
15 int printed = 0, flags = arg->val;
16
17 if (flags == 0)
18 return scnprintf(bf, size, "NONE");
19#define P_FLAG(n) \
20 if (flags & EFD_##n) { \
21 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
22 flags &= ~EFD_##n; \
23 }
24
25 P_FLAG(SEMAPHORE);
26 P_FLAG(CLOEXEC);
27 P_FLAG(NONBLOCK);
28#undef P_FLAG
29
30 if (flags)
31 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
32
33 return printed;
34}
35
36#define SCA_EFD_FLAGS syscall_arg__scnprintf_eventfd_flags
diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c
new file mode 100644
index 000000000000..74613703a14e
--- /dev/null
+++ b/tools/perf/trace/beauty/flock.c
@@ -0,0 +1,48 @@
1#include <fcntl.h>
2
3#ifndef LOCK_MAND
4#define LOCK_MAND 32
5#endif
6
7#ifndef LOCK_READ
8#define LOCK_READ 64
9#endif
10
11#ifndef LOCK_WRITE
12#define LOCK_WRITE 128
13#endif
14
15#ifndef LOCK_RW
16#define LOCK_RW 192
17#endif
18
19static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
20 struct syscall_arg *arg)
21{
22 int printed = 0, op = arg->val;
23
24 if (op == 0)
25 return scnprintf(bf, size, "NONE");
26#define P_CMD(cmd) \
27 if ((op & LOCK_##cmd) == LOCK_##cmd) { \
28 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #cmd); \
29 op &= ~LOCK_##cmd; \
30 }
31
32 P_CMD(SH);
33 P_CMD(EX);
34 P_CMD(NB);
35 P_CMD(UN);
36 P_CMD(MAND);
37 P_CMD(RW);
38 P_CMD(READ);
39 P_CMD(WRITE);
40#undef P_OP
41
42 if (op)
43 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", op);
44
45 return printed;
46}
47
48#define SCA_FLOCK syscall_arg__scnprintf_flock
diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c
new file mode 100644
index 000000000000..bfd3359b09b6
--- /dev/null
+++ b/tools/perf/trace/beauty/futex_op.c
@@ -0,0 +1,60 @@
1#include <linux/futex.h>
2
3#ifndef FUTEX_WAIT_BITSET
4#define FUTEX_WAIT_BITSET 9
5#endif
6#ifndef FUTEX_WAKE_BITSET
7#define FUTEX_WAKE_BITSET 10
8#endif
9#ifndef FUTEX_WAIT_REQUEUE_PI
10#define FUTEX_WAIT_REQUEUE_PI 11
11#endif
12#ifndef FUTEX_CMP_REQUEUE_PI
13#define FUTEX_CMP_REQUEUE_PI 12
14#endif
15#ifndef FUTEX_CLOCK_REALTIME
16#define FUTEX_CLOCK_REALTIME 256
17#endif
18
19static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
20{
21 enum syscall_futex_args {
22 SCF_UADDR = (1 << 0),
23 SCF_OP = (1 << 1),
24 SCF_VAL = (1 << 2),
25 SCF_TIMEOUT = (1 << 3),
26 SCF_UADDR2 = (1 << 4),
27 SCF_VAL3 = (1 << 5),
28 };
29 int op = arg->val;
30 int cmd = op & FUTEX_CMD_MASK;
31 size_t printed = 0;
32
33 switch (cmd) {
34#define P_FUTEX_OP(n) case FUTEX_##n: printed = scnprintf(bf, size, #n);
35 P_FUTEX_OP(WAIT); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
36 P_FUTEX_OP(WAKE); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
37 P_FUTEX_OP(FD); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
38 P_FUTEX_OP(REQUEUE); arg->mask |= SCF_VAL3|SCF_TIMEOUT; break;
39 P_FUTEX_OP(CMP_REQUEUE); arg->mask |= SCF_TIMEOUT; break;
40 P_FUTEX_OP(CMP_REQUEUE_PI); arg->mask |= SCF_TIMEOUT; break;
41 P_FUTEX_OP(WAKE_OP); break;
42 P_FUTEX_OP(LOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
43 P_FUTEX_OP(UNLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2|SCF_TIMEOUT; break;
44 P_FUTEX_OP(TRYLOCK_PI); arg->mask |= SCF_VAL3|SCF_UADDR2; break;
45 P_FUTEX_OP(WAIT_BITSET); arg->mask |= SCF_UADDR2; break;
46 P_FUTEX_OP(WAKE_BITSET); arg->mask |= SCF_UADDR2; break;
47 P_FUTEX_OP(WAIT_REQUEUE_PI); break;
48 default: printed = scnprintf(bf, size, "%#x", cmd); break;
49 }
50
51 if (op & FUTEX_PRIVATE_FLAG)
52 printed += scnprintf(bf + printed, size - printed, "|PRIV");
53
54 if (op & FUTEX_CLOCK_REALTIME)
55 printed += scnprintf(bf + printed, size - printed, "|CLKRT");
56
57 return printed;
58}
59
60#define SCA_FUTEX_OP syscall_arg__scnprintf_futex_op
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
new file mode 100644
index 000000000000..d0a3a8e402e7
--- /dev/null
+++ b/tools/perf/trace/beauty/mmap.c
@@ -0,0 +1,191 @@
1#include <sys/mman.h>
2
3#ifndef PROT_SEM
4#define PROT_SEM 0x8
5#endif
6
7static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
8 struct syscall_arg *arg)
9{
10 int printed = 0, prot = arg->val;
11
12 if (prot == PROT_NONE)
13 return scnprintf(bf, size, "NONE");
14#define P_MMAP_PROT(n) \
15 if (prot & PROT_##n) { \
16 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
17 prot &= ~PROT_##n; \
18 }
19
20 P_MMAP_PROT(EXEC);
21 P_MMAP_PROT(READ);
22 P_MMAP_PROT(WRITE);
23 P_MMAP_PROT(SEM);
24 P_MMAP_PROT(GROWSDOWN);
25 P_MMAP_PROT(GROWSUP);
26#undef P_MMAP_PROT
27
28 if (prot)
29 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", prot);
30
31 return printed;
32}
33
34#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
35
36#ifndef MAP_FIXED
37#define MAP_FIXED 0x10
38#endif
39
40#ifndef MAP_ANONYMOUS
41#define MAP_ANONYMOUS 0x20
42#endif
43
44#ifndef MAP_32BIT
45#define MAP_32BIT 0x40
46#endif
47
48#ifndef MAP_STACK
49#define MAP_STACK 0x20000
50#endif
51
52#ifndef MAP_HUGETLB
53#define MAP_HUGETLB 0x40000
54#endif
55
56#ifndef MAP_UNINITIALIZED
57#define MAP_UNINITIALIZED 0x4000000
58#endif
59
60
61static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
62 struct syscall_arg *arg)
63{
64 int printed = 0, flags = arg->val;
65
66#define P_MMAP_FLAG(n) \
67 if (flags & MAP_##n) { \
68 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
69 flags &= ~MAP_##n; \
70 }
71
72 P_MMAP_FLAG(SHARED);
73 P_MMAP_FLAG(PRIVATE);
74 P_MMAP_FLAG(32BIT);
75 P_MMAP_FLAG(ANONYMOUS);
76 P_MMAP_FLAG(DENYWRITE);
77 P_MMAP_FLAG(EXECUTABLE);
78 P_MMAP_FLAG(FILE);
79 P_MMAP_FLAG(FIXED);
80 P_MMAP_FLAG(GROWSDOWN);
81 P_MMAP_FLAG(HUGETLB);
82 P_MMAP_FLAG(LOCKED);
83 P_MMAP_FLAG(NONBLOCK);
84 P_MMAP_FLAG(NORESERVE);
85 P_MMAP_FLAG(POPULATE);
86 P_MMAP_FLAG(STACK);
87 P_MMAP_FLAG(UNINITIALIZED);
88#undef P_MMAP_FLAG
89
90 if (flags)
91 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
92
93 return printed;
94}
95
96#define SCA_MMAP_FLAGS syscall_arg__scnprintf_mmap_flags
97
98#ifndef MREMAP_MAYMOVE
99#define MREMAP_MAYMOVE 1
100#endif
101#ifndef MREMAP_FIXED
102#define MREMAP_FIXED 2
103#endif
104
105static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
106 struct syscall_arg *arg)
107{
108 int printed = 0, flags = arg->val;
109
110#define P_MREMAP_FLAG(n) \
111 if (flags & MREMAP_##n) { \
112 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
113 flags &= ~MREMAP_##n; \
114 }
115
116 P_MREMAP_FLAG(MAYMOVE);
117 P_MREMAP_FLAG(FIXED);
118#undef P_MREMAP_FLAG
119
120 if (flags)
121 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
122
123 return printed;
124}
125
126#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
127
128#ifndef MADV_HWPOISON
129#define MADV_HWPOISON 100
130#endif
131
132#ifndef MADV_SOFT_OFFLINE
133#define MADV_SOFT_OFFLINE 101
134#endif
135
136#ifndef MADV_MERGEABLE
137#define MADV_MERGEABLE 12
138#endif
139
140#ifndef MADV_UNMERGEABLE
141#define MADV_UNMERGEABLE 13
142#endif
143
144#ifndef MADV_HUGEPAGE
145#define MADV_HUGEPAGE 14
146#endif
147
148#ifndef MADV_NOHUGEPAGE
149#define MADV_NOHUGEPAGE 15
150#endif
151
152#ifndef MADV_DONTDUMP
153#define MADV_DONTDUMP 16
154#endif
155
156#ifndef MADV_DODUMP
157#define MADV_DODUMP 17
158#endif
159
160
161static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
162 struct syscall_arg *arg)
163{
164 int behavior = arg->val;
165
166 switch (behavior) {
167#define P_MADV_BHV(n) case MADV_##n: return scnprintf(bf, size, #n)
168 P_MADV_BHV(NORMAL);
169 P_MADV_BHV(RANDOM);
170 P_MADV_BHV(SEQUENTIAL);
171 P_MADV_BHV(WILLNEED);
172 P_MADV_BHV(DONTNEED);
173 P_MADV_BHV(REMOVE);
174 P_MADV_BHV(DONTFORK);
175 P_MADV_BHV(DOFORK);
176 P_MADV_BHV(HWPOISON);
177 P_MADV_BHV(SOFT_OFFLINE);
178 P_MADV_BHV(MERGEABLE);
179 P_MADV_BHV(UNMERGEABLE);
180 P_MADV_BHV(HUGEPAGE);
181 P_MADV_BHV(NOHUGEPAGE);
182 P_MADV_BHV(DONTDUMP);
183 P_MADV_BHV(DODUMP);
184#undef P_MADV_BHV
185 default: break;
186 }
187
188 return scnprintf(bf, size, "%#x", behavior);
189}
190
191#define SCA_MADV_BHV syscall_arg__scnprintf_madvise_behavior
diff --git a/tools/perf/trace/beauty/mode_t.c b/tools/perf/trace/beauty/mode_t.c
new file mode 100644
index 000000000000..930d8fef2400
--- /dev/null
+++ b/tools/perf/trace/beauty/mode_t.c
@@ -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
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c
new file mode 100644
index 000000000000..1106c8960cc4
--- /dev/null
+++ b/tools/perf/trace/beauty/msg_flags.c
@@ -0,0 +1,61 @@
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(CTRUNC);
37 P_MSG_FLAG(PROBE);
38 P_MSG_FLAG(TRUNC);
39 P_MSG_FLAG(DONTWAIT);
40 P_MSG_FLAG(EOR);
41 P_MSG_FLAG(WAITALL);
42 P_MSG_FLAG(FIN);
43 P_MSG_FLAG(SYN);
44 P_MSG_FLAG(CONFIRM);
45 P_MSG_FLAG(RST);
46 P_MSG_FLAG(ERRQUEUE);
47 P_MSG_FLAG(NOSIGNAL);
48 P_MSG_FLAG(MORE);
49 P_MSG_FLAG(WAITFORONE);
50 P_MSG_FLAG(SENDPAGE_NOTLAST);
51 P_MSG_FLAG(FASTOPEN);
52 P_MSG_FLAG(CMSG_CLOEXEC);
53#undef P_MSG_FLAG
54
55 if (flags)
56 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
57
58 return printed;
59}
60
61#define SCA_MSG_FLAGS syscall_arg__scnprintf_msg_flags
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
new file mode 100644
index 000000000000..f55a4597fc38
--- /dev/null
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -0,0 +1,71 @@
1#include <sys/types.h>
2#include <sys/stat.h>
3#include <fcntl.h>
4
5#ifndef O_DIRECT
6#define O_DIRECT 00040000
7#endif
8
9#ifndef O_DIRECTORY
10#define O_DIRECTORY 00200000
11#endif
12
13#ifndef O_NOATIME
14#define O_NOATIME 01000000
15#endif
16
17static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
18 struct syscall_arg *arg)
19{
20 int printed = 0, flags = arg->val;
21
22 if (!(flags & O_CREAT))
23 arg->mask |= 1 << (arg->idx + 1); /* Mask the mode parm */
24
25 if (flags == 0)
26 return scnprintf(bf, size, "RDONLY");
27#define P_FLAG(n) \
28 if (flags & O_##n) { \
29 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
30 flags &= ~O_##n; \
31 }
32
33 P_FLAG(APPEND);
34 P_FLAG(ASYNC);
35 P_FLAG(CLOEXEC);
36 P_FLAG(CREAT);
37 P_FLAG(DIRECT);
38 P_FLAG(DIRECTORY);
39 P_FLAG(EXCL);
40 P_FLAG(LARGEFILE);
41 P_FLAG(NOATIME);
42 P_FLAG(NOCTTY);
43#ifdef O_NONBLOCK
44 P_FLAG(NONBLOCK);
45#elif O_NDELAY
46 P_FLAG(NDELAY);
47#endif
48#ifdef O_PATH
49 P_FLAG(PATH);
50#endif
51 P_FLAG(RDWR);
52#ifdef O_DSYNC
53 if ((flags & O_SYNC) == O_SYNC)
54 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", "SYNC");
55 else {
56 P_FLAG(DSYNC);
57 }
58#else
59 P_FLAG(SYNC);
60#endif
61 P_FLAG(TRUNC);
62 P_FLAG(WRONLY);
63#undef P_FLAG
64
65 if (flags)
66 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
67
68 return printed;
69}
70
71#define SCA_OPEN_FLAGS syscall_arg__scnprintf_open_flags
diff --git a/tools/perf/trace/beauty/perf_event_open.c b/tools/perf/trace/beauty/perf_event_open.c
new file mode 100644
index 000000000000..311f09dd718d
--- /dev/null
+++ b/tools/perf/trace/beauty/perf_event_open.c
@@ -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
diff --git a/tools/perf/trace/beauty/pid.c b/tools/perf/trace/beauty/pid.c
new file mode 100644
index 000000000000..07486ea65ae3
--- /dev/null
+++ b/tools/perf/trace/beauty/pid.c
@@ -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
diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c
new file mode 100644
index 000000000000..34775295b9b3
--- /dev/null
+++ b/tools/perf/trace/beauty/sched_policy.c
@@ -0,0 +1,47 @@
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#ifndef SCHED_RESET_ON_FORK
13#define SCHED_RESET_ON_FORK 0x40000000
14#endif
15
16static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size,
17 struct syscall_arg *arg)
18{
19 const char *policies[] = {
20 "NORMAL", "FIFO", "RR", "BATCH", "ISO", "IDLE", "DEADLINE",
21 };
22 size_t printed;
23 int policy = arg->val,
24 flags = policy & ~SCHED_POLICY_MASK;
25
26 policy &= SCHED_POLICY_MASK;
27 if (policy <= SCHED_DEADLINE)
28 printed = scnprintf(bf, size, "%s", policies[policy]);
29 else
30 printed = scnprintf(bf, size, "%#x", policy);
31
32#define P_POLICY_FLAG(n) \
33 if (flags & SCHED_##n) { \
34 printed += scnprintf(bf + printed, size - printed, "|%s", #n); \
35 flags &= ~SCHED_##n; \
36 }
37
38 P_POLICY_FLAG(RESET_ON_FORK);
39#undef P_POLICY_FLAG
40
41 if (flags)
42 printed += scnprintf(bf + printed, size - printed, "|%#x", flags);
43
44 return printed;
45}
46
47#define SCA_SCHED_POLICY syscall_arg__scnprintf_sched_policy
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c
new file mode 100644
index 000000000000..356441bce27d
--- /dev/null
+++ b/tools/perf/trace/beauty/seccomp.c
@@ -0,0 +1,50 @@
1#ifndef SECCOMP_SET_MODE_STRICT
2#define SECCOMP_SET_MODE_STRICT 0
3#endif
4#ifndef SECCOMP_SET_MODE_FILTER
5#define SECCOMP_SET_MODE_FILTER 1
6#endif
7
8static size_t syscall_arg__scnprintf_seccomp_op(char *bf, size_t size, struct syscall_arg *arg)
9{
10 int op = arg->val;
11 size_t printed = 0;
12
13 switch (op) {
14#define P_SECCOMP_SET_MODE_OP(n) case SECCOMP_SET_MODE_##n: printed = scnprintf(bf, size, #n); break
15 P_SECCOMP_SET_MODE_OP(STRICT);
16 P_SECCOMP_SET_MODE_OP(FILTER);
17#undef P_SECCOMP_SET_MODE_OP
18 default: printed = scnprintf(bf, size, "%#x", op); break;
19 }
20
21 return printed;
22}
23
24#define SCA_SECCOMP_OP syscall_arg__scnprintf_seccomp_op
25
26#ifndef SECCOMP_FILTER_FLAG_TSYNC
27#define SECCOMP_FILTER_FLAG_TSYNC 1
28#endif
29
30static size_t syscall_arg__scnprintf_seccomp_flags(char *bf, size_t size,
31 struct syscall_arg *arg)
32{
33 int printed = 0, flags = arg->val;
34
35#define P_FLAG(n) \
36 if (flags & SECCOMP_FILTER_FLAG_##n) { \
37 printed += scnprintf(bf + printed, size - printed, "%s%s", printed ? "|" : "", #n); \
38 flags &= ~SECCOMP_FILTER_FLAG_##n; \
39 }
40
41 P_FLAG(TSYNC);
42#undef P_FLAG
43
44 if (flags)
45 printed += scnprintf(bf + printed, size - printed, "%s%#x", printed ? "|" : "", flags);
46
47 return printed;
48}
49
50#define SCA_SECCOMP_FLAGS syscall_arg__scnprintf_seccomp_flags
diff --git a/tools/perf/trace/beauty/signum.c b/tools/perf/trace/beauty/signum.c
new file mode 100644
index 000000000000..d3b0b1fab077
--- /dev/null
+++ b/tools/perf/trace/beauty/signum.c
@@ -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
diff --git a/tools/perf/trace/beauty/socket_type.c b/tools/perf/trace/beauty/socket_type.c
new file mode 100644
index 000000000000..0a5ce818131c
--- /dev/null
+++ b/tools/perf/trace/beauty/socket_type.c
@@ -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
diff --git a/tools/perf/trace/beauty/waitid_options.c b/tools/perf/trace/beauty/waitid_options.c
new file mode 100644
index 000000000000..7942724adec8
--- /dev/null
+++ b/tools/perf/trace/beauty/waitid_options.c
@@ -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
diff --git a/tools/perf/ui/browser.c b/tools/perf/ui/browser.c
index af68a9d488bf..3eb3edb307a4 100644
--- a/tools/perf/ui/browser.c
+++ b/tools/perf/ui/browser.c
@@ -1,5 +1,5 @@
1#include "../util.h" 1#include "../util.h"
2#include "../cache.h" 2#include "../config.h"
3#include "../../perf.h" 3#include "../../perf.h"
4#include "libslang.h" 4#include "libslang.h"
5#include "ui.h" 5#include "ui.h"
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index 4fc208e82c6f..2e2d10022355 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -8,6 +8,7 @@
8#include "../../util/sort.h" 8#include "../../util/sort.h"
9#include "../../util/symbol.h" 9#include "../../util/symbol.h"
10#include "../../util/evsel.h" 10#include "../../util/evsel.h"
11#include "../../util/config.h"
11#include <pthread.h> 12#include <pthread.h>
12 13
13struct disasm_line_samples { 14struct disasm_line_samples {
@@ -222,16 +223,14 @@ static void annotate_browser__write(struct ui_browser *browser, void *entry, int
222 } else if (ins__is_call(dl->ins)) { 223 } else if (ins__is_call(dl->ins)) {
223 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR); 224 ui_browser__write_graph(browser, SLSMG_RARROW_CHAR);
224 SLsmg_write_char(' '); 225 SLsmg_write_char(' ');
226 } else if (ins__is_ret(dl->ins)) {
227 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
228 SLsmg_write_char(' ');
225 } else { 229 } else {
226 ui_browser__write_nstring(browser, " ", 2); 230 ui_browser__write_nstring(browser, " ", 2);
227 } 231 }
228 } else { 232 } else {
229 if (strcmp(dl->name, "retq")) { 233 ui_browser__write_nstring(browser, " ", 2);
230 ui_browser__write_nstring(browser, " ", 2);
231 } else {
232 ui_browser__write_graph(browser, SLSMG_LARROW_CHAR);
233 SLsmg_write_char(' ');
234 }
235 } 234 }
236 235
237 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset); 236 disasm_line__scnprintf(dl, bf, sizeof(bf), !annotate_browser__opts.use_offset);
@@ -842,14 +841,14 @@ show_help:
842 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org"); 841 ui_helpline__puts("Huh? No selection. Report to linux-kernel@vger.kernel.org");
843 else if (browser->selection->offset == -1) 842 else if (browser->selection->offset == -1)
844 ui_helpline__puts("Actions are only available for assembly lines."); 843 ui_helpline__puts("Actions are only available for assembly lines.");
845 else if (!browser->selection->ins) { 844 else if (!browser->selection->ins)
846 if (strcmp(browser->selection->name, "retq")) 845 goto show_sup_ins;
847 goto show_sup_ins; 846 else if (ins__is_ret(browser->selection->ins))
848 goto out; 847 goto out;
849 } else if (!(annotate_browser__jump(browser) || 848 else if (!(annotate_browser__jump(browser) ||
850 annotate_browser__callq(browser, evsel, hbt))) { 849 annotate_browser__callq(browser, evsel, hbt))) {
851show_sup_ins: 850show_sup_ins:
852 ui_helpline__puts("Actions are only available for 'callq', 'retq' & jump instructions."); 851 ui_helpline__puts("Actions are only available for function call/return & jump/branch instructions.");
853 } 852 }
854 continue; 853 continue;
855 case 't': 854 case 't':
@@ -1027,7 +1026,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1027 .use_navkeypressed = true, 1026 .use_navkeypressed = true,
1028 }, 1027 },
1029 }; 1028 };
1030 int ret = -1; 1029 int ret = -1, err;
1031 int nr_pcnt = 1; 1030 int nr_pcnt = 1;
1032 size_t sizeof_bdl = sizeof(struct browser_disasm_line); 1031 size_t sizeof_bdl = sizeof(struct browser_disasm_line);
1033 1032
@@ -1051,8 +1050,11 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map,
1051 (nr_pcnt - 1); 1050 (nr_pcnt - 1);
1052 } 1051 }
1053 1052
1054 if (symbol__annotate(sym, map, sizeof_bdl) < 0) { 1053 err = symbol__disassemble(sym, map, sizeof_bdl);
1055 ui__error("%s", ui_helpline__last_msg); 1054 if (err) {
1055 char msg[BUFSIZ];
1056 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
1057 ui__error("Couldn't annotate %s:\n%s", sym->name, msg);
1056 goto out_free_offsets; 1058 goto out_free_offsets;
1057 } 1059 }
1058 1060
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 2a83414159a6..13d414384739 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -12,35 +12,17 @@
12#include "../../util/top.h" 12#include "../../util/top.h"
13#include "../../arch/common.h" 13#include "../../arch/common.h"
14 14
15#include "../browser.h" 15#include "../browsers/hists.h"
16#include "../helpline.h" 16#include "../helpline.h"
17#include "../util.h" 17#include "../util.h"
18#include "../ui.h" 18#include "../ui.h"
19#include "map.h" 19#include "map.h"
20#include "annotate.h" 20#include "annotate.h"
21 21
22struct hist_browser {
23 struct ui_browser b;
24 struct hists *hists;
25 struct hist_entry *he_selection;
26 struct map_symbol *selection;
27 struct hist_browser_timer *hbt;
28 struct pstack *pstack;
29 struct perf_env *env;
30 int print_seq;
31 bool show_dso;
32 bool show_headers;
33 float min_pcnt;
34 u64 nr_non_filtered_entries;
35 u64 nr_hierarchy_entries;
36 u64 nr_callchain_rows;
37};
38
39extern void hist_browser__init_hpp(void); 22extern void hist_browser__init_hpp(void);
40 23
41static int hists__browser_title(struct hists *hists, 24static int perf_evsel_browser_title(struct hist_browser *browser,
42 struct hist_browser_timer *hbt, 25 char *bf, size_t size);
43 char *bf, size_t size);
44static void hist_browser__update_nr_entries(struct hist_browser *hb); 26static void hist_browser__update_nr_entries(struct hist_browser *hb);
45 27
46static struct rb_node *hists__filter_entries(struct rb_node *nd, 28static struct rb_node *hists__filter_entries(struct rb_node *nd,
@@ -585,7 +567,12 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
585 "Or reduce the sampling frequency."); 567 "Or reduce the sampling frequency.");
586} 568}
587 569
588static int hist_browser__run(struct hist_browser *browser, const char *help) 570static int hist_browser__title(struct hist_browser *browser, char *bf, size_t size)
571{
572 return browser->title ? browser->title(browser, bf, size) : 0;
573}
574
575int hist_browser__run(struct hist_browser *browser, const char *help)
589{ 576{
590 int key; 577 int key;
591 char title[160]; 578 char title[160];
@@ -595,7 +582,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help)
595 browser->b.entries = &browser->hists->entries; 582 browser->b.entries = &browser->hists->entries;
596 browser->b.nr_entries = hist_browser__nr_entries(browser); 583 browser->b.nr_entries = hist_browser__nr_entries(browser);
597 584
598 hists__browser_title(browser->hists, hbt, title, sizeof(title)); 585 hist_browser__title(browser, title, sizeof(title));
599 586
600 if (ui_browser__show(&browser->b, title, "%s", help) < 0) 587 if (ui_browser__show(&browser->b, title, "%s", help) < 0)
601 return -1; 588 return -1;
@@ -621,8 +608,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help)
621 ui_browser__warn_lost_events(&browser->b); 608 ui_browser__warn_lost_events(&browser->b);
622 } 609 }
623 610
624 hists__browser_title(browser->hists, 611 hist_browser__title(browser, title, sizeof(title));
625 hbt, title, sizeof(title));
626 ui_browser__show_title(&browser->b, title); 612 ui_browser__show_title(&browser->b, title);
627 continue; 613 continue;
628 } 614 }
@@ -1470,7 +1456,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,
1470 column++ < browser->b.horiz_scroll) 1456 column++ < browser->b.horiz_scroll)
1471 continue; 1457 continue;
1472 1458
1473 ret = fmt->width(fmt, NULL, hists_to_evsel(browser->hists)); 1459 ret = fmt->width(fmt, NULL, browser->hists);
1474 1460
1475 if (first) { 1461 if (first) {
1476 /* for folded sign */ 1462 /* for folded sign */
@@ -1531,7 +1517,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
1531 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) 1517 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll)
1532 continue; 1518 continue;
1533 1519
1534 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1520 ret = fmt->header(fmt, &dummy_hpp, hists);
1535 if (advance_hpp_check(&dummy_hpp, ret)) 1521 if (advance_hpp_check(&dummy_hpp, ret))
1536 break; 1522 break;
1537 1523
@@ -1568,7 +1554,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1568 if (column++ < browser->b.horiz_scroll) 1554 if (column++ < browser->b.horiz_scroll)
1569 continue; 1555 continue;
1570 1556
1571 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1557 ret = fmt->header(fmt, &dummy_hpp, hists);
1572 if (advance_hpp_check(&dummy_hpp, ret)) 1558 if (advance_hpp_check(&dummy_hpp, ret))
1573 break; 1559 break;
1574 1560
@@ -1605,11 +1591,10 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1605 } 1591 }
1606 first_col = false; 1592 first_col = false;
1607 1593
1608 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1594 ret = fmt->header(fmt, &dummy_hpp, hists);
1609 dummy_hpp.buf[ret] = '\0'; 1595 dummy_hpp.buf[ret] = '\0';
1610 rtrim(dummy_hpp.buf);
1611 1596
1612 start = ltrim(dummy_hpp.buf); 1597 start = trim(dummy_hpp.buf);
1613 ret = strlen(start); 1598 ret = strlen(start);
1614 1599
1615 if (start != dummy_hpp.buf) 1600 if (start != dummy_hpp.buf)
@@ -1623,21 +1608,38 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1623 return ret; 1608 return ret;
1624} 1609}
1625 1610
1626static void hist_browser__show_headers(struct hist_browser *browser) 1611static void hists_browser__hierarchy_headers(struct hist_browser *browser)
1627{ 1612{
1628 char headers[1024]; 1613 char headers[1024];
1629 1614
1630 if (symbol_conf.report_hierarchy) 1615 hists_browser__scnprintf_hierarchy_headers(browser, headers,
1631 hists_browser__scnprintf_hierarchy_headers(browser, headers, 1616 sizeof(headers));
1632 sizeof(headers)); 1617
1633 else
1634 hists_browser__scnprintf_headers(browser, headers,
1635 sizeof(headers));
1636 ui_browser__gotorc(&browser->b, 0, 0); 1618 ui_browser__gotorc(&browser->b, 0, 0);
1637 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 1619 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
1638 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 1620 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
1639} 1621}
1640 1622
1623static void hists_browser__headers(struct hist_browser *browser)
1624{
1625 char headers[1024];
1626
1627 hists_browser__scnprintf_headers(browser, headers,
1628 sizeof(headers));
1629
1630 ui_browser__gotorc(&browser->b, 0, 0);
1631 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
1632 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
1633}
1634
1635static void hist_browser__show_headers(struct hist_browser *browser)
1636{
1637 if (symbol_conf.report_hierarchy)
1638 hists_browser__hierarchy_headers(browser);
1639 else
1640 hists_browser__headers(browser);
1641}
1642
1641static void ui_browser__hists_init_top(struct ui_browser *browser) 1643static void ui_browser__hists_init_top(struct ui_browser *browser)
1642{ 1644{
1643 if (browser->top == NULL) { 1645 if (browser->top == NULL) {
@@ -1897,11 +1899,10 @@ static int hist_browser__fprintf_entry(struct hist_browser *browser,
1897 bool first = true; 1899 bool first = true;
1898 int ret; 1900 int ret;
1899 1901
1900 if (symbol_conf.use_callchain) 1902 if (symbol_conf.use_callchain) {
1901 folded_sign = hist_entry__folded(he); 1903 folded_sign = hist_entry__folded(he);
1902
1903 if (symbol_conf.use_callchain)
1904 printed += fprintf(fp, "%c ", folded_sign); 1904 printed += fprintf(fp, "%c ", folded_sign);
1905 }
1905 1906
1906 hists__for_each_format(browser->hists, fmt) { 1907 hists__for_each_format(browser->hists, fmt) {
1907 if (perf_hpp__should_skip(fmt, he->hists)) 1908 if (perf_hpp__should_skip(fmt, he->hists))
@@ -2028,7 +2029,7 @@ static int hist_browser__dump(struct hist_browser *browser)
2028 fp = fopen(filename, "w"); 2029 fp = fopen(filename, "w");
2029 if (fp == NULL) { 2030 if (fp == NULL) {
2030 char bf[64]; 2031 char bf[64];
2031 const char *err = strerror_r(errno, bf, sizeof(bf)); 2032 const char *err = str_error_r(errno, bf, sizeof(bf));
2032 ui_helpline__fpush("Couldn't write to %s: %s", filename, err); 2033 ui_helpline__fpush("Couldn't write to %s: %s", filename, err);
2033 return -1; 2034 return -1;
2034 } 2035 }
@@ -2041,27 +2042,50 @@ static int hist_browser__dump(struct hist_browser *browser)
2041 return 0; 2042 return 0;
2042} 2043}
2043 2044
2044static struct hist_browser *hist_browser__new(struct hists *hists, 2045void hist_browser__init(struct hist_browser *browser,
2045 struct hist_browser_timer *hbt, 2046 struct hists *hists)
2046 struct perf_env *env) 2047{
2048 struct perf_hpp_fmt *fmt;
2049
2050 browser->hists = hists;
2051 browser->b.refresh = hist_browser__refresh;
2052 browser->b.refresh_dimensions = hist_browser__refresh_dimensions;
2053 browser->b.seek = ui_browser__hists_seek;
2054 browser->b.use_navkeypressed = true;
2055 browser->show_headers = symbol_conf.show_hist_headers;
2056
2057 hists__for_each_format(hists, fmt) {
2058 perf_hpp__reset_width(fmt, hists);
2059 ++browser->b.columns;
2060 }
2061}
2062
2063struct hist_browser *hist_browser__new(struct hists *hists)
2047{ 2064{
2048 struct hist_browser *browser = zalloc(sizeof(*browser)); 2065 struct hist_browser *browser = zalloc(sizeof(*browser));
2049 2066
2067 if (browser)
2068 hist_browser__init(browser, hists);
2069
2070 return browser;
2071}
2072
2073static struct hist_browser *
2074perf_evsel_browser__new(struct perf_evsel *evsel,
2075 struct hist_browser_timer *hbt,
2076 struct perf_env *env)
2077{
2078 struct hist_browser *browser = hist_browser__new(evsel__hists(evsel));
2079
2050 if (browser) { 2080 if (browser) {
2051 browser->hists = hists; 2081 browser->hbt = hbt;
2052 browser->b.refresh = hist_browser__refresh; 2082 browser->env = env;
2053 browser->b.refresh_dimensions = hist_browser__refresh_dimensions; 2083 browser->title = perf_evsel_browser_title;
2054 browser->b.seek = ui_browser__hists_seek;
2055 browser->b.use_navkeypressed = true;
2056 browser->show_headers = symbol_conf.show_hist_headers;
2057 browser->hbt = hbt;
2058 browser->env = env;
2059 } 2084 }
2060
2061 return browser; 2085 return browser;
2062} 2086}
2063 2087
2064static void hist_browser__delete(struct hist_browser *browser) 2088void hist_browser__delete(struct hist_browser *browser)
2065{ 2089{
2066 free(browser); 2090 free(browser);
2067} 2091}
@@ -2082,10 +2106,11 @@ static inline bool is_report_browser(void *timer)
2082 return timer == NULL; 2106 return timer == NULL;
2083} 2107}
2084 2108
2085static int hists__browser_title(struct hists *hists, 2109static int perf_evsel_browser_title(struct hist_browser *browser,
2086 struct hist_browser_timer *hbt,
2087 char *bf, size_t size) 2110 char *bf, size_t size)
2088{ 2111{
2112 struct hist_browser_timer *hbt = browser->hbt;
2113 struct hists *hists = browser->hists;
2089 char unit; 2114 char unit;
2090 int printed; 2115 int printed;
2091 const struct dso *dso = hists->dso_filter; 2116 const struct dso *dso = hists->dso_filter;
@@ -2137,7 +2162,7 @@ static int hists__browser_title(struct hists *hists,
2137 printed += snprintf(bf + printed, size - printed, 2162 printed += snprintf(bf + printed, size - printed,
2138 ", UID: %s", hists->uid_filter_str); 2163 ", UID: %s", hists->uid_filter_str);
2139 if (thread) { 2164 if (thread) {
2140 if (sort__has_thread) { 2165 if (hists__has(hists, thread)) {
2141 printed += scnprintf(bf + printed, size - printed, 2166 printed += scnprintf(bf + printed, size - printed,
2142 ", Thread: %s(%d)", 2167 ", Thread: %s(%d)",
2143 (thread->comm_set ? thread__comm_str(thread) : ""), 2168 (thread->comm_set ? thread__comm_str(thread) : ""),
@@ -2322,7 +2347,8 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
2322{ 2347{
2323 struct thread *thread = act->thread; 2348 struct thread *thread = act->thread;
2324 2349
2325 if ((!sort__has_thread && !sort__has_comm) || thread == NULL) 2350 if ((!hists__has(browser->hists, thread) &&
2351 !hists__has(browser->hists, comm)) || thread == NULL)
2326 return 0; 2352 return 0;
2327 2353
2328 if (browser->hists->thread_filter) { 2354 if (browser->hists->thread_filter) {
@@ -2331,7 +2357,7 @@ do_zoom_thread(struct hist_browser *browser, struct popup_action *act)
2331 thread__zput(browser->hists->thread_filter); 2357 thread__zput(browser->hists->thread_filter);
2332 ui_helpline__pop(); 2358 ui_helpline__pop();
2333 } else { 2359 } else {
2334 if (sort__has_thread) { 2360 if (hists__has(browser->hists, thread)) {
2335 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"", 2361 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s(%d) thread\"",
2336 thread->comm_set ? thread__comm_str(thread) : "", 2362 thread->comm_set ? thread__comm_str(thread) : "",
2337 thread->tid); 2363 thread->tid);
@@ -2356,10 +2382,11 @@ add_thread_opt(struct hist_browser *browser, struct popup_action *act,
2356{ 2382{
2357 int ret; 2383 int ret;
2358 2384
2359 if ((!sort__has_thread && !sort__has_comm) || thread == NULL) 2385 if ((!hists__has(browser->hists, thread) &&
2386 !hists__has(browser->hists, comm)) || thread == NULL)
2360 return 0; 2387 return 0;
2361 2388
2362 if (sort__has_thread) { 2389 if (hists__has(browser->hists, thread)) {
2363 ret = asprintf(optstr, "Zoom %s %s(%d) thread", 2390 ret = asprintf(optstr, "Zoom %s %s(%d) thread",
2364 browser->hists->thread_filter ? "out of" : "into", 2391 browser->hists->thread_filter ? "out of" : "into",
2365 thread->comm_set ? thread__comm_str(thread) : "", 2392 thread->comm_set ? thread__comm_str(thread) : "",
@@ -2382,7 +2409,7 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2382{ 2409{
2383 struct map *map = act->ms.map; 2410 struct map *map = act->ms.map;
2384 2411
2385 if (!sort__has_dso || map == NULL) 2412 if (!hists__has(browser->hists, dso) || map == NULL)
2386 return 0; 2413 return 0;
2387 2414
2388 if (browser->hists->dso_filter) { 2415 if (browser->hists->dso_filter) {
@@ -2409,7 +2436,7 @@ static int
2409add_dso_opt(struct hist_browser *browser, struct popup_action *act, 2436add_dso_opt(struct hist_browser *browser, struct popup_action *act,
2410 char **optstr, struct map *map) 2437 char **optstr, struct map *map)
2411{ 2438{
2412 if (!sort__has_dso || map == NULL) 2439 if (!hists__has(browser->hists, dso) || map == NULL)
2413 return 0; 2440 return 0;
2414 2441
2415 if (asprintf(optstr, "Zoom %s %s DSO", 2442 if (asprintf(optstr, "Zoom %s %s DSO",
@@ -2431,10 +2458,10 @@ do_browse_map(struct hist_browser *browser __maybe_unused,
2431} 2458}
2432 2459
2433static int 2460static int
2434add_map_opt(struct hist_browser *browser __maybe_unused, 2461add_map_opt(struct hist_browser *browser,
2435 struct popup_action *act, char **optstr, struct map *map) 2462 struct popup_action *act, char **optstr, struct map *map)
2436{ 2463{
2437 if (!sort__has_dso || map == NULL) 2464 if (!hists__has(browser->hists, dso) || map == NULL)
2438 return 0; 2465 return 0;
2439 2466
2440 if (asprintf(optstr, "Browse map details") < 0) 2467 if (asprintf(optstr, "Browse map details") < 0)
@@ -2536,7 +2563,7 @@ add_exit_opt(struct hist_browser *browser __maybe_unused,
2536static int 2563static int
2537do_zoom_socket(struct hist_browser *browser, struct popup_action *act) 2564do_zoom_socket(struct hist_browser *browser, struct popup_action *act)
2538{ 2565{
2539 if (!sort__has_socket || act->socket < 0) 2566 if (!hists__has(browser->hists, socket) || act->socket < 0)
2540 return 0; 2567 return 0;
2541 2568
2542 if (browser->hists->socket_filter > -1) { 2569 if (browser->hists->socket_filter > -1) {
@@ -2558,7 +2585,7 @@ static int
2558add_socket_opt(struct hist_browser *browser, struct popup_action *act, 2585add_socket_opt(struct hist_browser *browser, struct popup_action *act,
2559 char **optstr, int socket_id) 2586 char **optstr, int socket_id)
2560{ 2587{
2561 if (!sort__has_socket || socket_id < 0) 2588 if (!hists__has(browser->hists, socket) || socket_id < 0)
2562 return 0; 2589 return 0;
2563 2590
2564 if (asprintf(optstr, "Zoom %s Processor Socket %d", 2591 if (asprintf(optstr, "Zoom %s Processor Socket %d",
@@ -2640,7 +2667,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2640 struct perf_env *env) 2667 struct perf_env *env)
2641{ 2668{
2642 struct hists *hists = evsel__hists(evsel); 2669 struct hists *hists = evsel__hists(evsel);
2643 struct hist_browser *browser = hist_browser__new(hists, hbt, env); 2670 struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env);
2644 struct branch_info *bi; 2671 struct branch_info *bi;
2645#define MAX_OPTIONS 16 2672#define MAX_OPTIONS 16
2646 char *options[MAX_OPTIONS]; 2673 char *options[MAX_OPTIONS];
@@ -2649,7 +2676,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2649 int key = -1; 2676 int key = -1;
2650 char buf[64]; 2677 char buf[64];
2651 int delay_secs = hbt ? hbt->refresh : 0; 2678 int delay_secs = hbt ? hbt->refresh : 0;
2652 struct perf_hpp_fmt *fmt;
2653 2679
2654#define HIST_BROWSER_HELP_COMMON \ 2680#define HIST_BROWSER_HELP_COMMON \
2655 "h/?/F1 Show this window\n" \ 2681 "h/?/F1 Show this window\n" \
@@ -2708,18 +2734,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2708 memset(options, 0, sizeof(options)); 2734 memset(options, 0, sizeof(options));
2709 memset(actions, 0, sizeof(actions)); 2735 memset(actions, 0, sizeof(actions));
2710 2736
2711 hists__for_each_format(browser->hists, fmt) {
2712 perf_hpp__reset_width(fmt, hists);
2713 /*
2714 * This is done just once, and activates the horizontal scrolling
2715 * code in the ui_browser code, it would be better to have a the
2716 * counter in the perf_hpp code, but I couldn't find doing it here
2717 * works, FIXME by setting this in hist_browser__new, for now, be
2718 * clever 8-)
2719 */
2720 ++browser->b.columns;
2721 }
2722
2723 if (symbol_conf.col_width_list_str) 2737 if (symbol_conf.col_width_list_str)
2724 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 2738 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
2725 2739
@@ -2749,7 +2763,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2749 */ 2763 */
2750 goto out_free_stack; 2764 goto out_free_stack;
2751 case 'a': 2765 case 'a':
2752 if (!sort__has_sym) { 2766 if (!hists__has(hists, sym)) {
2753 ui_browser__warning(&browser->b, delay_secs * 2, 2767 ui_browser__warning(&browser->b, delay_secs * 2,
2754 "Annotation is only available for symbolic views, " 2768 "Annotation is only available for symbolic views, "
2755 "include \"sym*\" in --sort to use it."); 2769 "include \"sym*\" in --sort to use it.");
@@ -2912,7 +2926,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2912 continue; 2926 continue;
2913 } 2927 }
2914 2928
2915 if (!sort__has_sym || browser->selection == NULL) 2929 if (!hists__has(hists, sym) || browser->selection == NULL)
2916 goto skip_annotation; 2930 goto skip_annotation;
2917 2931
2918 if (sort__mode == SORT_MODE__BRANCH) { 2932 if (sort__mode == SORT_MODE__BRANCH) {
@@ -2956,7 +2970,7 @@ skip_annotation:
2956 goto skip_scripting; 2970 goto skip_scripting;
2957 2971
2958 if (browser->he_selection) { 2972 if (browser->he_selection) {
2959 if (sort__has_thread && thread) { 2973 if (hists__has(hists, thread) && thread) {
2960 nr_options += add_script_opt(browser, 2974 nr_options += add_script_opt(browser,
2961 &actions[nr_options], 2975 &actions[nr_options],
2962 &options[nr_options], 2976 &options[nr_options],
@@ -2971,7 +2985,7 @@ skip_annotation:
2971 * 2985 *
2972 * See hist_browser__show_entry. 2986 * See hist_browser__show_entry.
2973 */ 2987 */
2974 if (sort__has_sym && browser->selection->sym) { 2988 if (hists__has(hists, sym) && browser->selection->sym) {
2975 nr_options += add_script_opt(browser, 2989 nr_options += add_script_opt(browser,
2976 &actions[nr_options], 2990 &actions[nr_options],
2977 &options[nr_options], 2991 &options[nr_options],
@@ -3185,7 +3199,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
3185 3199
3186 ui_helpline__push("Press ESC to exit"); 3200 ui_helpline__push("Press ESC to exit");
3187 3201
3188 evlist__for_each(evlist, pos) { 3202 evlist__for_each_entry(evlist, pos) {
3189 const char *ev_name = perf_evsel__name(pos); 3203 const char *ev_name = perf_evsel__name(pos);
3190 size_t line_len = strlen(ev_name) + 7; 3204 size_t line_len = strlen(ev_name) + 7;
3191 3205
@@ -3216,7 +3230,7 @@ single_entry:
3216 struct perf_evsel *pos; 3230 struct perf_evsel *pos;
3217 3231
3218 nr_entries = 0; 3232 nr_entries = 0;
3219 evlist__for_each(evlist, pos) { 3233 evlist__for_each_entry(evlist, pos) {
3220 if (perf_evsel__is_group_leader(pos)) 3234 if (perf_evsel__is_group_leader(pos))
3221 nr_entries++; 3235 nr_entries++;
3222 } 3236 }
diff --git a/tools/perf/ui/browsers/hists.h b/tools/perf/ui/browsers/hists.h
new file mode 100644
index 000000000000..39bd0f28f211
--- /dev/null
+++ b/tools/perf/ui/browsers/hists.h
@@ -0,0 +1,32 @@
1#ifndef _PERF_UI_BROWSER_HISTS_H_
2#define _PERF_UI_BROWSER_HISTS_H_ 1
3
4#include "ui/browser.h"
5
6struct hist_browser {
7 struct ui_browser b;
8 struct hists *hists;
9 struct hist_entry *he_selection;
10 struct map_symbol *selection;
11 struct hist_browser_timer *hbt;
12 struct pstack *pstack;
13 struct perf_env *env;
14 int print_seq;
15 bool show_dso;
16 bool show_headers;
17 float min_pcnt;
18 u64 nr_non_filtered_entries;
19 u64 nr_hierarchy_entries;
20 u64 nr_callchain_rows;
21
22 /* Get title string. */
23 int (*title)(struct hist_browser *browser,
24 char *bf, size_t size);
25};
26
27struct hist_browser *hist_browser__new(struct hists *hists);
28void hist_browser__delete(struct hist_browser *browser);
29int hist_browser__run(struct hist_browser *browser, const char *help);
30void hist_browser__init(struct hist_browser *browser,
31 struct hists *hists);
32#endif /* _PERF_UI_BROWSER_HISTS_H_ */
diff --git a/tools/perf/ui/gtk/annotate.c b/tools/perf/ui/gtk/annotate.c
index 9c7ff8d31b27..42d319927762 100644
--- a/tools/perf/ui/gtk/annotate.c
+++ b/tools/perf/ui/gtk/annotate.c
@@ -162,12 +162,16 @@ static int symbol__gtk_annotate(struct symbol *sym, struct map *map,
162 GtkWidget *notebook; 162 GtkWidget *notebook;
163 GtkWidget *scrolled_window; 163 GtkWidget *scrolled_window;
164 GtkWidget *tab_label; 164 GtkWidget *tab_label;
165 int err;
165 166
166 if (map->dso->annotate_warned) 167 if (map->dso->annotate_warned)
167 return -1; 168 return -1;
168 169
169 if (symbol__annotate(sym, map, 0) < 0) { 170 err = symbol__disassemble(sym, map, 0);
170 ui__error("%s", ui_helpline__current); 171 if (err) {
172 char msg[BUFSIZ];
173 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
174 ui__error("Couldn't annotate %s: %s\n", sym->name, msg);
171 return -1; 175 return -1;
172 } 176 }
173 177
diff --git a/tools/perf/ui/gtk/hists.c b/tools/perf/ui/gtk/hists.c
index 2aa45b606fa4..c5f3677f6679 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -379,7 +379,7 @@ static void perf_gtk__show_hists(GtkWidget *window, struct hists *hists,
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;
@@ -549,7 +549,7 @@ static void perf_gtk__show_hierarchy(GtkWidget *window, struct hists *hists,
549 strcat(buf, "+"); 549 strcat(buf, "+");
550 first_col = false; 550 first_col = false;
551 551
552 fmt->header(fmt, &hpp, hists_to_evsel(hists)); 552 fmt->header(fmt, &hpp, hists);
553 strcat(buf, ltrim(rtrim(hpp.buf))); 553 strcat(buf, ltrim(rtrim(hpp.buf)));
554 } 554 }
555 } 555 }
@@ -627,7 +627,7 @@ int perf_evlist__gtk_browse_hists(struct perf_evlist *evlist,
627 627
628 gtk_container_add(GTK_CONTAINER(window), vbox); 628 gtk_container_add(GTK_CONTAINER(window), vbox);
629 629
630 evlist__for_each(evlist, pos) { 630 evlist__for_each_entry(evlist, pos) {
631 struct hists *hists = evsel__hists(pos); 631 struct hists *hists = evsel__hists(pos);
632 const char *evname = perf_evsel__name(pos); 632 const char *evname = perf_evsel__name(pos);
633 GtkWidget *scrolled_window; 633 GtkWidget *scrolled_window;
diff --git a/tools/perf/ui/gtk/util.c b/tools/perf/ui/gtk/util.c
index 52e7fc48af9f..00b91921edb1 100644
--- a/tools/perf/ui/gtk/util.c
+++ b/tools/perf/ui/gtk/util.c
@@ -1,4 +1,5 @@
1#include "../util.h" 1#include "../util.h"
2#include "../../util/util.h"
2#include "../../util/debug.h" 3#include "../../util/debug.h"
3#include "gtk.h" 4#include "gtk.h"
4 5
diff --git a/tools/perf/ui/helpline.c b/tools/perf/ui/helpline.c
index 700fb3cfa1c7..5b74a7eba210 100644
--- a/tools/perf/ui/helpline.c
+++ b/tools/perf/ui/helpline.c
@@ -5,6 +5,7 @@
5#include "../debug.h" 5#include "../debug.h"
6#include "helpline.h" 6#include "helpline.h"
7#include "ui.h" 7#include "ui.h"
8#include "../util.h"
8 9
9char ui_helpline__current[512]; 10char ui_helpline__current[512];
10 11
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c
index 3baeaa6e71b5..4274969ddc89 100644
--- a/tools/perf/ui/hist.c
+++ b/tools/perf/ui/hist.c
@@ -215,9 +215,10 @@ static int __hpp__sort_acc(struct hist_entry *a, struct hist_entry *b,
215 215
216static int hpp__width_fn(struct perf_hpp_fmt *fmt, 216static int hpp__width_fn(struct perf_hpp_fmt *fmt,
217 struct perf_hpp *hpp __maybe_unused, 217 struct perf_hpp *hpp __maybe_unused,
218 struct perf_evsel *evsel) 218 struct hists *hists)
219{ 219{
220 int len = fmt->user_len ?: fmt->len; 220 int len = fmt->user_len ?: fmt->len;
221 struct perf_evsel *evsel = hists_to_evsel(hists);
221 222
222 if (symbol_conf.event_group) 223 if (symbol_conf.event_group)
223 len = max(len, evsel->nr_members * fmt->len); 224 len = max(len, evsel->nr_members * fmt->len);
@@ -229,9 +230,9 @@ static int hpp__width_fn(struct perf_hpp_fmt *fmt,
229} 230}
230 231
231static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 232static int hpp__header_fn(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
232 struct perf_evsel *evsel) 233 struct hists *hists)
233{ 234{
234 int len = hpp__width_fn(fmt, hpp, evsel); 235 int len = hpp__width_fn(fmt, hpp, hists);
235 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name); 236 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
236} 237}
237 238
@@ -632,10 +633,10 @@ unsigned int hists__sort_list_width(struct hists *hists)
632 else 633 else
633 ret += 2; 634 ret += 2;
634 635
635 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); 636 ret += fmt->width(fmt, &dummy_hpp, hists);
636 } 637 }
637 638
638 if (verbose && sort__has_sym) /* Addr + origin */ 639 if (verbose && hists__has(hists, sym)) /* Addr + origin */
639 ret += 3 + BITS_PER_LONG / 4; 640 ret += 3 + BITS_PER_LONG / 4;
640 641
641 return ret; 642 return ret;
@@ -657,7 +658,7 @@ unsigned int hists__overhead_width(struct hists *hists)
657 else 658 else
658 ret += 2; 659 ret += 2;
659 660
660 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); 661 ret += fmt->width(fmt, &dummy_hpp, hists);
661 } 662 }
662 663
663 return ret; 664 return ret;
@@ -765,7 +766,7 @@ int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
765 if (!symbol_conf.report_hierarchy) 766 if (!symbol_conf.report_hierarchy)
766 return 0; 767 return 0;
767 768
768 evlist__for_each(evlist, evsel) { 769 evlist__for_each_entry(evlist, evsel) {
769 hists = evsel__hists(evsel); 770 hists = evsel__hists(evsel);
770 771
771 perf_hpp_list__for_each_sort_list(list, fmt) { 772 perf_hpp_list__for_each_sort_list(list, fmt) {
diff --git a/tools/perf/ui/setup.c b/tools/perf/ui/setup.c
index ba51fa8a1176..1f6b0994f4f4 100644
--- a/tools/perf/ui/setup.c
+++ b/tools/perf/ui/setup.c
@@ -60,6 +60,13 @@ static inline int setup_gtk_browser(void) { return -1; }
60static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {} 60static inline void exit_gtk_browser(bool wait_for_ok __maybe_unused) {}
61#endif 61#endif
62 62
63int stdio__config_color(const struct option *opt __maybe_unused,
64 const char *mode, int unset __maybe_unused)
65{
66 perf_use_color_default = perf_config_colorbool("color.ui", mode, -1);
67 return 0;
68}
69
63void setup_browser(bool fallback_to_pager) 70void setup_browser(bool fallback_to_pager)
64{ 71{
65 if (use_browser < 2 && (!isatty(1) || dump_trace)) 72 if (use_browser < 2 && (!isatty(1) || dump_trace))
diff --git a/tools/perf/ui/stdio/hist.c b/tools/perf/ui/stdio/hist.c
index 7aff5acf3265..f04a63112079 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -492,14 +492,15 @@ out:
492} 492}
493 493
494static int hist_entry__fprintf(struct hist_entry *he, size_t size, 494static int hist_entry__fprintf(struct hist_entry *he, size_t size,
495 struct hists *hists, 495 char *bf, size_t bfsz, FILE *fp,
496 char *bf, size_t bfsz, FILE *fp) 496 bool use_callchain)
497{ 497{
498 int ret; 498 int ret;
499 struct perf_hpp hpp = { 499 struct perf_hpp hpp = {
500 .buf = bf, 500 .buf = bf,
501 .size = size, 501 .size = size,
502 }; 502 };
503 struct hists *hists = he->hists;
503 u64 total_period = hists->stats.total_period; 504 u64 total_period = hists->stats.total_period;
504 505
505 if (size == 0 || size > bfsz) 506 if (size == 0 || size > bfsz)
@@ -512,7 +513,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
512 513
513 ret = fprintf(fp, "%s\n", bf); 514 ret = fprintf(fp, "%s\n", bf);
514 515
515 if (symbol_conf.use_callchain) 516 if (use_callchain)
516 ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); 517 ret += hist_entry_callchain__fprintf(he, total_period, 0, fp);
517 518
518 return ret; 519 return ret;
@@ -548,7 +549,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
548 struct perf_hpp_list_node, list); 549 struct perf_hpp_list_node, list);
549 550
550 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 551 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
551 fmt->header(fmt, hpp, hists_to_evsel(hists)); 552 fmt->header(fmt, hpp, hists);
552 fprintf(fp, "%s%s", hpp->buf, sep ?: " "); 553 fprintf(fp, "%s%s", hpp->buf, sep ?: " ");
553 } 554 }
554 555
@@ -568,10 +569,9 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
568 header_width += fprintf(fp, "+"); 569 header_width += fprintf(fp, "+");
569 first_col = false; 570 first_col = false;
570 571
571 fmt->header(fmt, hpp, hists_to_evsel(hists)); 572 fmt->header(fmt, hpp, hists);
572 rtrim(hpp->buf);
573 573
574 header_width += fprintf(fp, "%s", ltrim(hpp->buf)); 574 header_width += fprintf(fp, "%s", trim(hpp->buf));
575 } 575 }
576 } 576 }
577 577
@@ -590,7 +590,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
590 fprintf(fp, "%s", sep ?: ".."); 590 fprintf(fp, "%s", sep ?: "..");
591 first_col = false; 591 first_col = false;
592 592
593 width = fmt->width(fmt, hpp, hists_to_evsel(hists)); 593 width = fmt->width(fmt, hpp, hists);
594 fprintf(fp, "%.*s", width, dots); 594 fprintf(fp, "%.*s", width, dots);
595 } 595 }
596 596
@@ -607,7 +607,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
607 width++; /* for '+' sign between column header */ 607 width++; /* for '+' sign between column header */
608 first_col = false; 608 first_col = false;
609 609
610 width += fmt->width(fmt, hpp, hists_to_evsel(hists)); 610 width += fmt->width(fmt, hpp, hists);
611 } 611 }
612 612
613 if (width > header_width) 613 if (width > header_width)
@@ -623,47 +623,31 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
623 return 2; 623 return 2;
624} 624}
625 625
626size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 626static int
627 int max_cols, float min_pcnt, FILE *fp) 627hists__fprintf_hierarchy_headers(struct hists *hists,
628 struct perf_hpp *hpp,
629 FILE *fp)
628{ 630{
629 struct perf_hpp_fmt *fmt;
630 struct perf_hpp_list_node *fmt_node; 631 struct perf_hpp_list_node *fmt_node;
631 struct rb_node *nd; 632 struct perf_hpp_fmt *fmt;
632 size_t ret = 0;
633 unsigned int width;
634 const char *sep = symbol_conf.field_sep;
635 int nr_rows = 0;
636 char bf[96];
637 struct perf_hpp dummy_hpp = {
638 .buf = bf,
639 .size = sizeof(bf),
640 };
641 bool first = true;
642 size_t linesz;
643 char *line = NULL;
644 unsigned indent;
645
646 init_rem_hits();
647
648 hists__for_each_format(hists, fmt)
649 perf_hpp__reset_width(fmt, hists);
650
651 if (symbol_conf.col_width_list_str)
652 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
653 633
654 if (!show_header) 634 list_for_each_entry(fmt_node, &hists->hpp_formats, list) {
655 goto print_entries; 635 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt)
636 perf_hpp__reset_width(fmt, hists);
637 }
656 638
657 fprintf(fp, "# "); 639 return print_hierarchy_header(hists, hpp, symbol_conf.field_sep, fp);
640}
658 641
659 if (symbol_conf.report_hierarchy) { 642static int
660 list_for_each_entry(fmt_node, &hists->hpp_formats, list) { 643hists__fprintf_standard_headers(struct hists *hists,
661 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) 644 struct perf_hpp *hpp,
662 perf_hpp__reset_width(fmt, hists); 645 FILE *fp)
663 } 646{
664 nr_rows += print_hierarchy_header(hists, &dummy_hpp, sep, fp); 647 struct perf_hpp_fmt *fmt;
665 goto print_entries; 648 unsigned int width;
666 } 649 const char *sep = symbol_conf.field_sep;
650 bool first = true;
667 651
668 hists__for_each_format(hists, fmt) { 652 hists__for_each_format(hists, fmt) {
669 if (perf_hpp__should_skip(fmt, hists)) 653 if (perf_hpp__should_skip(fmt, hists))
@@ -674,16 +658,14 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
674 else 658 else
675 first = false; 659 first = false;
676 660
677 fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 661 fmt->header(fmt, hpp, hists);
678 fprintf(fp, "%s", bf); 662 fprintf(fp, "%s", hpp->buf);
679 } 663 }
680 664
681 fprintf(fp, "\n"); 665 fprintf(fp, "\n");
682 if (max_rows && ++nr_rows >= max_rows)
683 goto out;
684 666
685 if (sep) 667 if (sep)
686 goto print_entries; 668 return 1;
687 669
688 first = true; 670 first = true;
689 671
@@ -700,20 +682,60 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
700 else 682 else
701 first = false; 683 first = false;
702 684
703 width = fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); 685 width = fmt->width(fmt, hpp, hists);
704 for (i = 0; i < width; i++) 686 for (i = 0; i < width; i++)
705 fprintf(fp, "."); 687 fprintf(fp, ".");
706 } 688 }
707 689
708 fprintf(fp, "\n"); 690 fprintf(fp, "\n");
709 if (max_rows && ++nr_rows >= max_rows)
710 goto out;
711
712 fprintf(fp, "#\n"); 691 fprintf(fp, "#\n");
713 if (max_rows && ++nr_rows >= max_rows) 692 return 3;
693}
694
695static int hists__fprintf_headers(struct hists *hists, FILE *fp)
696{
697 char bf[96];
698 struct perf_hpp dummy_hpp = {
699 .buf = bf,
700 .size = sizeof(bf),
701 };
702
703 fprintf(fp, "# ");
704
705 if (symbol_conf.report_hierarchy)
706 return hists__fprintf_hierarchy_headers(hists, &dummy_hpp, fp);
707 else
708 return hists__fprintf_standard_headers(hists, &dummy_hpp, fp);
709
710}
711
712size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
713 int max_cols, float min_pcnt, FILE *fp,
714 bool use_callchain)
715{
716 struct perf_hpp_fmt *fmt;
717 struct rb_node *nd;
718 size_t ret = 0;
719 const char *sep = symbol_conf.field_sep;
720 int nr_rows = 0;
721 size_t linesz;
722 char *line = NULL;
723 unsigned indent;
724
725 init_rem_hits();
726
727 hists__for_each_format(hists, fmt)
728 perf_hpp__reset_width(fmt, hists);
729
730 if (symbol_conf.col_width_list_str)
731 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
732
733 if (show_header)
734 nr_rows += hists__fprintf_headers(hists, fp);
735
736 if (max_rows && nr_rows >= max_rows)
714 goto out; 737 goto out;
715 738
716print_entries:
717 linesz = hists__sort_list_width(hists) + 3 + 1; 739 linesz = hists__sort_list_width(hists) + 3 + 1;
718 linesz += perf_hpp__color_overhead(); 740 linesz += perf_hpp__color_overhead();
719 line = malloc(linesz); 741 line = malloc(linesz);
@@ -735,7 +757,7 @@ print_entries:
735 if (percent < min_pcnt) 757 if (percent < min_pcnt)
736 continue; 758 continue;
737 759
738 ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp); 760 ret += hist_entry__fprintf(h, max_cols, line, linesz, fp, use_callchain);
739 761
740 if (max_rows && ++nr_rows >= max_rows) 762 if (max_rows && ++nr_rows >= max_rows)
741 break; 763 break;
diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c
index 7dfeba0a91f3..4ea2ba861fc2 100644
--- a/tools/perf/ui/tui/setup.c
+++ b/tools/perf/ui/tui/setup.c
@@ -1,3 +1,4 @@
1#include <errno.h>
1#include <signal.h> 2#include <signal.h>
2#include <stdbool.h> 3#include <stdbool.h>
3#ifdef HAVE_BACKTRACE_SUPPORT 4#ifdef HAVE_BACKTRACE_SUPPORT
@@ -6,6 +7,7 @@
6 7
7#include "../../util/cache.h" 8#include "../../util/cache.h"
8#include "../../util/debug.h" 9#include "../../util/debug.h"
10#include "../../util/util.h"
9#include "../browser.h" 11#include "../browser.h"
10#include "../helpline.h" 12#include "../helpline.h"
11#include "../ui.h" 13#include "../ui.h"
diff --git a/tools/perf/ui/ui.h b/tools/perf/ui/ui.h
index ab88383f8be8..4b6fb6c7a542 100644
--- a/tools/perf/ui/ui.h
+++ b/tools/perf/ui/ui.h
@@ -26,4 +26,8 @@ static inline void ui__exit(bool wait_for_ok __maybe_unused) {}
26 26
27void ui__refresh_dimensions(bool force); 27void ui__refresh_dimensions(bool force);
28 28
29struct option;
30
31int stdio__config_color(const struct option *opt, const char *mode, int unset);
32
29#endif /* _PERF_UI_H_ */ 33#endif /* _PERF_UI_H_ */
diff --git a/tools/perf/util/Build b/tools/perf/util/Build
index da48fd843438..91c5f6e1af59 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -8,6 +8,7 @@ libperf-y += env.o
8libperf-y += event.o 8libperf-y += event.o
9libperf-y += evlist.o 9libperf-y += evlist.o
10libperf-y += evsel.o 10libperf-y += evsel.o
11libperf-y += evsel_fprintf.o
11libperf-y += find_bit.o 12libperf-y += find_bit.o
12libperf-y += kallsyms.o 13libperf-y += kallsyms.o
13libperf-y += levenshtein.o 14libperf-y += levenshtein.o
@@ -26,9 +27,9 @@ libperf-y += strlist.o
26libperf-y += strfilter.o 27libperf-y += strfilter.o
27libperf-y += top.o 28libperf-y += top.o
28libperf-y += usage.o 29libperf-y += usage.o
29libperf-y += wrapper.o
30libperf-y += dso.o 30libperf-y += dso.o
31libperf-y += symbol.o 31libperf-y += symbol.o
32libperf-y += symbol_fprintf.o
32libperf-y += color.o 33libperf-y += color.o
33libperf-y += header.o 34libperf-y += header.o
34libperf-y += callchain.o 35libperf-y += callchain.o
@@ -38,6 +39,7 @@ libperf-y += machine.o
38libperf-y += map.o 39libperf-y += map.o
39libperf-y += pstack.o 40libperf-y += pstack.o
40libperf-y += session.o 41libperf-y += session.o
42libperf-$(CONFIG_AUDIT) += syscalltbl.o
41libperf-y += ordered-events.o 43libperf-y += ordered-events.o
42libperf-y += comm.o 44libperf-y += comm.o
43libperf-y += thread.o 45libperf-y += thread.o
@@ -69,9 +71,9 @@ libperf-y += stat-shadow.o
69libperf-y += record.o 71libperf-y += record.o
70libperf-y += srcline.o 72libperf-y += srcline.o
71libperf-y += data.o 73libperf-y += data.o
72libperf-$(CONFIG_X86) += tsc.o 74libperf-y += tsc.o
73libperf-$(CONFIG_AUXTRACE) += tsc.o
74libperf-y += cloexec.o 75libperf-y += cloexec.o
76libperf-y += call-path.o
75libperf-y += thread-stack.o 77libperf-y += thread-stack.o
76libperf-$(CONFIG_AUXTRACE) += auxtrace.o 78libperf-$(CONFIG_AUXTRACE) += auxtrace.o
77libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/ 79libperf-$(CONFIG_AUXTRACE) += intel-pt-decoder/
@@ -82,6 +84,7 @@ libperf-y += parse-regs-options.o
82libperf-y += term.o 84libperf-y += term.o
83libperf-y += help-unknown-cmd.o 85libperf-y += help-unknown-cmd.o
84libperf-y += mem-events.o 86libperf-y += mem-events.o
87libperf-y += vsprintf.o
85 88
86libperf-$(CONFIG_LIBBPF) += bpf-loader.o 89libperf-$(CONFIG_LIBBPF) += bpf-loader.o
87libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 90libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -97,7 +100,10 @@ libperf-$(CONFIG_DWARF) += probe-finder.o
97libperf-$(CONFIG_DWARF) += dwarf-aux.o 100libperf-$(CONFIG_DWARF) += dwarf-aux.o
98 101
99libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 102libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
103libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
100libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 104libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
105libperf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o
106libperf-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o
101 107
102libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o 108libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
103 109
@@ -106,6 +112,7 @@ libperf-y += scripting-engines/
106libperf-$(CONFIG_ZLIB) += zlib.o 112libperf-$(CONFIG_ZLIB) += zlib.o
107libperf-$(CONFIG_LZMA) += lzma.o 113libperf-$(CONFIG_LZMA) += lzma.o
108libperf-y += demangle-java.o 114libperf-y += demangle-java.o
115libperf-y += demangle-rust.o
109 116
110ifdef CONFIG_JITDUMP 117ifdef CONFIG_JITDUMP
111libperf-$(CONFIG_LIBELF) += jitdump.o 118libperf-$(CONFIG_LIBELF) += jitdump.o
@@ -171,3 +178,7 @@ $(OUTPUT)util/libstring.o: ../lib/string.c FORCE
171$(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE 178$(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE
172 $(call rule_mkdir) 179 $(call rule_mkdir)
173 $(call if_changed_dep,cc_o_c) 180 $(call if_changed_dep,cc_o_c)
181
182$(OUTPUT)util/vsprintf.o: ../lib/vsprintf.c FORCE
183 $(call rule_mkdir)
184 $(call if_changed_dep,cc_o_c)
diff --git a/tools/perf/util/alias.c b/tools/perf/util/alias.c
index c0b43ee40d95..6455471d9cd1 100644
--- a/tools/perf/util/alias.c
+++ b/tools/perf/util/alias.c
@@ -1,4 +1,6 @@
1#include "cache.h" 1#include "cache.h"
2#include "util.h"
3#include "config.h"
2 4
3static const char *alias_key; 5static const char *alias_key;
4static char *alias_val; 6static char *alias_val;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index b795b6994144..4024d309bb00 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -354,9 +354,15 @@ static struct ins_ops nop_ops = {
354 .scnprintf = nop__scnprintf, 354 .scnprintf = nop__scnprintf,
355}; 355};
356 356
357/* 357static struct ins_ops ret_ops = {
358 * Must be sorted by name! 358 .scnprintf = ins__raw_scnprintf,
359 */ 359};
360
361bool ins__is_ret(const struct ins *ins)
362{
363 return ins->ops == &ret_ops;
364}
365
360static struct ins instructions[] = { 366static struct ins instructions[] = {
361 { .name = "add", .ops = &mov_ops, }, 367 { .name = "add", .ops = &mov_ops, },
362 { .name = "addl", .ops = &mov_ops, }, 368 { .name = "addl", .ops = &mov_ops, },
@@ -372,8 +378,8 @@ static struct ins instructions[] = {
372 { .name = "bgt", .ops = &jump_ops, }, 378 { .name = "bgt", .ops = &jump_ops, },
373 { .name = "bhi", .ops = &jump_ops, }, 379 { .name = "bhi", .ops = &jump_ops, },
374 { .name = "bl", .ops = &call_ops, }, 380 { .name = "bl", .ops = &call_ops, },
375 { .name = "blt", .ops = &jump_ops, },
376 { .name = "bls", .ops = &jump_ops, }, 381 { .name = "bls", .ops = &jump_ops, },
382 { .name = "blt", .ops = &jump_ops, },
377 { .name = "blx", .ops = &call_ops, }, 383 { .name = "blx", .ops = &call_ops, },
378 { .name = "bne", .ops = &jump_ops, }, 384 { .name = "bne", .ops = &jump_ops, },
379#endif 385#endif
@@ -447,20 +453,42 @@ static struct ins instructions[] = {
447 { .name = "xadd", .ops = &mov_ops, }, 453 { .name = "xadd", .ops = &mov_ops, },
448 { .name = "xbeginl", .ops = &jump_ops, }, 454 { .name = "xbeginl", .ops = &jump_ops, },
449 { .name = "xbeginq", .ops = &jump_ops, }, 455 { .name = "xbeginq", .ops = &jump_ops, },
456 { .name = "retq", .ops = &ret_ops, },
450}; 457};
451 458
452static int ins__cmp(const void *name, const void *insp) 459static int ins__key_cmp(const void *name, const void *insp)
453{ 460{
454 const struct ins *ins = insp; 461 const struct ins *ins = insp;
455 462
456 return strcmp(name, ins->name); 463 return strcmp(name, ins->name);
457} 464}
458 465
466static int ins__cmp(const void *a, const void *b)
467{
468 const struct ins *ia = a;
469 const struct ins *ib = b;
470
471 return strcmp(ia->name, ib->name);
472}
473
474static void ins__sort(void)
475{
476 const int nmemb = ARRAY_SIZE(instructions);
477
478 qsort(instructions, nmemb, sizeof(struct ins), ins__cmp);
479}
480
459static struct ins *ins__find(const char *name) 481static struct ins *ins__find(const char *name)
460{ 482{
461 const int nmemb = ARRAY_SIZE(instructions); 483 const int nmemb = ARRAY_SIZE(instructions);
484 static bool sorted;
485
486 if (!sorted) {
487 ins__sort();
488 sorted = true;
489 }
462 490
463 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__cmp); 491 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
464} 492}
465 493
466int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym) 494int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
@@ -1095,7 +1123,46 @@ static void delete_last_nop(struct symbol *sym)
1095 } 1123 }
1096} 1124}
1097 1125
1098int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) 1126int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
1127 int errnum, char *buf, size_t buflen)
1128{
1129 struct dso *dso = map->dso;
1130
1131 BUG_ON(buflen == 0);
1132
1133 if (errnum >= 0) {
1134 str_error_r(errnum, buf, buflen);
1135 return 0;
1136 }
1137
1138 switch (errnum) {
1139 case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
1140 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1141 char *build_id_msg = NULL;
1142
1143 if (dso->has_build_id) {
1144 build_id__sprintf(dso->build_id,
1145 sizeof(dso->build_id), bf + 15);
1146 build_id_msg = bf;
1147 }
1148 scnprintf(buf, buflen,
1149 "No vmlinux file%s\nwas found in the path.\n\n"
1150 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1151 "Please use:\n\n"
1152 " perf buildid-cache -vu vmlinux\n\n"
1153 "or:\n\n"
1154 " --vmlinux vmlinux\n", build_id_msg ?: "");
1155 }
1156 break;
1157 default:
1158 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1159 break;
1160 }
1161
1162 return 0;
1163}
1164
1165int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
1099{ 1166{
1100 struct dso *dso = map->dso; 1167 struct dso *dso = map->dso;
1101 char *filename = dso__build_id_filename(dso, NULL, 0); 1168 char *filename = dso__build_id_filename(dso, NULL, 0);
@@ -1106,23 +1173,21 @@ int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize)
1106 char symfs_filename[PATH_MAX]; 1173 char symfs_filename[PATH_MAX];
1107 struct kcore_extract kce; 1174 struct kcore_extract kce;
1108 bool delete_extract = false; 1175 bool delete_extract = false;
1176 int stdout_fd[2];
1109 int lineno = 0; 1177 int lineno = 0;
1110 int nline; 1178 int nline;
1179 pid_t pid;
1111 1180
1112 if (filename) 1181 if (filename)
1113 symbol__join_symfs(symfs_filename, filename); 1182 symbol__join_symfs(symfs_filename, filename);
1114 1183
1115 if (filename == NULL) { 1184 if (filename == NULL) {
1116 if (dso->has_build_id) { 1185 if (dso->has_build_id)
1117 pr_err("Can't annotate %s: not enough memory\n", 1186 return ENOMEM;
1118 sym->name);
1119 return -ENOMEM;
1120 }
1121 goto fallback;
1122 } else if (dso__is_kcore(dso)) {
1123 goto fallback; 1187 goto fallback;
1124 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 1188 } else if (dso__is_kcore(dso) ||
1125 strstr(command, "[kernel.kallsyms]") || 1189 readlink(symfs_filename, command, sizeof(command)) < 0 ||
1190 strstr(command, DSO__NAME_KALLSYMS) ||
1126 access(symfs_filename, R_OK)) { 1191 access(symfs_filename, R_OK)) {
1127 free(filename); 1192 free(filename);
1128fallback: 1193fallback:
@@ -1138,27 +1203,7 @@ fallback:
1138 1203
1139 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1204 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1140 !dso__is_kcore(dso)) { 1205 !dso__is_kcore(dso)) {
1141 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 1206 err = SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1142 char *build_id_msg = NULL;
1143
1144 if (dso->annotate_warned)
1145 goto out_free_filename;
1146
1147 if (dso->has_build_id) {
1148 build_id__sprintf(dso->build_id,
1149 sizeof(dso->build_id), bf + 15);
1150 build_id_msg = bf;
1151 }
1152 err = -ENOENT;
1153 dso->annotate_warned = 1;
1154 pr_err("Can't annotate %s:\n\n"
1155 "No vmlinux file%s\nwas found in the path.\n\n"
1156 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1157 "Please use:\n\n"
1158 " perf buildid-cache -vu vmlinux\n\n"
1159 "or:\n\n"
1160 " --vmlinux vmlinux\n",
1161 sym->name, build_id_msg ?: "");
1162 goto out_free_filename; 1207 goto out_free_filename;
1163 } 1208 }
1164 1209
@@ -1230,9 +1275,32 @@ fallback:
1230 1275
1231 pr_debug("Executing: %s\n", command); 1276 pr_debug("Executing: %s\n", command);
1232 1277
1233 file = popen(command, "r"); 1278 err = -1;
1279 if (pipe(stdout_fd) < 0) {
1280 pr_err("Failure creating the pipe to run %s\n", command);
1281 goto out_remove_tmp;
1282 }
1283
1284 pid = fork();
1285 if (pid < 0) {
1286 pr_err("Failure forking to run %s\n", command);
1287 goto out_close_stdout;
1288 }
1289
1290 if (pid == 0) {
1291 close(stdout_fd[0]);
1292 dup2(stdout_fd[1], 1);
1293 close(stdout_fd[1]);
1294 execl("/bin/sh", "sh", "-c", command, NULL);
1295 perror(command);
1296 exit(-1);
1297 }
1298
1299 close(stdout_fd[1]);
1300
1301 file = fdopen(stdout_fd[0], "r");
1234 if (!file) { 1302 if (!file) {
1235 pr_err("Failure running %s\n", command); 1303 pr_err("Failure creating FILE stream for %s\n", command);
1236 /* 1304 /*
1237 * If we were using debug info should retry with 1305 * If we were using debug info should retry with
1238 * original binary. 1306 * original binary.
@@ -1258,9 +1326,11 @@ fallback:
1258 if (dso__is_kcore(dso)) 1326 if (dso__is_kcore(dso))
1259 delete_last_nop(sym); 1327 delete_last_nop(sym);
1260 1328
1261 pclose(file); 1329 fclose(file);
1262 1330 err = 0;
1263out_remove_tmp: 1331out_remove_tmp:
1332 close(stdout_fd[0]);
1333
1264 if (dso__needs_decompress(dso)) 1334 if (dso__needs_decompress(dso))
1265 unlink(symfs_filename); 1335 unlink(symfs_filename);
1266out_free_filename: 1336out_free_filename:
@@ -1269,6 +1339,10 @@ out_free_filename:
1269 if (free_filename) 1339 if (free_filename)
1270 free(filename); 1340 free(filename);
1271 return err; 1341 return err;
1342
1343out_close_stdout:
1344 close(stdout_fd[1]);
1345 goto out_remove_tmp;
1272} 1346}
1273 1347
1274static void insert_source_line(struct rb_root *root, struct source_line *src_line) 1348static void insert_source_line(struct rb_root *root, struct source_line *src_line)
@@ -1494,13 +1568,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1494 const char *d_filename; 1568 const char *d_filename;
1495 const char *evsel_name = perf_evsel__name(evsel); 1569 const char *evsel_name = perf_evsel__name(evsel);
1496 struct annotation *notes = symbol__annotation(sym); 1570 struct annotation *notes = symbol__annotation(sym);
1571 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
1497 struct disasm_line *pos, *queue = NULL; 1572 struct disasm_line *pos, *queue = NULL;
1498 u64 start = map__rip_2objdump(map, sym->start); 1573 u64 start = map__rip_2objdump(map, sym->start);
1499 int printed = 2, queue_len = 0; 1574 int printed = 2, queue_len = 0;
1500 int more = 0; 1575 int more = 0;
1501 u64 len; 1576 u64 len;
1502 int width = 8; 1577 int width = 8;
1503 int namelen, evsel_name_len, graph_dotted_len; 1578 int graph_dotted_len;
1504 1579
1505 filename = strdup(dso->long_name); 1580 filename = strdup(dso->long_name);
1506 if (!filename) 1581 if (!filename)
@@ -1512,17 +1587,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1512 d_filename = basename(filename); 1587 d_filename = basename(filename);
1513 1588
1514 len = symbol__size(sym); 1589 len = symbol__size(sym);
1515 namelen = strlen(d_filename);
1516 evsel_name_len = strlen(evsel_name);
1517 1590
1518 if (perf_evsel__is_group_event(evsel)) 1591 if (perf_evsel__is_group_event(evsel))
1519 width *= evsel->nr_members; 1592 width *= evsel->nr_members;
1520 1593
1521 printf(" %-*.*s| Source code & Disassembly of %s for %s\n", 1594 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1522 width, width, "Percent", d_filename, evsel_name); 1595 width, width, "Percent", d_filename, evsel_name, h->sum);
1523 1596
1524 graph_dotted_len = width + namelen + evsel_name_len; 1597 printf("%-*.*s----\n",
1525 printf("-%-*.*s-----------------------------------------\n",
1526 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1598 graph_dotted_len, graph_dotted_len, graph_dotted_line);
1527 1599
1528 if (verbose) 1600 if (verbose)
@@ -1637,7 +1709,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1637 struct rb_root source_line = RB_ROOT; 1709 struct rb_root source_line = RB_ROOT;
1638 u64 len; 1710 u64 len;
1639 1711
1640 if (symbol__annotate(sym, map, 0) < 0) 1712 if (symbol__disassemble(sym, map, 0) < 0)
1641 return -1; 1713 return -1;
1642 1714
1643 len = symbol__size(sym); 1715 len = symbol__size(sym);
@@ -1658,12 +1730,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1658 return 0; 1730 return 0;
1659} 1731}
1660 1732
1661int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1662{
1663 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
1664}
1665
1666bool ui__has_annotation(void) 1733bool ui__has_annotation(void)
1667{ 1734{
1668 return use_browser == 1 && sort__has_sym; 1735 return use_browser == 1 && perf_hpp_list.sym;
1669} 1736}
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 9241f8c2b7e1..f67ccb027561 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -48,6 +48,7 @@ struct ins {
48 48
49bool ins__is_jump(const struct ins *ins); 49bool ins__is_jump(const struct ins *ins);
50bool ins__is_call(const struct ins *ins); 50bool ins__is_call(const struct ins *ins);
51bool ins__is_ret(const struct ins *ins);
51int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops); 52int ins__scnprintf(struct ins *ins, char *bf, size_t size, struct ins_operands *ops);
52 53
53struct annotation; 54struct annotation;
@@ -154,9 +155,27 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
154int symbol__alloc_hist(struct symbol *sym); 155int symbol__alloc_hist(struct symbol *sym);
155void symbol__annotate_zero_histograms(struct symbol *sym); 156void symbol__annotate_zero_histograms(struct symbol *sym);
156 157
157int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 158int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize);
158 159
159int hist_entry__annotate(struct hist_entry *he, size_t privsize); 160enum symbol_disassemble_errno {
161 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
162
163 /*
164 * Choose an arbitrary negative big number not to clash with standard
165 * errno since SUS requires the errno has distinct positive values.
166 * See 'Issue 6' in the link below.
167 *
168 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
169 */
170 __SYMBOL_ANNOTATE_ERRNO__START = -10000,
171
172 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
173
174 __SYMBOL_ANNOTATE_ERRNO__END,
175};
176
177int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
178 int errnum, char *buf, size_t buflen);
160 179
161int symbol__annotate_init(struct map *map, struct symbol *sym); 180int symbol__annotate_init(struct map *map, struct symbol *sym);
162int symbol__annotate_printf(struct symbol *sym, struct map *map, 181int symbol__annotate_printf(struct symbol *sym, struct map *map,
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index ec164fe70718..c9169011e55e 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -940,6 +940,7 @@ void itrace_synth_opts__set_default(struct itrace_synth_opts *synth_opts)
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,
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;
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 57ff31ecb8e4..ac5f0d7167e6 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -63,11 +63,13 @@ enum itrace_period_type {
63 * @calls: limit branch samples to calls (can be combined with @returns) 63 * @calls: limit branch samples to calls (can be combined with @returns)
64 * @returns: limit branch samples to returns (can be combined with @calls) 64 * @returns: limit branch samples to returns (can be combined with @calls)
65 * @callchain: add callchain to 'instructions' events 65 * @callchain: add callchain to 'instructions' events
66 * @thread_stack: feed branches to the thread_stack
66 * @last_branch: add branch context to 'instruction' events 67 * @last_branch: add branch context to 'instruction' events
67 * @callchain_sz: maximum callchain size 68 * @callchain_sz: maximum callchain size
68 * @last_branch_sz: branch context size 69 * @last_branch_sz: branch context size
69 * @period: 'instructions' events period 70 * @period: 'instructions' events period
70 * @period_type: 'instructions' events period type 71 * @period_type: 'instructions' events period type
72 * @initial_skip: skip N events at the beginning.
71 */ 73 */
72struct itrace_synth_opts { 74struct itrace_synth_opts {
73 bool set; 75 bool set;
@@ -81,11 +83,13 @@ struct itrace_synth_opts {
81 bool calls; 83 bool calls;
82 bool returns; 84 bool returns;
83 bool callchain; 85 bool callchain;
86 bool thread_stack;
84 bool last_branch; 87 bool last_branch;
85 unsigned int callchain_sz; 88 unsigned int callchain_sz;
86 unsigned int last_branch_sz; 89 unsigned int last_branch_sz;
87 unsigned long long period; 90 unsigned long long period;
88 enum itrace_period_type period_type; 91 enum itrace_period_type period_type;
92 unsigned long initial_skip;
89}; 93};
90 94
91/** 95/**
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 0967ce601931..1f12e4e40006 100644
--- a/tools/perf/util/bpf-loader.c
+++ b/tools/perf/util/bpf-loader.c
@@ -37,6 +37,9 @@ DEFINE_PRINT_FN(info, 1)
37DEFINE_PRINT_FN(debug, 1) 37DEFINE_PRINT_FN(debug, 1)
38 38
39struct bpf_prog_priv { 39struct bpf_prog_priv {
40 bool is_tp;
41 char *sys_name;
42 char *evt_name;
40 struct perf_probe_event pev; 43 struct perf_probe_event pev;
41 bool need_prologue; 44 bool need_prologue;
42 struct bpf_insn *insns_buf; 45 struct bpf_insn *insns_buf;
@@ -118,6 +121,8 @@ clear_prog_priv(struct bpf_program *prog __maybe_unused,
118 cleanup_perf_probe_events(&priv->pev, 1); 121 cleanup_perf_probe_events(&priv->pev, 1);
119 zfree(&priv->insns_buf); 122 zfree(&priv->insns_buf);
120 zfree(&priv->type_mapping); 123 zfree(&priv->type_mapping);
124 zfree(&priv->sys_name);
125 zfree(&priv->evt_name);
121 free(priv); 126 free(priv);
122} 127}
123 128
@@ -269,7 +274,8 @@ nextline:
269} 274}
270 275
271static int 276static int
272parse_prog_config(const char *config_str, struct perf_probe_event *pev) 277parse_prog_config(const char *config_str, const char **p_main_str,
278 bool *is_tp, struct perf_probe_event *pev)
273{ 279{
274 int err; 280 int err;
275 const char *main_str = parse_prog_config_kvpair(config_str, pev); 281 const char *main_str = parse_prog_config_kvpair(config_str, pev);
@@ -277,6 +283,22 @@ parse_prog_config(const char *config_str, struct perf_probe_event *pev)
277 if (IS_ERR(main_str)) 283 if (IS_ERR(main_str))
278 return PTR_ERR(main_str); 284 return PTR_ERR(main_str);
279 285
286 *p_main_str = main_str;
287 if (!strchr(main_str, '=')) {
288 /* Is a tracepoint event? */
289 const char *s = strchr(main_str, ':');
290
291 if (!s) {
292 pr_debug("bpf: '%s' is not a valid tracepoint\n",
293 config_str);
294 return -BPF_LOADER_ERRNO__CONFIG;
295 }
296
297 *is_tp = true;
298 return 0;
299 }
300
301 *is_tp = false;
280 err = parse_perf_probe_command(main_str, pev); 302 err = parse_perf_probe_command(main_str, pev);
281 if (err < 0) { 303 if (err < 0) {
282 pr_debug("bpf: '%s' is not a valid config string\n", 304 pr_debug("bpf: '%s' is not a valid config string\n",
@@ -292,7 +314,8 @@ config_bpf_program(struct bpf_program *prog)
292{ 314{
293 struct perf_probe_event *pev = NULL; 315 struct perf_probe_event *pev = NULL;
294 struct bpf_prog_priv *priv = NULL; 316 struct bpf_prog_priv *priv = NULL;
295 const char *config_str; 317 const char *config_str, *main_str;
318 bool is_tp = false;
296 int err; 319 int err;
297 320
298 /* Initialize per-program probing setting */ 321 /* Initialize per-program probing setting */
@@ -313,10 +336,19 @@ config_bpf_program(struct bpf_program *prog)
313 pev = &priv->pev; 336 pev = &priv->pev;
314 337
315 pr_debug("bpf: config program '%s'\n", config_str); 338 pr_debug("bpf: config program '%s'\n", config_str);
316 err = parse_prog_config(config_str, pev); 339 err = parse_prog_config(config_str, &main_str, &is_tp, pev);
317 if (err) 340 if (err)
318 goto errout; 341 goto errout;
319 342
343 if (is_tp) {
344 char *s = strchr(main_str, ':');
345
346 priv->is_tp = true;
347 priv->sys_name = strndup(main_str, s - main_str);
348 priv->evt_name = strdup(s + 1);
349 goto set_priv;
350 }
351
320 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) { 352 if (pev->group && strcmp(pev->group, PERF_BPF_PROBE_GROUP)) {
321 pr_debug("bpf: '%s': group for event is set and not '%s'.\n", 353 pr_debug("bpf: '%s': group for event is set and not '%s'.\n",
322 config_str, PERF_BPF_PROBE_GROUP); 354 config_str, PERF_BPF_PROBE_GROUP);
@@ -339,7 +371,8 @@ config_bpf_program(struct bpf_program *prog)
339 } 371 }
340 pr_debug("bpf: config '%s' is ok\n", config_str); 372 pr_debug("bpf: config '%s' is ok\n", config_str);
341 373
342 err = bpf_program__set_private(prog, priv, clear_prog_priv); 374set_priv:
375 err = bpf_program__set_priv(prog, priv, clear_prog_priv);
343 if (err) { 376 if (err) {
344 pr_debug("Failed to set priv for program '%s'\n", config_str); 377 pr_debug("Failed to set priv for program '%s'\n", config_str);
345 goto errout; 378 goto errout;
@@ -380,15 +413,14 @@ preproc_gen_prologue(struct bpf_program *prog, int n,
380 struct bpf_insn *orig_insns, int orig_insns_cnt, 413 struct bpf_insn *orig_insns, int orig_insns_cnt,
381 struct bpf_prog_prep_result *res) 414 struct bpf_prog_prep_result *res)
382{ 415{
416 struct bpf_prog_priv *priv = bpf_program__priv(prog);
383 struct probe_trace_event *tev; 417 struct probe_trace_event *tev;
384 struct perf_probe_event *pev; 418 struct perf_probe_event *pev;
385 struct bpf_prog_priv *priv;
386 struct bpf_insn *buf; 419 struct bpf_insn *buf;
387 size_t prologue_cnt = 0; 420 size_t prologue_cnt = 0;
388 int i, err; 421 int i, err;
389 422
390 err = bpf_program__get_private(prog, (void **)&priv); 423 if (IS_ERR(priv) || !priv || priv->is_tp)
391 if (err || !priv)
392 goto errout; 424 goto errout;
393 425
394 pev = &priv->pev; 426 pev = &priv->pev;
@@ -535,17 +567,21 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping,
535 567
536static int hook_load_preprocessor(struct bpf_program *prog) 568static int hook_load_preprocessor(struct bpf_program *prog)
537{ 569{
570 struct bpf_prog_priv *priv = bpf_program__priv(prog);
538 struct perf_probe_event *pev; 571 struct perf_probe_event *pev;
539 struct bpf_prog_priv *priv;
540 bool need_prologue = false; 572 bool need_prologue = false;
541 int err, i; 573 int err, i;
542 574
543 err = bpf_program__get_private(prog, (void **)&priv); 575 if (IS_ERR(priv) || !priv) {
544 if (err || !priv) {
545 pr_debug("Internal error when hook preprocessor\n"); 576 pr_debug("Internal error when hook preprocessor\n");
546 return -BPF_LOADER_ERRNO__INTERNAL; 577 return -BPF_LOADER_ERRNO__INTERNAL;
547 } 578 }
548 579
580 if (priv->is_tp) {
581 priv->need_prologue = false;
582 return 0;
583 }
584
549 pev = &priv->pev; 585 pev = &priv->pev;
550 for (i = 0; i < pev->ntevs; i++) { 586 for (i = 0; i < pev->ntevs; i++) {
551 struct probe_trace_event *tev = &pev->tevs[i]; 587 struct probe_trace_event *tev = &pev->tevs[i];
@@ -607,9 +643,18 @@ int bpf__probe(struct bpf_object *obj)
607 if (err) 643 if (err)
608 goto out; 644 goto out;
609 645
610 err = bpf_program__get_private(prog, (void **)&priv); 646 priv = bpf_program__priv(prog);
611 if (err || !priv) 647 if (IS_ERR(priv) || !priv) {
648 err = PTR_ERR(priv);
612 goto out; 649 goto out;
650 }
651
652 if (priv->is_tp) {
653 bpf_program__set_tracepoint(prog);
654 continue;
655 }
656
657 bpf_program__set_kprobe(prog);
613 pev = &priv->pev; 658 pev = &priv->pev;
614 659
615 err = convert_perf_probe_events(pev, 1); 660 err = convert_perf_probe_events(pev, 1);
@@ -645,13 +690,12 @@ int bpf__unprobe(struct bpf_object *obj)
645{ 690{
646 int err, ret = 0; 691 int err, ret = 0;
647 struct bpf_program *prog; 692 struct bpf_program *prog;
648 struct bpf_prog_priv *priv;
649 693
650 bpf_object__for_each_program(prog, obj) { 694 bpf_object__for_each_program(prog, obj) {
695 struct bpf_prog_priv *priv = bpf_program__priv(prog);
651 int i; 696 int i;
652 697
653 err = bpf_program__get_private(prog, (void **)&priv); 698 if (IS_ERR(priv) || !priv || priv->is_tp)
654 if (err || !priv)
655 continue; 699 continue;
656 700
657 for (i = 0; i < priv->pev.ntevs; i++) { 701 for (i = 0; i < priv->pev.ntevs; i++) {
@@ -694,26 +738,34 @@ int bpf__load(struct bpf_object *obj)
694 return 0; 738 return 0;
695} 739}
696 740
697int bpf__foreach_tev(struct bpf_object *obj, 741int bpf__foreach_event(struct bpf_object *obj,
698 bpf_prog_iter_callback_t func, 742 bpf_prog_iter_callback_t func,
699 void *arg) 743 void *arg)
700{ 744{
701 struct bpf_program *prog; 745 struct bpf_program *prog;
702 int err; 746 int err;
703 747
704 bpf_object__for_each_program(prog, obj) { 748 bpf_object__for_each_program(prog, obj) {
749 struct bpf_prog_priv *priv = bpf_program__priv(prog);
705 struct probe_trace_event *tev; 750 struct probe_trace_event *tev;
706 struct perf_probe_event *pev; 751 struct perf_probe_event *pev;
707 struct bpf_prog_priv *priv;
708 int i, fd; 752 int i, fd;
709 753
710 err = bpf_program__get_private(prog, 754 if (IS_ERR(priv) || !priv) {
711 (void **)&priv);
712 if (err || !priv) {
713 pr_debug("bpf: failed to get private field\n"); 755 pr_debug("bpf: failed to get private field\n");
714 return -BPF_LOADER_ERRNO__INTERNAL; 756 return -BPF_LOADER_ERRNO__INTERNAL;
715 } 757 }
716 758
759 if (priv->is_tp) {
760 fd = bpf_program__fd(prog);
761 err = (*func)(priv->sys_name, priv->evt_name, fd, arg);
762 if (err) {
763 pr_debug("bpf: tracepoint call back failed, stop iterate\n");
764 return err;
765 }
766 continue;
767 }
768
717 pev = &priv->pev; 769 pev = &priv->pev;
718 for (i = 0; i < pev->ntevs; i++) { 770 for (i = 0; i < pev->ntevs; i++) {
719 tev = &pev->tevs[i]; 771 tev = &pev->tevs[i];
@@ -731,7 +783,7 @@ int bpf__foreach_tev(struct bpf_object *obj,
731 return fd; 783 return fd;
732 } 784 }
733 785
734 err = (*func)(tev, fd, arg); 786 err = (*func)(tev->group, tev->event, fd, arg);
735 if (err) { 787 if (err) {
736 pr_debug("bpf: call back failed, stop iterate\n"); 788 pr_debug("bpf: call back failed, stop iterate\n");
737 return err; 789 return err;
@@ -842,18 +894,67 @@ bpf_map_op__new(struct parse_events_term *term)
842 return op; 894 return op;
843} 895}
844 896
897static struct bpf_map_op *
898bpf_map_op__clone(struct bpf_map_op *op)
899{
900 struct bpf_map_op *newop;
901
902 newop = memdup(op, sizeof(*op));
903 if (!newop) {
904 pr_debug("Failed to alloc bpf_map_op\n");
905 return NULL;
906 }
907
908 INIT_LIST_HEAD(&newop->list);
909 if (op->key_type == BPF_MAP_KEY_RANGES) {
910 size_t memsz = op->k.array.nr_ranges *
911 sizeof(op->k.array.ranges[0]);
912
913 newop->k.array.ranges = memdup(op->k.array.ranges, memsz);
914 if (!newop->k.array.ranges) {
915 pr_debug("Failed to alloc indices for map\n");
916 free(newop);
917 return NULL;
918 }
919 }
920
921 return newop;
922}
923
924static struct bpf_map_priv *
925bpf_map_priv__clone(struct bpf_map_priv *priv)
926{
927 struct bpf_map_priv *newpriv;
928 struct bpf_map_op *pos, *newop;
929
930 newpriv = zalloc(sizeof(*newpriv));
931 if (!newpriv) {
932 pr_debug("No enough memory to alloc map private\n");
933 return NULL;
934 }
935 INIT_LIST_HEAD(&newpriv->ops_list);
936
937 list_for_each_entry(pos, &priv->ops_list, list) {
938 newop = bpf_map_op__clone(pos);
939 if (!newop) {
940 bpf_map_priv__purge(newpriv);
941 return NULL;
942 }
943 list_add_tail(&newop->list, &newpriv->ops_list);
944 }
945
946 return newpriv;
947}
948
845static int 949static int
846bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op) 950bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
847{ 951{
848 struct bpf_map_priv *priv; 952 const char *map_name = bpf_map__name(map);
849 const char *map_name; 953 struct bpf_map_priv *priv = bpf_map__priv(map);
850 int err;
851 954
852 map_name = bpf_map__get_name(map); 955 if (IS_ERR(priv)) {
853 err = bpf_map__get_private(map, (void **)&priv);
854 if (err) {
855 pr_debug("Failed to get private from map %s\n", map_name); 956 pr_debug("Failed to get private from map %s\n", map_name);
856 return err; 957 return PTR_ERR(priv);
857 } 958 }
858 959
859 if (!priv) { 960 if (!priv) {
@@ -864,7 +965,7 @@ bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
864 } 965 }
865 INIT_LIST_HEAD(&priv->ops_list); 966 INIT_LIST_HEAD(&priv->ops_list);
866 967
867 if (bpf_map__set_private(map, priv, bpf_map_priv__clear)) { 968 if (bpf_map__set_priv(map, priv, bpf_map_priv__clear)) {
868 free(priv); 969 free(priv);
869 return -BPF_LOADER_ERRNO__INTERNAL; 970 return -BPF_LOADER_ERRNO__INTERNAL;
870 } 971 }
@@ -896,30 +997,26 @@ static int
896__bpf_map__config_value(struct bpf_map *map, 997__bpf_map__config_value(struct bpf_map *map,
897 struct parse_events_term *term) 998 struct parse_events_term *term)
898{ 999{
899 struct bpf_map_def def;
900 struct bpf_map_op *op; 1000 struct bpf_map_op *op;
901 const char *map_name; 1001 const char *map_name = bpf_map__name(map);
902 int err; 1002 const struct bpf_map_def *def = bpf_map__def(map);
903 1003
904 map_name = bpf_map__get_name(map); 1004 if (IS_ERR(def)) {
905
906 err = bpf_map__get_def(map, &def);
907 if (err) {
908 pr_debug("Unable to get map definition from '%s'\n", 1005 pr_debug("Unable to get map definition from '%s'\n",
909 map_name); 1006 map_name);
910 return -BPF_LOADER_ERRNO__INTERNAL; 1007 return -BPF_LOADER_ERRNO__INTERNAL;
911 } 1008 }
912 1009
913 if (def.type != BPF_MAP_TYPE_ARRAY) { 1010 if (def->type != BPF_MAP_TYPE_ARRAY) {
914 pr_debug("Map %s type is not BPF_MAP_TYPE_ARRAY\n", 1011 pr_debug("Map %s type is not BPF_MAP_TYPE_ARRAY\n",
915 map_name); 1012 map_name);
916 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; 1013 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
917 } 1014 }
918 if (def.key_size < sizeof(unsigned int)) { 1015 if (def->key_size < sizeof(unsigned int)) {
919 pr_debug("Map %s has incorrect key size\n", map_name); 1016 pr_debug("Map %s has incorrect key size\n", map_name);
920 return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE; 1017 return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE;
921 } 1018 }
922 switch (def.value_size) { 1019 switch (def->value_size) {
923 case 1: 1020 case 1:
924 case 2: 1021 case 2:
925 case 4: 1022 case 4:
@@ -962,12 +1059,10 @@ __bpf_map__config_event(struct bpf_map *map,
962 struct perf_evlist *evlist) 1059 struct perf_evlist *evlist)
963{ 1060{
964 struct perf_evsel *evsel; 1061 struct perf_evsel *evsel;
965 struct bpf_map_def def; 1062 const struct bpf_map_def *def;
966 struct bpf_map_op *op; 1063 struct bpf_map_op *op;
967 const char *map_name; 1064 const char *map_name = bpf_map__name(map);
968 int err;
969 1065
970 map_name = bpf_map__get_name(map);
971 evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str); 1066 evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str);
972 if (!evsel) { 1067 if (!evsel) {
973 pr_debug("Event (for '%s') '%s' doesn't exist\n", 1068 pr_debug("Event (for '%s') '%s' doesn't exist\n",
@@ -975,18 +1070,18 @@ __bpf_map__config_event(struct bpf_map *map,
975 return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT; 1070 return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT;
976 } 1071 }
977 1072
978 err = bpf_map__get_def(map, &def); 1073 def = bpf_map__def(map);
979 if (err) { 1074 if (IS_ERR(def)) {
980 pr_debug("Unable to get map definition from '%s'\n", 1075 pr_debug("Unable to get map definition from '%s'\n",
981 map_name); 1076 map_name);
982 return err; 1077 return PTR_ERR(def);
983 } 1078 }
984 1079
985 /* 1080 /*
986 * No need to check key_size and value_size: 1081 * No need to check key_size and value_size:
987 * kernel has already checked them. 1082 * kernel has already checked them.
988 */ 1083 */
989 if (def.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) { 1084 if (def->type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
990 pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n", 1085 pr_debug("Map %s type is not BPF_MAP_TYPE_PERF_EVENT_ARRAY\n",
991 map_name); 1086 map_name);
992 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; 1087 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
@@ -1035,9 +1130,8 @@ config_map_indices_range_check(struct parse_events_term *term,
1035 const char *map_name) 1130 const char *map_name)
1036{ 1131{
1037 struct parse_events_array *array = &term->array; 1132 struct parse_events_array *array = &term->array;
1038 struct bpf_map_def def; 1133 const struct bpf_map_def *def;
1039 unsigned int i; 1134 unsigned int i;
1040 int err;
1041 1135
1042 if (!array->nr_ranges) 1136 if (!array->nr_ranges)
1043 return 0; 1137 return 0;
@@ -1047,8 +1141,8 @@ config_map_indices_range_check(struct parse_events_term *term,
1047 return -BPF_LOADER_ERRNO__INTERNAL; 1141 return -BPF_LOADER_ERRNO__INTERNAL;
1048 } 1142 }
1049 1143
1050 err = bpf_map__get_def(map, &def); 1144 def = bpf_map__def(map);
1051 if (err) { 1145 if (IS_ERR(def)) {
1052 pr_debug("ERROR: Unable to get map definition from '%s'\n", 1146 pr_debug("ERROR: Unable to get map definition from '%s'\n",
1053 map_name); 1147 map_name);
1054 return -BPF_LOADER_ERRNO__INTERNAL; 1148 return -BPF_LOADER_ERRNO__INTERNAL;
@@ -1059,7 +1153,7 @@ config_map_indices_range_check(struct parse_events_term *term,
1059 size_t length = array->ranges[i].length; 1153 size_t length = array->ranges[i].length;
1060 unsigned int idx = start + length - 1; 1154 unsigned int idx = start + length - 1;
1061 1155
1062 if (idx >= def.max_entries) { 1156 if (idx >= def->max_entries) {
1063 pr_debug("ERROR: index %d too large\n", idx); 1157 pr_debug("ERROR: index %d too large\n", idx);
1064 return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG; 1158 return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG;
1065 } 1159 }
@@ -1095,7 +1189,7 @@ bpf__obj_config_map(struct bpf_object *obj,
1095 goto out; 1189 goto out;
1096 } 1190 }
1097 1191
1098 map = bpf_object__get_map_by_name(obj, map_name); 1192 map = bpf_object__find_map_by_name(obj, map_name);
1099 if (!map) { 1193 if (!map) {
1100 pr_debug("ERROR: Map %s doesn't exist\n", map_name); 1194 pr_debug("ERROR: Map %s doesn't exist\n", map_name);
1101 err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST; 1195 err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST;
@@ -1152,14 +1246,14 @@ out:
1152} 1246}
1153 1247
1154typedef int (*map_config_func_t)(const char *name, int map_fd, 1248typedef int (*map_config_func_t)(const char *name, int map_fd,
1155 struct bpf_map_def *pdef, 1249 const struct bpf_map_def *pdef,
1156 struct bpf_map_op *op, 1250 struct bpf_map_op *op,
1157 void *pkey, void *arg); 1251 void *pkey, void *arg);
1158 1252
1159static int 1253static int
1160foreach_key_array_all(map_config_func_t func, 1254foreach_key_array_all(map_config_func_t func,
1161 void *arg, const char *name, 1255 void *arg, const char *name,
1162 int map_fd, struct bpf_map_def *pdef, 1256 int map_fd, const struct bpf_map_def *pdef,
1163 struct bpf_map_op *op) 1257 struct bpf_map_op *op)
1164{ 1258{
1165 unsigned int i; 1259 unsigned int i;
@@ -1179,7 +1273,7 @@ foreach_key_array_all(map_config_func_t func,
1179static int 1273static int
1180foreach_key_array_ranges(map_config_func_t func, void *arg, 1274foreach_key_array_ranges(map_config_func_t func, void *arg,
1181 const char *name, int map_fd, 1275 const char *name, int map_fd,
1182 struct bpf_map_def *pdef, 1276 const struct bpf_map_def *pdef,
1183 struct bpf_map_op *op) 1277 struct bpf_map_op *op)
1184{ 1278{
1185 unsigned int i, j; 1279 unsigned int i, j;
@@ -1209,15 +1303,12 @@ bpf_map_config_foreach_key(struct bpf_map *map,
1209 void *arg) 1303 void *arg)
1210{ 1304{
1211 int err, map_fd; 1305 int err, map_fd;
1212 const char *name;
1213 struct bpf_map_op *op; 1306 struct bpf_map_op *op;
1214 struct bpf_map_def def; 1307 const struct bpf_map_def *def;
1215 struct bpf_map_priv *priv; 1308 const char *name = bpf_map__name(map);
1309 struct bpf_map_priv *priv = bpf_map__priv(map);
1216 1310
1217 name = bpf_map__get_name(map); 1311 if (IS_ERR(priv)) {
1218
1219 err = bpf_map__get_private(map, (void **)&priv);
1220 if (err) {
1221 pr_debug("ERROR: failed to get private from map %s\n", name); 1312 pr_debug("ERROR: failed to get private from map %s\n", name);
1222 return -BPF_LOADER_ERRNO__INTERNAL; 1313 return -BPF_LOADER_ERRNO__INTERNAL;
1223 } 1314 }
@@ -1226,29 +1317,29 @@ bpf_map_config_foreach_key(struct bpf_map *map,
1226 return 0; 1317 return 0;
1227 } 1318 }
1228 1319
1229 err = bpf_map__get_def(map, &def); 1320 def = bpf_map__def(map);
1230 if (err) { 1321 if (IS_ERR(def)) {
1231 pr_debug("ERROR: failed to get definition from map %s\n", name); 1322 pr_debug("ERROR: failed to get definition from map %s\n", name);
1232 return -BPF_LOADER_ERRNO__INTERNAL; 1323 return -BPF_LOADER_ERRNO__INTERNAL;
1233 } 1324 }
1234 map_fd = bpf_map__get_fd(map); 1325 map_fd = bpf_map__fd(map);
1235 if (map_fd < 0) { 1326 if (map_fd < 0) {
1236 pr_debug("ERROR: failed to get fd from map %s\n", name); 1327 pr_debug("ERROR: failed to get fd from map %s\n", name);
1237 return map_fd; 1328 return map_fd;
1238 } 1329 }
1239 1330
1240 list_for_each_entry(op, &priv->ops_list, list) { 1331 list_for_each_entry(op, &priv->ops_list, list) {
1241 switch (def.type) { 1332 switch (def->type) {
1242 case BPF_MAP_TYPE_ARRAY: 1333 case BPF_MAP_TYPE_ARRAY:
1243 case BPF_MAP_TYPE_PERF_EVENT_ARRAY: 1334 case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
1244 switch (op->key_type) { 1335 switch (op->key_type) {
1245 case BPF_MAP_KEY_ALL: 1336 case BPF_MAP_KEY_ALL:
1246 err = foreach_key_array_all(func, arg, name, 1337 err = foreach_key_array_all(func, arg, name,
1247 map_fd, &def, op); 1338 map_fd, def, op);
1248 break; 1339 break;
1249 case BPF_MAP_KEY_RANGES: 1340 case BPF_MAP_KEY_RANGES:
1250 err = foreach_key_array_ranges(func, arg, name, 1341 err = foreach_key_array_ranges(func, arg, name,
1251 map_fd, &def, 1342 map_fd, def,
1252 op); 1343 op);
1253 break; 1344 break;
1254 default: 1345 default:
@@ -1358,7 +1449,7 @@ apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
1358 1449
1359static int 1450static int
1360apply_obj_config_map_for_key(const char *name, int map_fd, 1451apply_obj_config_map_for_key(const char *name, int map_fd,
1361 struct bpf_map_def *pdef __maybe_unused, 1452 const struct bpf_map_def *pdef,
1362 struct bpf_map_op *op, 1453 struct bpf_map_op *op,
1363 void *pkey, void *arg __maybe_unused) 1454 void *pkey, void *arg __maybe_unused)
1364{ 1455{
@@ -1417,6 +1508,87 @@ int bpf__apply_obj_config(void)
1417 return 0; 1508 return 0;
1418} 1509}
1419 1510
1511#define bpf__for_each_map(pos, obj, objtmp) \
1512 bpf_object__for_each_safe(obj, objtmp) \
1513 bpf_map__for_each(pos, obj)
1514
1515#define bpf__for_each_stdout_map(pos, obj, objtmp) \
1516 bpf__for_each_map(pos, obj, objtmp) \
1517 if (bpf_map__name(pos) && \
1518 (strcmp("__bpf_stdout__", \
1519 bpf_map__name(pos)) == 0))
1520
1521int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
1522{
1523 struct bpf_map_priv *tmpl_priv = NULL;
1524 struct bpf_object *obj, *tmp;
1525 struct perf_evsel *evsel = NULL;
1526 struct bpf_map *map;
1527 int err;
1528 bool need_init = false;
1529
1530 bpf__for_each_stdout_map(map, obj, tmp) {
1531 struct bpf_map_priv *priv = bpf_map__priv(map);
1532
1533 if (IS_ERR(priv))
1534 return -BPF_LOADER_ERRNO__INTERNAL;
1535
1536 /*
1537 * No need to check map type: type should have been
1538 * verified by kernel.
1539 */
1540 if (!need_init && !priv)
1541 need_init = !priv;
1542 if (!tmpl_priv && priv)
1543 tmpl_priv = priv;
1544 }
1545
1546 if (!need_init)
1547 return 0;
1548
1549 if (!tmpl_priv) {
1550 err = parse_events(evlist, "bpf-output/no-inherit=1,name=__bpf_stdout__/",
1551 NULL);
1552 if (err) {
1553 pr_debug("ERROR: failed to create bpf-output event\n");
1554 return -err;
1555 }
1556
1557 evsel = perf_evlist__last(evlist);
1558 }
1559
1560 bpf__for_each_stdout_map(map, obj, tmp) {
1561 struct bpf_map_priv *priv = bpf_map__priv(map);
1562
1563 if (IS_ERR(priv))
1564 return -BPF_LOADER_ERRNO__INTERNAL;
1565 if (priv)
1566 continue;
1567
1568 if (tmpl_priv) {
1569 priv = bpf_map_priv__clone(tmpl_priv);
1570 if (!priv)
1571 return -ENOMEM;
1572
1573 err = bpf_map__set_priv(map, priv, bpf_map_priv__clear);
1574 if (err) {
1575 bpf_map_priv__clear(map, priv);
1576 return err;
1577 }
1578 } else if (evsel) {
1579 struct bpf_map_op *op;
1580
1581 op = bpf_map__add_newop(map, NULL);
1582 if (IS_ERR(op))
1583 return PTR_ERR(op);
1584 op->op_type = BPF_MAP_OP_SET_EVSEL;
1585 op->v.evsel = evsel;
1586 }
1587 }
1588
1589 return 0;
1590}
1591
1420#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START) 1592#define ERRNO_OFFSET(e) ((e) - __BPF_LOADER_ERRNO__START)
1421#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c) 1593#define ERRCODE_OFFSET(c) ERRNO_OFFSET(BPF_LOADER_ERRNO__##c)
1422#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START) 1594#define NR_ERRNO (__BPF_LOADER_ERRNO__END - __BPF_LOADER_ERRNO__START)
@@ -1472,7 +1644,7 @@ bpf_loader_strerror(int err, char *buf, size_t size)
1472 snprintf(buf, size, "Unknown bpf loader error %d", err); 1644 snprintf(buf, size, "Unknown bpf loader error %d", err);
1473 else 1645 else
1474 snprintf(buf, size, "%s", 1646 snprintf(buf, size, "%s",
1475 strerror_r(err, sbuf, sizeof(sbuf))); 1647 str_error_r(err, sbuf, sizeof(sbuf)));
1476 1648
1477 buf[size - 1] = '\0'; 1649 buf[size - 1] = '\0';
1478 return -1; 1650 return -1;
@@ -1542,7 +1714,7 @@ int bpf__strerror_load(struct bpf_object *obj,
1542{ 1714{
1543 bpf__strerror_head(err, buf, size); 1715 bpf__strerror_head(err, buf, size);
1544 case LIBBPF_ERRNO__KVER: { 1716 case LIBBPF_ERRNO__KVER: {
1545 unsigned int obj_kver = bpf_object__get_kversion(obj); 1717 unsigned int obj_kver = bpf_object__kversion(obj);
1546 unsigned int real_kver; 1718 unsigned int real_kver;
1547 1719
1548 if (fetch_kernel_version(&real_kver, NULL, 0)) { 1720 if (fetch_kernel_version(&real_kver, NULL, 0)) {
@@ -1590,3 +1762,11 @@ int bpf__strerror_apply_obj_config(int err, char *buf, size_t size)
1590 bpf__strerror_end(buf, size); 1762 bpf__strerror_end(buf, size);
1591 return 0; 1763 return 0;
1592} 1764}
1765
1766int bpf__strerror_setup_stdout(struct perf_evlist *evlist __maybe_unused,
1767 int err, char *buf, size_t size)
1768{
1769 bpf__strerror_head(err, buf, size);
1770 bpf__strerror_end(buf, size);
1771 return 0;
1772}
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index be4311944e3d..f2b737b225f2 100644
--- a/tools/perf/util/bpf-loader.h
+++ b/tools/perf/util/bpf-loader.h
@@ -46,7 +46,7 @@ struct bpf_object;
46struct parse_events_term; 46struct parse_events_term;
47#define PERF_BPF_PROBE_GROUP "perf_bpf_probe" 47#define PERF_BPF_PROBE_GROUP "perf_bpf_probe"
48 48
49typedef int (*bpf_prog_iter_callback_t)(struct probe_trace_event *tev, 49typedef int (*bpf_prog_iter_callback_t)(const char *group, const char *event,
50 int fd, void *arg); 50 int fd, void *arg);
51 51
52#ifdef HAVE_LIBBPF_SUPPORT 52#ifdef HAVE_LIBBPF_SUPPORT
@@ -67,8 +67,8 @@ int bpf__strerror_probe(struct bpf_object *obj, int err,
67int bpf__load(struct bpf_object *obj); 67int bpf__load(struct bpf_object *obj);
68int bpf__strerror_load(struct bpf_object *obj, int err, 68int bpf__strerror_load(struct bpf_object *obj, int err,
69 char *buf, size_t size); 69 char *buf, size_t size);
70int bpf__foreach_tev(struct bpf_object *obj, 70int bpf__foreach_event(struct bpf_object *obj,
71 bpf_prog_iter_callback_t func, void *arg); 71 bpf_prog_iter_callback_t func, void *arg);
72 72
73int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term, 73int bpf__config_obj(struct bpf_object *obj, struct parse_events_term *term,
74 struct perf_evlist *evlist, int *error_pos); 74 struct perf_evlist *evlist, int *error_pos);
@@ -79,6 +79,11 @@ int bpf__strerror_config_obj(struct bpf_object *obj,
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#else 87#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,
@@ -102,9 +107,9 @@ static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0
102static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; } 107static inline int bpf__load(struct bpf_object *obj __maybe_unused) { return 0; }
103 108
104static inline int 109static inline int
105bpf__foreach_tev(struct bpf_object *obj __maybe_unused, 110bpf__foreach_event(struct bpf_object *obj __maybe_unused,
106 bpf_prog_iter_callback_t func __maybe_unused, 111 bpf_prog_iter_callback_t func __maybe_unused,
107 void *arg __maybe_unused) 112 void *arg __maybe_unused)
108{ 113{
109 return 0; 114 return 0;
110} 115}
@@ -125,6 +130,12 @@ bpf__apply_obj_config(void)
125} 130}
126 131
127static inline int 132static inline int
133bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
134{
135 return 0;
136}
137
138static inline int
128__bpf_strerror(char *buf, size_t size) 139__bpf_strerror(char *buf, size_t size)
129{ 140{
130 if (!size) 141 if (!size)
@@ -177,5 +188,13 @@ bpf__strerror_apply_obj_config(int err __maybe_unused,
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#endif 199#endif
181#endif 200#endif
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 0573c2ec861d..5651f3c12f93 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -17,6 +17,7 @@
17#include "tool.h" 17#include "tool.h"
18#include "header.h" 18#include "header.h"
19#include "vdso.h" 19#include "vdso.h"
20#include "probe-file.h"
20 21
21 22
22static bool no_buildid_cache; 23static bool no_buildid_cache;
@@ -144,7 +145,28 @@ static int asnprintf(char **strp, size_t size, const char *fmt, ...)
144 return ret; 145 return ret;
145} 146}
146 147
147static char *build_id__filename(const char *sbuild_id, char *bf, size_t size) 148char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
149 size_t size)
150{
151 bool retry_old = true;
152
153 snprintf(bf, size, "%s/%s/%s/kallsyms",
154 buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
155retry:
156 if (!access(bf, F_OK))
157 return bf;
158 if (retry_old) {
159 /* Try old style kallsyms cache */
160 snprintf(bf, size, "%s/%s/%s",
161 buildid_dir, DSO__NAME_KALLSYMS, sbuild_id);
162 retry_old = false;
163 goto retry;
164 }
165
166 return NULL;
167}
168
169char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size)
148{ 170{
149 char *tmp = bf; 171 char *tmp = bf;
150 int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir, 172 int ret = asnprintf(&bf, size, "%s/.build-id/%.2s/%s", buildid_dir,
@@ -154,23 +176,107 @@ static char *build_id__filename(const char *sbuild_id, char *bf, size_t size)
154 return bf; 176 return bf;
155} 177}
156 178
179char *build_id_cache__origname(const char *sbuild_id)
180{
181 char *linkname;
182 char buf[PATH_MAX];
183 char *ret = NULL, *p;
184 size_t offs = 5; /* == strlen("../..") */
185
186 linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
187 if (!linkname)
188 return NULL;
189
190 if (readlink(linkname, buf, PATH_MAX) < 0)
191 goto out;
192 /* The link should be "../..<origpath>/<sbuild_id>" */
193 p = strrchr(buf, '/'); /* Cut off the "/<sbuild_id>" */
194 if (p && (p > buf + offs)) {
195 *p = '\0';
196 if (buf[offs + 1] == '[')
197 offs++; /*
198 * This is a DSO name, like [kernel.kallsyms].
199 * Skip the first '/', since this is not the
200 * cache of a regular file.
201 */
202 ret = strdup(buf + offs); /* Skip "../..[/]" */
203 }
204out:
205 free(linkname);
206 return ret;
207}
208
209/* Check if the given build_id cache is valid on current running system */
210static bool build_id_cache__valid_id(char *sbuild_id)
211{
212 char real_sbuild_id[SBUILD_ID_SIZE] = "";
213 char *pathname;
214 int ret = 0;
215 bool result = false;
216
217 pathname = build_id_cache__origname(sbuild_id);
218 if (!pathname)
219 return false;
220
221 if (!strcmp(pathname, DSO__NAME_KALLSYMS))
222 ret = sysfs__sprintf_build_id("/", real_sbuild_id);
223 else if (pathname[0] == '/')
224 ret = filename__sprintf_build_id(pathname, real_sbuild_id);
225 else
226 ret = -EINVAL; /* Should we support other special DSO cache? */
227 if (ret >= 0)
228 result = (strcmp(sbuild_id, real_sbuild_id) == 0);
229 free(pathname);
230
231 return result;
232}
233
234static const char *build_id_cache__basename(bool is_kallsyms, bool is_vdso)
235{
236 return is_kallsyms ? "kallsyms" : (is_vdso ? "vdso" : "elf");
237}
238
157char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size) 239char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size)
158{ 240{
159 char build_id_hex[SBUILD_ID_SIZE]; 241 bool is_kallsyms = dso__is_kallsyms((struct dso *)dso);
242 bool is_vdso = dso__is_vdso((struct dso *)dso);
243 char sbuild_id[SBUILD_ID_SIZE];
244 char *linkname;
245 bool alloc = (bf == NULL);
246 int ret;
160 247
161 if (!dso->has_build_id) 248 if (!dso->has_build_id)
162 return NULL; 249 return NULL;
163 250
164 build_id__sprintf(dso->build_id, sizeof(dso->build_id), build_id_hex); 251 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
165 return build_id__filename(build_id_hex, bf, size); 252 linkname = build_id_cache__linkname(sbuild_id, NULL, 0);
253 if (!linkname)
254 return NULL;
255
256 /* Check if old style build_id cache */
257 if (is_regular_file(linkname))
258 ret = asnprintf(&bf, size, "%s", linkname);
259 else
260 ret = asnprintf(&bf, size, "%s/%s", linkname,
261 build_id_cache__basename(is_kallsyms, is_vdso));
262 if (ret < 0 || (!alloc && size < (unsigned int)ret))
263 bf = NULL;
264 free(linkname);
265
266 return bf;
166} 267}
167 268
168bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size) 269bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
169{ 270{
170 char *id_name, *ch; 271 char *id_name = NULL, *ch;
171 struct stat sb; 272 struct stat sb;
273 char sbuild_id[SBUILD_ID_SIZE];
274
275 if (!dso->has_build_id)
276 goto err;
172 277
173 id_name = dso__build_id_filename(dso, bf, size); 278 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
279 id_name = build_id_cache__linkname(sbuild_id, NULL, 0);
174 if (!id_name) 280 if (!id_name)
175 goto err; 281 goto err;
176 if (access(id_name, F_OK)) 282 if (access(id_name, F_OK))
@@ -194,18 +300,14 @@ bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size)
194 if (ch - 3 < bf) 300 if (ch - 3 < bf)
195 goto err; 301 goto err;
196 302
303 free(id_name);
197 return strncmp(".ko", ch - 3, 3) == 0; 304 return strncmp(".ko", ch - 3, 3) == 0;
198err: 305err:
199 /*
200 * If dso__build_id_filename work, get id_name again,
201 * because id_name points to bf and is broken.
202 */
203 if (id_name)
204 id_name = dso__build_id_filename(dso, bf, size);
205 pr_err("Invalid build id: %s\n", id_name ? : 306 pr_err("Invalid build id: %s\n", id_name ? :
206 dso->long_name ? : 307 dso->long_name ? :
207 dso->short_name ? : 308 dso->short_name ? :
208 "[unknown]"); 309 "[unknown]");
310 free(id_name);
209 return false; 311 return false;
210} 312}
211 313
@@ -256,19 +358,19 @@ static int machine__write_buildid_table(struct machine *machine, int fd)
256 size_t name_len; 358 size_t name_len;
257 bool in_kernel = false; 359 bool in_kernel = false;
258 360
259 if (!pos->hit) 361 if (!pos->hit && !dso__is_vdso(pos))
260 continue; 362 continue;
261 363
262 if (dso__is_vdso(pos)) { 364 if (dso__is_vdso(pos)) {
263 name = pos->short_name; 365 name = pos->short_name;
264 name_len = pos->short_name_len + 1; 366 name_len = pos->short_name_len;
265 } else if (dso__is_kcore(pos)) { 367 } else if (dso__is_kcore(pos)) {
266 machine__mmap_name(machine, nm, sizeof(nm)); 368 machine__mmap_name(machine, nm, sizeof(nm));
267 name = nm; 369 name = nm;
268 name_len = strlen(nm) + 1; 370 name_len = strlen(nm);
269 } else { 371 } else {
270 name = pos->long_name; 372 name = pos->long_name;
271 name_len = pos->long_name_len + 1; 373 name_len = pos->long_name_len;
272 } 374 }
273 375
274 in_kernel = pos->kernel || 376 in_kernel = pos->kernel ||
@@ -340,8 +442,132 @@ void disable_buildid_cache(void)
340 no_buildid_cache = true; 442 no_buildid_cache = true;
341} 443}
342 444
343static char *build_id_cache__dirname_from_path(const char *name, 445static bool lsdir_bid_head_filter(const char *name __maybe_unused,
344 bool is_kallsyms, bool is_vdso) 446 struct dirent *d __maybe_unused)
447{
448 return (strlen(d->d_name) == 2) &&
449 isxdigit(d->d_name[0]) && isxdigit(d->d_name[1]);
450}
451
452static bool lsdir_bid_tail_filter(const char *name __maybe_unused,
453 struct dirent *d __maybe_unused)
454{
455 int i = 0;
456 while (isxdigit(d->d_name[i]) && i < SBUILD_ID_SIZE - 3)
457 i++;
458 return (i == SBUILD_ID_SIZE - 3) && (d->d_name[i] == '\0');
459}
460
461struct strlist *build_id_cache__list_all(bool validonly)
462{
463 struct strlist *toplist, *linklist = NULL, *bidlist;
464 struct str_node *nd, *nd2;
465 char *topdir, *linkdir = NULL;
466 char sbuild_id[SBUILD_ID_SIZE];
467
468 /* for filename__ functions */
469 if (validonly)
470 symbol__init(NULL);
471
472 /* Open the top-level directory */
473 if (asprintf(&topdir, "%s/.build-id/", buildid_dir) < 0)
474 return NULL;
475
476 bidlist = strlist__new(NULL, NULL);
477 if (!bidlist)
478 goto out;
479
480 toplist = lsdir(topdir, lsdir_bid_head_filter);
481 if (!toplist) {
482 pr_debug("Error in lsdir(%s): %d\n", topdir, errno);
483 /* If there is no buildid cache, return an empty list */
484 if (errno == ENOENT)
485 goto out;
486 goto err_out;
487 }
488
489 strlist__for_each_entry(nd, toplist) {
490 if (asprintf(&linkdir, "%s/%s", topdir, nd->s) < 0)
491 goto err_out;
492 /* Open the lower-level directory */
493 linklist = lsdir(linkdir, lsdir_bid_tail_filter);
494 if (!linklist) {
495 pr_debug("Error in lsdir(%s): %d\n", linkdir, errno);
496 goto err_out;
497 }
498 strlist__for_each_entry(nd2, linklist) {
499 if (snprintf(sbuild_id, SBUILD_ID_SIZE, "%s%s",
500 nd->s, nd2->s) != SBUILD_ID_SIZE - 1)
501 goto err_out;
502 if (validonly && !build_id_cache__valid_id(sbuild_id))
503 continue;
504 if (strlist__add(bidlist, sbuild_id) < 0)
505 goto err_out;
506 }
507 strlist__delete(linklist);
508 zfree(&linkdir);
509 }
510
511out_free:
512 strlist__delete(toplist);
513out:
514 free(topdir);
515
516 return bidlist;
517
518err_out:
519 strlist__delete(linklist);
520 zfree(&linkdir);
521 strlist__delete(bidlist);
522 bidlist = NULL;
523 goto out_free;
524}
525
526static bool str_is_build_id(const char *maybe_sbuild_id, size_t len)
527{
528 size_t i;
529
530 for (i = 0; i < len; i++) {
531 if (!isxdigit(maybe_sbuild_id[i]))
532 return false;
533 }
534 return true;
535}
536
537/* Return the valid complete build-id */
538char *build_id_cache__complement(const char *incomplete_sbuild_id)
539{
540 struct strlist *bidlist;
541 struct str_node *nd, *cand = NULL;
542 char *sbuild_id = NULL;
543 size_t len = strlen(incomplete_sbuild_id);
544
545 if (len >= SBUILD_ID_SIZE ||
546 !str_is_build_id(incomplete_sbuild_id, len))
547 return NULL;
548
549 bidlist = build_id_cache__list_all(true);
550 if (!bidlist)
551 return NULL;
552
553 strlist__for_each_entry(nd, bidlist) {
554 if (strncmp(nd->s, incomplete_sbuild_id, len) != 0)
555 continue;
556 if (cand) { /* Error: There are more than 2 candidates. */
557 cand = NULL;
558 break;
559 }
560 cand = nd;
561 }
562 if (cand)
563 sbuild_id = strdup(cand->s);
564 strlist__delete(bidlist);
565
566 return sbuild_id;
567}
568
569char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
570 bool is_kallsyms, bool is_vdso)
345{ 571{
346 char *realname = (char *)name, *filename; 572 char *realname = (char *)name, *filename;
347 bool slash = is_kallsyms || is_vdso; 573 bool slash = is_kallsyms || is_vdso;
@@ -352,8 +578,9 @@ static char *build_id_cache__dirname_from_path(const char *name,
352 return NULL; 578 return NULL;
353 } 579 }
354 580
355 if (asprintf(&filename, "%s%s%s", buildid_dir, slash ? "/" : "", 581 if (asprintf(&filename, "%s%s%s%s%s", buildid_dir, slash ? "/" : "",
356 is_vdso ? DSO__NAME_VDSO : realname) < 0) 582 is_vdso ? DSO__NAME_VDSO : realname,
583 sbuild_id ? "/" : "", sbuild_id ?: "") < 0)
357 filename = NULL; 584 filename = NULL;
358 585
359 if (!slash) 586 if (!slash)
@@ -365,49 +592,51 @@ static char *build_id_cache__dirname_from_path(const char *name,
365int build_id_cache__list_build_ids(const char *pathname, 592int build_id_cache__list_build_ids(const char *pathname,
366 struct strlist **result) 593 struct strlist **result)
367{ 594{
368 struct strlist *list;
369 char *dir_name; 595 char *dir_name;
370 DIR *dir;
371 struct dirent *d;
372 int ret = 0; 596 int ret = 0;
373 597
374 list = strlist__new(NULL, NULL); 598 dir_name = build_id_cache__cachedir(NULL, pathname, false, false);
375 dir_name = build_id_cache__dirname_from_path(pathname, false, false); 599 if (!dir_name)
376 if (!list || !dir_name) { 600 return -ENOMEM;
377 ret = -ENOMEM;
378 goto out;
379 }
380 601
381 /* List up all dirents */ 602 *result = lsdir(dir_name, lsdir_no_dot_filter);
382 dir = opendir(dir_name); 603 if (!*result)
383 if (!dir) {
384 ret = -errno; 604 ret = -errno;
385 goto out; 605 free(dir_name);
386 }
387 606
388 while ((d = readdir(dir)) != NULL) { 607 return ret;
389 if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) 608}
390 continue;
391 strlist__add(list, d->d_name);
392 }
393 closedir(dir);
394 609
395out: 610#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT)
396 free(dir_name); 611static int build_id_cache__add_sdt_cache(const char *sbuild_id,
397 if (ret) 612 const char *realname)
398 strlist__delete(list); 613{
399 else 614 struct probe_cache *cache;
400 *result = list; 615 int ret;
401 616
617 cache = probe_cache__new(sbuild_id);
618 if (!cache)
619 return -1;
620
621 ret = probe_cache__scan_sdt(cache, realname);
622 if (ret >= 0) {
623 pr_debug("Found %d SDTs in %s\n", ret, realname);
624 if (probe_cache__commit(cache) < 0)
625 ret = -1;
626 }
627 probe_cache__delete(cache);
402 return ret; 628 return ret;
403} 629}
630#else
631#define build_id_cache__add_sdt_cache(sbuild_id, realname) (0)
632#endif
404 633
405int build_id_cache__add_s(const char *sbuild_id, const char *name, 634int build_id_cache__add_s(const char *sbuild_id, const char *name,
406 bool is_kallsyms, bool is_vdso) 635 bool is_kallsyms, bool is_vdso)
407{ 636{
408 const size_t size = PATH_MAX; 637 const size_t size = PATH_MAX;
409 char *realname = NULL, *filename = NULL, *dir_name = NULL, 638 char *realname = NULL, *filename = NULL, *dir_name = NULL,
410 *linkname = zalloc(size), *targetname, *tmp; 639 *linkname = zalloc(size), *tmp;
411 int err = -1; 640 int err = -1;
412 641
413 if (!is_kallsyms) { 642 if (!is_kallsyms) {
@@ -416,14 +645,22 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
416 goto out_free; 645 goto out_free;
417 } 646 }
418 647
419 dir_name = build_id_cache__dirname_from_path(name, is_kallsyms, is_vdso); 648 dir_name = build_id_cache__cachedir(sbuild_id, name,
649 is_kallsyms, is_vdso);
420 if (!dir_name) 650 if (!dir_name)
421 goto out_free; 651 goto out_free;
422 652
653 /* Remove old style build-id cache */
654 if (is_regular_file(dir_name))
655 if (unlink(dir_name))
656 goto out_free;
657
423 if (mkdir_p(dir_name, 0755)) 658 if (mkdir_p(dir_name, 0755))
424 goto out_free; 659 goto out_free;
425 660
426 if (asprintf(&filename, "%s/%s", dir_name, sbuild_id) < 0) { 661 /* Save the allocated buildid dirname */
662 if (asprintf(&filename, "%s/%s", dir_name,
663 build_id_cache__basename(is_kallsyms, is_vdso)) < 0) {
427 filename = NULL; 664 filename = NULL;
428 goto out_free; 665 goto out_free;
429 } 666 }
@@ -437,7 +674,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
437 goto out_free; 674 goto out_free;
438 } 675 }
439 676
440 if (!build_id__filename(sbuild_id, linkname, size)) 677 if (!build_id_cache__linkname(sbuild_id, linkname, size))
441 goto out_free; 678 goto out_free;
442 tmp = strrchr(linkname, '/'); 679 tmp = strrchr(linkname, '/');
443 *tmp = '\0'; 680 *tmp = '\0';
@@ -446,11 +683,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
446 goto out_free; 683 goto out_free;
447 684
448 *tmp = '/'; 685 *tmp = '/';
449 targetname = filename + strlen(buildid_dir) - 5; 686 tmp = dir_name + strlen(buildid_dir) - 5;
450 memcpy(targetname, "../..", 5); 687 memcpy(tmp, "../..", 5);
451 688
452 if (symlink(targetname, linkname) == 0) 689 if (symlink(tmp, linkname) == 0)
453 err = 0; 690 err = 0;
691
692 /* Update SDT cache : error is just warned */
693 if (build_id_cache__add_sdt_cache(sbuild_id, realname) < 0)
694 pr_debug("Failed to update/scan SDT cache for %s\n", realname);
695
454out_free: 696out_free:
455 if (!is_kallsyms) 697 if (!is_kallsyms)
456 free(realname); 698 free(realname);
@@ -474,7 +716,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
474bool build_id_cache__cached(const char *sbuild_id) 716bool build_id_cache__cached(const char *sbuild_id)
475{ 717{
476 bool ret = false; 718 bool ret = false;
477 char *filename = build_id__filename(sbuild_id, NULL, 0); 719 char *filename = build_id_cache__linkname(sbuild_id, NULL, 0);
478 720
479 if (filename && !access(filename, F_OK)) 721 if (filename && !access(filename, F_OK))
480 ret = true; 722 ret = true;
@@ -493,7 +735,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
493 if (filename == NULL || linkname == NULL) 735 if (filename == NULL || linkname == NULL)
494 goto out_free; 736 goto out_free;
495 737
496 if (!build_id__filename(sbuild_id, linkname, size)) 738 if (!build_id_cache__linkname(sbuild_id, linkname, size))
497 goto out_free; 739 goto out_free;
498 740
499 if (access(linkname, F_OK)) 741 if (access(linkname, F_OK))
@@ -511,7 +753,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
511 tmp = strrchr(linkname, '/') + 1; 753 tmp = strrchr(linkname, '/') + 1;
512 snprintf(tmp, size - (tmp - linkname), "%s", filename); 754 snprintf(tmp, size - (tmp - linkname), "%s", filename);
513 755
514 if (unlink(linkname)) 756 if (rm_rf(linkname))
515 goto out_free; 757 goto out_free;
516 758
517 err = 0; 759 err = 0;
@@ -523,7 +765,7 @@ out_free:
523 765
524static int dso__cache_build_id(struct dso *dso, struct machine *machine) 766static int dso__cache_build_id(struct dso *dso, struct machine *machine)
525{ 767{
526 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 768 bool is_kallsyms = dso__is_kallsyms(dso);
527 bool is_vdso = dso__is_vdso(dso); 769 bool is_vdso = dso__is_vdso(dso);
528 const char *name = dso->long_name; 770 const char *name = dso->long_name;
529 char nm[PATH_MAX]; 771 char nm[PATH_MAX];
diff --git a/tools/perf/util/build-id.h b/tools/perf/util/build-id.h
index 64af3e20610d..d27990610f9f 100644
--- a/tools/perf/util/build-id.h
+++ b/tools/perf/util/build-id.h
@@ -14,6 +14,8 @@ struct dso;
14int build_id__sprintf(const u8 *build_id, int len, char *bf); 14int build_id__sprintf(const u8 *build_id, int len, char *bf);
15int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id); 15int sysfs__sprintf_build_id(const char *root_dir, char *sbuild_id);
16int filename__sprintf_build_id(const char *pathname, char *sbuild_id); 16int filename__sprintf_build_id(const char *pathname, char *sbuild_id);
17char *build_id_cache__kallsyms_path(const char *sbuild_id, char *bf,
18 size_t size);
17 19
18char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size); 20char *dso__build_id_filename(const struct dso *dso, char *bf, size_t size);
19bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size); 21bool dso__build_id_is_kmod(const struct dso *dso, char *bf, size_t size);
@@ -28,6 +30,12 @@ bool perf_session__read_build_ids(struct perf_session *session, bool with_hits);
28int perf_session__write_buildid_table(struct perf_session *session, int fd); 30int perf_session__write_buildid_table(struct perf_session *session, int fd);
29int perf_session__cache_build_ids(struct perf_session *session); 31int perf_session__cache_build_ids(struct perf_session *session);
30 32
33char *build_id_cache__origname(const char *sbuild_id);
34char *build_id_cache__linkname(const char *sbuild_id, char *bf, size_t size);
35char *build_id_cache__cachedir(const char *sbuild_id, const char *name,
36 bool is_kallsyms, bool is_vdso);
37struct strlist *build_id_cache__list_all(bool validonly);
38char *build_id_cache__complement(const char *incomplete_sbuild_id);
31int build_id_cache__list_build_ids(const char *pathname, 39int build_id_cache__list_build_ids(const char *pathname,
32 struct strlist **result); 40 struct strlist **result);
33bool build_id_cache__cached(const char *sbuild_id); 41bool build_id_cache__cached(const char *sbuild_id);
diff --git a/tools/perf/util/cache.h b/tools/perf/util/cache.h
index 1f5a93c2c9a2..512c0c83fbc6 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,72 +1,30 @@
1#ifndef __PERF_CACHE_H 1#ifndef __PERF_CACHE_H
2#define __PERF_CACHE_H 2#define __PERF_CACHE_H
3 3
4#include <stdbool.h>
5#include "util.h"
6#include "strbuf.h" 4#include "strbuf.h"
7#include <subcmd/pager.h> 5#include <subcmd/pager.h>
8#include "../perf.h"
9#include "../ui/ui.h" 6#include "../ui/ui.h"
10 7
11#include <linux/string.h> 8#include <linux/string.h>
12 9
13#define CMD_EXEC_PATH "--exec-path" 10#define CMD_EXEC_PATH "--exec-path"
14#define CMD_PERF_DIR "--perf-dir="
15#define CMD_WORK_TREE "--work-tree="
16#define CMD_DEBUGFS_DIR "--debugfs-dir=" 11#define CMD_DEBUGFS_DIR "--debugfs-dir="
17 12
18#define PERF_DIR_ENVIRONMENT "PERF_DIR"
19#define PERF_WORK_TREE_ENVIRONMENT "PERF_WORK_TREE"
20#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH" 13#define EXEC_PATH_ENVIRONMENT "PERF_EXEC_PATH"
21#define DEFAULT_PERF_DIR_ENVIRONMENT ".perf"
22#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR" 14#define PERF_DEBUGFS_ENVIRONMENT "PERF_DEBUGFS_DIR"
23#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR" 15#define PERF_TRACEFS_ENVIRONMENT "PERF_TRACEFS_DIR"
24#define PERF_PAGER_ENVIRONMENT "PERF_PAGER" 16#define PERF_PAGER_ENVIRONMENT "PERF_PAGER"
25 17
26extern const char *config_exclusive_filename;
27
28typedef int (*config_fn_t)(const char *, const char *, void *);
29int perf_default_config(const char *, const char *, void *);
30int perf_config(config_fn_t fn, void *);
31int perf_config_int(const char *, const char *);
32u64 perf_config_u64(const char *, const char *);
33int perf_config_bool(const char *, const char *);
34int config_error_nonbool(const char *);
35const char *perf_config_dirname(const char *, const char *);
36const char *perf_etc_perfconfig(void);
37
38char *alias_lookup(const char *alias); 18char *alias_lookup(const char *alias);
39int split_cmdline(char *cmdline, const char ***argv); 19int split_cmdline(char *cmdline, const char ***argv);
40 20
41#define alloc_nr(x) (((x)+16)*3/2) 21#define alloc_nr(x) (((x)+16)*3/2)
42 22
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) 23static inline int is_absolute_path(const char *path)
63{ 24{
64 return path[0] == '/'; 25 return path[0] == '/';
65} 26}
66 27
67char *strip_path_suffix(const char *path, const char *suffix);
68
69char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 28char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
70char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
71 29
72#endif /* __PERF_CACHE_H */ 30#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/call-path.c b/tools/perf/util/call-path.c
new file mode 100644
index 000000000000..904a17052e38
--- /dev/null
+++ b/tools/perf/util/call-path.c
@@ -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}
diff --git a/tools/perf/util/call-path.h b/tools/perf/util/call-path.h
new file mode 100644
index 000000000000..477f6d03b659
--- /dev/null
+++ b/tools/perf/util/call-path.h
@@ -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
diff --git a/tools/perf/util/callchain.c b/tools/perf/util/callchain.c
index 24b4bd0d7754..07fd30bc2f81 100644
--- a/tools/perf/util/callchain.c
+++ b/tools/perf/util/callchain.c
@@ -109,6 +109,7 @@ __parse_callchain_report_opt(const char *arg, bool allow_record_opt)
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)
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,
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
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;
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index d2a9e694810c..13e75549c440 100644
--- a/tools/perf/util/callchain.h
+++ b/tools/perf/util/callchain.h
@@ -94,6 +94,7 @@ struct callchain_param {
94 enum perf_call_graph_mode record_mode; 94 enum perf_call_graph_mode record_mode;
95 u32 dump_size; 95 u32 dump_size;
96 enum chain_mode mode; 96 enum chain_mode mode;
97 u16 max_stack;
97 u32 print_limit; 98 u32 print_limit;
98 double min_percent; 99 double min_percent;
99 sort_chain_func_t sort; 100 sort_chain_func_t sort;
@@ -105,6 +106,7 @@ struct callchain_param {
105}; 106};
106 107
107extern struct callchain_param callchain_param; 108extern struct callchain_param callchain_param;
109extern struct callchain_param callchain_param_default;
108 110
109struct callchain_list { 111struct callchain_list {
110 u64 ip; 112 u64 ip;
@@ -212,7 +214,14 @@ struct hist_entry;
212int record_parse_callchain_opt(const struct option *opt, const char *arg, int unset); 214int 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); 215int record_callchain_opt(const struct option *opt, const char *arg, int unset);
214 216
215int sample__resolve_callchain(struct perf_sample *sample, struct symbol **parent, 217struct record_opts;
218
219int record_opts__parse_callchain(struct record_opts *record,
220 struct callchain_param *callchain,
221 const char *arg, bool unset);
222
223int sample__resolve_callchain(struct perf_sample *sample,
224 struct callchain_cursor *cursor, struct symbol **parent,
216 struct perf_evsel *evsel, struct addr_location *al, 225 struct perf_evsel *evsel, struct addr_location *al,
217 int max_stack); 226 int max_stack);
218int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample); 227int hist_entry__append_callchain(struct hist_entry *he, struct perf_sample *sample);
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 90aa1b46b2e5..8fdee24725a7 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -81,7 +81,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
81 /* 81 /*
82 * check if cgrp is already defined, if so we reuse it 82 * check if cgrp is already defined, if so we reuse it
83 */ 83 */
84 evlist__for_each(evlist, counter) { 84 evlist__for_each_entry(evlist, counter) {
85 cgrp = counter->cgrp; 85 cgrp = counter->cgrp;
86 if (!cgrp) 86 if (!cgrp)
87 continue; 87 continue;
@@ -110,7 +110,7 @@ static int add_cgroup(struct perf_evlist *evlist, char *str)
110 * if add cgroup N, then need to find event N 110 * if add cgroup N, then need to find event N
111 */ 111 */
112 n = 0; 112 n = 0;
113 evlist__for_each(evlist, counter) { 113 evlist__for_each_entry(evlist, counter) {
114 if (n == nr_cgroups) 114 if (n == nr_cgroups)
115 goto found; 115 goto found;
116 n++; 116 n++;
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index 2babddaa2481..f0dcd0ee0afa 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -4,18 +4,24 @@
4#include "cloexec.h" 4#include "cloexec.h"
5#include "asm/bug.h" 5#include "asm/bug.h"
6#include "debug.h" 6#include "debug.h"
7#include <unistd.h>
8#include <asm/unistd.h>
9#include <sys/syscall.h>
7 10
8static unsigned long flag = PERF_FLAG_FD_CLOEXEC; 11static unsigned long flag = PERF_FLAG_FD_CLOEXEC;
9 12
10#ifdef __GLIBC_PREREQ
11#if !__GLIBC_PREREQ(2, 6)
12int __weak sched_getcpu(void) 13int __weak sched_getcpu(void)
13{ 14{
15#ifdef __NR_getcpu
16 unsigned cpu;
17 int err = syscall(__NR_getcpu, &cpu, NULL, NULL);
18 if (!err)
19 return cpu;
20#else
14 errno = ENOSYS; 21 errno = ENOSYS;
22#endif
15 return -1; 23 return -1;
16} 24}
17#endif
18#endif
19 25
20static int perf_flag_probe(void) 26static int perf_flag_probe(void)
21{ 27{
@@ -58,7 +64,7 @@ static int perf_flag_probe(void)
58 64
59 WARN_ONCE(err != EINVAL && err != EBUSY, 65 WARN_ONCE(err != EINVAL && err != EBUSY,
60 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n", 66 "perf_event_open(..., PERF_FLAG_FD_CLOEXEC) failed with unexpected error %d (%s)\n",
61 err, strerror_r(err, sbuf, sizeof(sbuf))); 67 err, str_error_r(err, sbuf, sizeof(sbuf)));
62 68
63 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 69 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
64 while (1) { 70 while (1) {
@@ -76,7 +82,7 @@ static int perf_flag_probe(void)
76 82
77 if (WARN_ONCE(fd < 0 && err != EBUSY, 83 if (WARN_ONCE(fd < 0 && err != EBUSY,
78 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n", 84 "perf_event_open(..., 0) failed unexpectedly with error %d (%s)\n",
79 err, strerror_r(err, sbuf, sizeof(sbuf)))) 85 err, str_error_r(err, sbuf, sizeof(sbuf))))
80 return -1; 86 return -1;
81 87
82 return 0; 88 return 0;
diff --git a/tools/perf/util/color.c b/tools/perf/util/color.c
index 43e84aa27e4a..dbbf89b050a5 100644
--- a/tools/perf/util/color.c
+++ b/tools/perf/util/color.c
@@ -1,7 +1,11 @@
1#include <linux/kernel.h> 1#include <linux/kernel.h>
2#include "cache.h" 2#include "cache.h"
3#include "config.h"
4#include <stdlib.h>
5#include <stdio.h>
3#include "color.h" 6#include "color.h"
4#include <math.h> 7#include <math.h>
8#include <unistd.h>
5 9
6int perf_use_color_default = -1; 10int perf_use_color_default = -1;
7 11
diff --git a/tools/perf/util/config.c b/tools/perf/util/config.c
index 4e727635476e..18dae745034f 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -13,6 +13,7 @@
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
@@ -25,6 +26,7 @@ static FILE *config_file;
25static const char *config_file_name; 26static const char *config_file_name;
26static int config_linenr; 27static int config_linenr;
27static int config_file_eof; 28static int config_file_eof;
29static struct perf_config_set *config_set;
28 30
29const char *config_exclusive_filename; 31const char *config_exclusive_filename;
30 32
@@ -274,7 +276,8 @@ static int perf_parse_file(config_fn_t fn, void *data)
274 break; 276 break;
275 } 277 }
276 } 278 }
277 die("bad config file line %d in %s", config_linenr, config_file_name); 279 pr_err("bad config file line %d in %s\n", config_linenr, config_file_name);
280 return -1;
278} 281}
279 282
280static int parse_unit_factor(const char *end, unsigned long *val) 283static int parse_unit_factor(const char *end, unsigned long *val)
@@ -370,13 +373,28 @@ int perf_config_bool(const char *name, const char *value)
370 return !!perf_config_bool_or_int(name, value, &discard); 373 return !!perf_config_bool_or_int(name, value, &discard);
371} 374}
372 375
373const char *perf_config_dirname(const char *name, const char *value) 376static const char *perf_config_dirname(const char *name, const char *value)
374{ 377{
375 if (!name) 378 if (!name)
376 return NULL; 379 return NULL;
377 return value; 380 return value;
378} 381}
379 382
383static int perf_buildid_config(const char *var, const char *value)
384{
385 /* same dir for all commands */
386 if (!strcmp(var, "buildid.dir")) {
387 const char *dir = perf_config_dirname(var, value);
388
389 if (!dir)
390 return -1;
391 strncpy(buildid_dir, dir, MAXPATHLEN-1);
392 buildid_dir[MAXPATHLEN-1] = '\0';
393 }
394
395 return 0;
396}
397
380static int perf_default_core_config(const char *var __maybe_unused, 398static int perf_default_core_config(const char *var __maybe_unused,
381 const char *value __maybe_unused) 399 const char *value __maybe_unused)
382{ 400{
@@ -412,6 +430,9 @@ int perf_default_config(const char *var, const char *value,
412 if (!prefixcmp(var, "llvm.")) 430 if (!prefixcmp(var, "llvm."))
413 return perf_llvm_config(var, value); 431 return perf_llvm_config(var, value);
414 432
433 if (!prefixcmp(var, "buildid."))
434 return perf_buildid_config(var, value);
435
415 /* Add other config variables here. */ 436 /* Add other config variables here. */
416 return 0; 437 return 0;
417} 438}
@@ -458,18 +479,140 @@ static int perf_config_global(void)
458 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 479 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
459} 480}
460 481
461int perf_config(config_fn_t fn, void *data) 482static struct perf_config_section *find_section(struct list_head *sections,
483 const char *section_name)
484{
485 struct perf_config_section *section;
486
487 list_for_each_entry(section, sections, node)
488 if (!strcmp(section->name, section_name))
489 return section;
490
491 return NULL;
492}
493
494static struct perf_config_item *find_config_item(const char *name,
495 struct perf_config_section *section)
496{
497 struct perf_config_item *item;
498
499 list_for_each_entry(item, &section->items, node)
500 if (!strcmp(item->name, name))
501 return item;
502
503 return NULL;
504}
505
506static struct perf_config_section *add_section(struct list_head *sections,
507 const char *section_name)
508{
509 struct perf_config_section *section = zalloc(sizeof(*section));
510
511 if (!section)
512 return NULL;
513
514 INIT_LIST_HEAD(&section->items);
515 section->name = strdup(section_name);
516 if (!section->name) {
517 pr_debug("%s: strdup failed\n", __func__);
518 free(section);
519 return NULL;
520 }
521
522 list_add_tail(&section->node, sections);
523 return section;
524}
525
526static struct perf_config_item *add_config_item(struct perf_config_section *section,
527 const char *name)
528{
529 struct perf_config_item *item = zalloc(sizeof(*item));
530
531 if (!item)
532 return NULL;
533
534 item->name = strdup(name);
535 if (!item->name) {
536 pr_debug("%s: strdup failed\n", __func__);
537 free(item);
538 return NULL;
539 }
540
541 list_add_tail(&item->node, &section->items);
542 return item;
543}
544
545static int set_value(struct perf_config_item *item, const char *value)
546{
547 char *val = strdup(value);
548
549 if (!val)
550 return -1;
551
552 zfree(&item->value);
553 item->value = val;
554 return 0;
555}
556
557static int collect_config(const char *var, const char *value,
558 void *perf_config_set)
559{
560 int ret = -1;
561 char *ptr, *key;
562 char *section_name, *name;
563 struct perf_config_section *section = NULL;
564 struct perf_config_item *item = NULL;
565 struct perf_config_set *set = perf_config_set;
566 struct list_head *sections;
567
568 if (set == NULL)
569 return -1;
570
571 sections = &set->sections;
572 key = ptr = strdup(var);
573 if (!key) {
574 pr_debug("%s: strdup failed\n", __func__);
575 return -1;
576 }
577
578 section_name = strsep(&ptr, ".");
579 name = ptr;
580 if (name == NULL || value == NULL)
581 goto out_free;
582
583 section = find_section(sections, section_name);
584 if (!section) {
585 section = add_section(sections, section_name);
586 if (!section)
587 goto out_free;
588 }
589
590 item = find_config_item(name, section);
591 if (!item) {
592 item = add_config_item(section, name);
593 if (!item)
594 goto out_free;
595 }
596
597 ret = set_value(item, value);
598 return ret;
599
600out_free:
601 free(key);
602 return -1;
603}
604
605static int perf_config_set__init(struct perf_config_set *set)
462{ 606{
463 int ret = 0, found = 0; 607 int ret = -1;
464 const char *home = NULL; 608 const char *home = NULL;
465 609
466 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */ 610 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
467 if (config_exclusive_filename) 611 if (config_exclusive_filename)
468 return perf_config_from_file(fn, config_exclusive_filename, data); 612 return perf_config_from_file(collect_config, config_exclusive_filename, set);
469 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) { 613 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) {
470 ret += perf_config_from_file(fn, perf_etc_perfconfig(), 614 if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0)
471 data); 615 goto out;
472 found += 1;
473 } 616 }
474 617
475 home = getenv("HOME"); 618 home = getenv("HOME");
@@ -495,52 +638,126 @@ int perf_config(config_fn_t fn, void *data)
495 if (!st.st_size) 638 if (!st.st_size)
496 goto out_free; 639 goto out_free;
497 640
498 ret += perf_config_from_file(fn, user_config, data); 641 ret = perf_config_from_file(collect_config, user_config, set);
499 found += 1; 642
500out_free: 643out_free:
501 free(user_config); 644 free(user_config);
502 } 645 }
503out: 646out:
504 if (found == 0) 647 return ret;
648}
649
650struct perf_config_set *perf_config_set__new(void)
651{
652 struct perf_config_set *set = zalloc(sizeof(*set));
653
654 if (set) {
655 INIT_LIST_HEAD(&set->sections);
656 if (perf_config_set__init(set) < 0) {
657 perf_config_set__delete(set);
658 set = NULL;
659 }
660 }
661
662 return set;
663}
664
665int perf_config(config_fn_t fn, void *data)
666{
667 int ret = 0;
668 char key[BUFSIZ];
669 struct perf_config_section *section;
670 struct perf_config_item *item;
671
672 if (config_set == NULL)
505 return -1; 673 return -1;
674
675 perf_config_set__for_each_entry(config_set, section, item) {
676 char *value = item->value;
677
678 if (value) {
679 scnprintf(key, sizeof(key), "%s.%s",
680 section->name, item->name);
681 ret = fn(key, value, data);
682 if (ret < 0) {
683 pr_err("Error: wrong config key-value pair %s=%s\n",
684 key, value);
685 break;
686 }
687 }
688 }
689
506 return ret; 690 return ret;
507} 691}
508 692
509/* 693void perf_config__init(void)
510 * Call this to report error for your variable that should not
511 * get a boolean value (i.e. "[my] var" means "true").
512 */
513int config_error_nonbool(const char *var)
514{ 694{
515 return error("Missing value for '%s'", var); 695 if (config_set == NULL)
696 config_set = perf_config_set__new();
516} 697}
517 698
518struct buildid_dir_config { 699void perf_config__exit(void)
519 char *dir; 700{
520}; 701 perf_config_set__delete(config_set);
702 config_set = NULL;
703}
521 704
522static int buildid_dir_command_config(const char *var, const char *value, 705void perf_config__refresh(void)
523 void *data)
524{ 706{
525 struct buildid_dir_config *c = data; 707 perf_config__exit();
526 const char *v; 708 perf_config__init();
709}
527 710
528 /* same dir for all commands */ 711static void perf_config_item__delete(struct perf_config_item *item)
529 if (!strcmp(var, "buildid.dir")) { 712{
530 v = perf_config_dirname(var, value); 713 zfree(&item->name);
531 if (!v) 714 zfree(&item->value);
532 return -1; 715 free(item);
533 strncpy(c->dir, v, MAXPATHLEN-1); 716}
534 c->dir[MAXPATHLEN-1] = '\0'; 717
718static void perf_config_section__purge(struct perf_config_section *section)
719{
720 struct perf_config_item *item, *tmp;
721
722 list_for_each_entry_safe(item, tmp, &section->items, node) {
723 list_del_init(&item->node);
724 perf_config_item__delete(item);
535 } 725 }
536 return 0;
537} 726}
538 727
539static void check_buildid_dir_config(void) 728static void perf_config_section__delete(struct perf_config_section *section)
729{
730 perf_config_section__purge(section);
731 zfree(&section->name);
732 free(section);
733}
734
735static void perf_config_set__purge(struct perf_config_set *set)
540{ 736{
541 struct buildid_dir_config c; 737 struct perf_config_section *section, *tmp;
542 c.dir = buildid_dir; 738
543 perf_config(buildid_dir_command_config, &c); 739 list_for_each_entry_safe(section, tmp, &set->sections, node) {
740 list_del_init(&section->node);
741 perf_config_section__delete(section);
742 }
743}
744
745void perf_config_set__delete(struct perf_config_set *set)
746{
747 if (set == NULL)
748 return;
749
750 perf_config_set__purge(set);
751 free(set);
752}
753
754/*
755 * Call this to report error for your variable that should not
756 * get a boolean value (i.e. "[my] var" means "true").
757 */
758int config_error_nonbool(const char *var)
759{
760 return error("Missing value for '%s'", var);
544} 761}
545 762
546void set_buildid_dir(const char *dir) 763void set_buildid_dir(const char *dir)
@@ -548,16 +765,13 @@ void set_buildid_dir(const char *dir)
548 if (dir) 765 if (dir)
549 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir); 766 scnprintf(buildid_dir, MAXPATHLEN-1, "%s", dir);
550 767
551 /* try config file */
552 if (buildid_dir[0] == '\0')
553 check_buildid_dir_config();
554
555 /* default to $HOME/.debug */ 768 /* default to $HOME/.debug */
556 if (buildid_dir[0] == '\0') { 769 if (buildid_dir[0] == '\0') {
557 char *v = getenv("HOME"); 770 char *home = getenv("HOME");
558 if (v) { 771
772 if (home) {
559 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s", 773 snprintf(buildid_dir, MAXPATHLEN-1, "%s/%s",
560 v, DEBUG_CACHE_DIR); 774 home, DEBUG_CACHE_DIR);
561 } else { 775 } else {
562 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1); 776 strncpy(buildid_dir, DEBUG_CACHE_DIR, MAXPATHLEN-1);
563 } 777 }
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
new file mode 100644
index 000000000000..6f813d46045e
--- /dev/null
+++ b/tools/perf/util/config.h
@@ -0,0 +1,66 @@
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
23extern const char *config_exclusive_filename;
24
25typedef int (*config_fn_t)(const char *, const char *, void *);
26int perf_default_config(const char *, const char *, void *);
27int perf_config(config_fn_t fn, void *);
28int perf_config_int(const char *, const char *);
29u64 perf_config_u64(const char *, const char *);
30int perf_config_bool(const char *, const char *);
31int config_error_nonbool(const char *);
32const char *perf_etc_perfconfig(void);
33
34struct perf_config_set *perf_config_set__new(void);
35void perf_config_set__delete(struct perf_config_set *set);
36void perf_config__init(void);
37void perf_config__exit(void);
38void perf_config__refresh(void);
39
40/**
41 * perf_config_sections__for_each - iterate thru all the sections
42 * @list: list_head instance to iterate
43 * @section: struct perf_config_section iterator
44 */
45#define perf_config_sections__for_each_entry(list, section) \
46 list_for_each_entry(section, list, node)
47
48/**
49 * perf_config_items__for_each - iterate thru all the items
50 * @list: list_head instance to iterate
51 * @item: struct perf_config_item iterator
52 */
53#define perf_config_items__for_each_entry(list, item) \
54 list_for_each_entry(item, list, node)
55
56/**
57 * perf_config_set__for_each - iterate thru all the config section-item pairs
58 * @set: evlist instance to iterate
59 * @section: struct perf_config_section iterator
60 * @item: struct perf_config_item iterator
61 */
62#define perf_config_set__for_each_entry(set, section, item) \
63 perf_config_sections__for_each_entry(&set->sections, section) \
64 perf_config_items__for_each_entry(&section->items, item)
65
66#endif /* __PERF_CONFIG_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 9bcf2bed3a6d..2c0b52264a46 100644
--- a/tools/perf/util/cpumap.c
+++ b/tools/perf/util/cpumap.c
@@ -236,13 +236,12 @@ struct cpu_map *cpu_map__new_data(struct cpu_map_data *data)
236 236
237size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp) 237size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp)
238{ 238{
239 int i; 239#define BUFSIZE 1024
240 size_t printed = fprintf(fp, "%d cpu%s: ", 240 char buf[BUFSIZE];
241 map->nr, map->nr > 1 ? "s" : "");
242 for (i = 0; i < map->nr; ++i)
243 printed += fprintf(fp, "%s%d", i ? ", " : "", map->map[i]);
244 241
245 return printed + fprintf(fp, "\n"); 242 cpu_map__snprint(map, buf, sizeof(buf));
243 return fprintf(fp, "%s\n", buf);
244#undef BUFSIZE
246} 245}
247 246
248struct cpu_map *cpu_map__dummy_new(void) 247struct cpu_map *cpu_map__dummy_new(void)
@@ -587,3 +586,68 @@ int cpu__setup_cpunode_map(void)
587 closedir(dir1); 586 closedir(dir1);
588 return 0; 587 return 0;
589} 588}
589
590bool cpu_map__has(struct cpu_map *cpus, int cpu)
591{
592 return cpu_map__idx(cpus, cpu) != -1;
593}
594
595int cpu_map__idx(struct cpu_map *cpus, int cpu)
596{
597 int i;
598
599 for (i = 0; i < cpus->nr; ++i) {
600 if (cpus->map[i] == cpu)
601 return i;
602 }
603
604 return -1;
605}
606
607int cpu_map__cpu(struct cpu_map *cpus, int idx)
608{
609 return cpus->map[idx];
610}
611
612size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size)
613{
614 int i, cpu, start = -1;
615 bool first = true;
616 size_t ret = 0;
617
618#define COMMA first ? "" : ","
619
620 for (i = 0; i < map->nr + 1; i++) {
621 bool last = i == map->nr;
622
623 cpu = last ? INT_MAX : map->map[i];
624
625 if (start == -1) {
626 start = i;
627 if (last) {
628 ret += snprintf(buf + ret, size - ret,
629 "%s%d", COMMA,
630 map->map[i]);
631 }
632 } else if (((i - start) != (cpu - map->map[start])) || last) {
633 int end = i - 1;
634
635 if (start == end) {
636 ret += snprintf(buf + ret, size - ret,
637 "%s%d", COMMA,
638 map->map[start]);
639 } else {
640 ret += snprintf(buf + ret, size - ret,
641 "%s%d-%d", COMMA,
642 map->map[start], map->map[end]);
643 }
644 first = false;
645 start = i;
646 }
647 }
648
649#undef COMMA
650
651 pr_debug("cpumask list: %s\n", buf);
652 return ret;
653}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 81a2562aaa2b..06bd689f5989 100644
--- a/tools/perf/util/cpumap.h
+++ b/tools/perf/util/cpumap.h
@@ -19,6 +19,7 @@ struct cpu_map *cpu_map__empty_new(int nr);
19struct cpu_map *cpu_map__dummy_new(void); 19struct cpu_map *cpu_map__dummy_new(void);
20struct cpu_map *cpu_map__new_data(struct cpu_map_data *data); 20struct cpu_map *cpu_map__new_data(struct cpu_map_data *data);
21struct cpu_map *cpu_map__read(FILE *file); 21struct cpu_map *cpu_map__read(FILE *file);
22size_t cpu_map__snprint(struct cpu_map *map, char *buf, size_t size);
22size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp); 23size_t cpu_map__fprintf(struct cpu_map *map, FILE *fp);
23int cpu_map__get_socket_id(int cpu); 24int cpu_map__get_socket_id(int cpu);
24int cpu_map__get_socket(struct cpu_map *map, int idx, void *data); 25int cpu_map__get_socket(struct cpu_map *map, int idx, void *data);
@@ -66,4 +67,8 @@ int cpu__get_node(int cpu);
66int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, 67int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res,
67 int (*f)(struct cpu_map *map, int cpu, void *data), 68 int (*f)(struct cpu_map *map, int cpu, void *data),
68 void *data); 69 void *data);
70
71int cpu_map__cpu(struct cpu_map *cpus, int idx);
72bool cpu_map__has(struct cpu_map *cpus, int cpu);
73int cpu_map__idx(struct cpu_map *cpus, int cpu);
69#endif /* __PERF_CPUMAP_H */ 74#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index bbf69d248ec5..4f979bb27b6c 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -26,6 +26,7 @@
26#include "evlist.h" 26#include "evlist.h"
27#include "evsel.h" 27#include "evsel.h"
28#include "machine.h" 28#include "machine.h"
29#include "config.h"
29 30
30#define pr_N(n, fmt, ...) \ 31#define pr_N(n, fmt, ...) \
31 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) 32 eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
@@ -68,6 +69,9 @@ struct ctf_writer {
68 }; 69 };
69 struct bt_ctf_field_type *array[6]; 70 struct bt_ctf_field_type *array[6];
70 } data; 71 } data;
72 struct bt_ctf_event_class *comm_class;
73 struct bt_ctf_event_class *exit_class;
74 struct bt_ctf_event_class *fork_class;
71}; 75};
72 76
73struct convert { 77struct convert {
@@ -76,6 +80,7 @@ struct convert {
76 80
77 u64 events_size; 81 u64 events_size;
78 u64 events_count; 82 u64 events_count;
83 u64 non_sample_count;
79 84
80 /* Ordered events configured queue size. */ 85 /* Ordered events configured queue size. */
81 u64 queue_size; 86 u64 queue_size;
@@ -140,6 +145,36 @@ FUNC_VALUE_SET(s64)
140FUNC_VALUE_SET(u64) 145FUNC_VALUE_SET(u64)
141__FUNC_VALUE_SET(u64_hex, u64) 146__FUNC_VALUE_SET(u64_hex, u64)
142 147
148static int string_set_value(struct bt_ctf_field *field, const char *string);
149static __maybe_unused int
150value_set_string(struct ctf_writer *cw, struct bt_ctf_event *event,
151 const char *name, const char *string)
152{
153 struct bt_ctf_field_type *type = cw->data.string;
154 struct bt_ctf_field *field;
155 int ret = 0;
156
157 field = bt_ctf_field_create(type);
158 if (!field) {
159 pr_err("failed to create a field %s\n", name);
160 return -1;
161 }
162
163 ret = string_set_value(field, string);
164 if (ret) {
165 pr_err("failed to set value %s\n", name);
166 goto err_put_field;
167 }
168
169 ret = bt_ctf_event_set_payload(event, name, field);
170 if (ret)
171 pr_err("failed to set payload %s\n", name);
172
173err_put_field:
174 bt_ctf_field_put(field);
175 return ret;
176}
177
143static struct bt_ctf_field_type* 178static struct bt_ctf_field_type*
144get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) 179get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
145{ 180{
@@ -204,6 +239,44 @@ static unsigned long long adjust_signedness(unsigned long long value_int, int si
204 return (value_int & value_mask) | ~value_mask; 239 return (value_int & value_mask) | ~value_mask;
205} 240}
206 241
242static int string_set_value(struct bt_ctf_field *field, const char *string)
243{
244 char *buffer = NULL;
245 size_t len = strlen(string), i, p;
246 int err;
247
248 for (i = p = 0; i < len; i++, p++) {
249 if (isprint(string[i])) {
250 if (!buffer)
251 continue;
252 buffer[p] = string[i];
253 } else {
254 char numstr[5];
255
256 snprintf(numstr, sizeof(numstr), "\\x%02x",
257 (unsigned int)(string[i]) & 0xff);
258
259 if (!buffer) {
260 buffer = zalloc(i + (len - i) * 4 + 2);
261 if (!buffer) {
262 pr_err("failed to set unprintable string '%s'\n", string);
263 return bt_ctf_field_string_set_value(field, "UNPRINTABLE-STRING");
264 }
265 if (i > 0)
266 strncpy(buffer, string, i);
267 }
268 strncat(buffer + p, numstr, 4);
269 p += 3;
270 }
271 }
272
273 if (!buffer)
274 return bt_ctf_field_string_set_value(field, string);
275 err = bt_ctf_field_string_set_value(field, buffer);
276 free(buffer);
277 return err;
278}
279
207static int add_tracepoint_field_value(struct ctf_writer *cw, 280static int add_tracepoint_field_value(struct ctf_writer *cw,
208 struct bt_ctf_event_class *event_class, 281 struct bt_ctf_event_class *event_class,
209 struct bt_ctf_event *event, 282 struct bt_ctf_event *event,
@@ -270,8 +343,7 @@ static int add_tracepoint_field_value(struct ctf_writer *cw,
270 } 343 }
271 344
272 if (flags & FIELD_IS_STRING) 345 if (flags & FIELD_IS_STRING)
273 ret = bt_ctf_field_string_set_value(field, 346 ret = string_set_value(field, data + offset + i * len);
274 data + offset + i * len);
275 else { 347 else {
276 unsigned long long value_int; 348 unsigned long long value_int;
277 349
@@ -694,6 +766,72 @@ static int process_sample_event(struct perf_tool *tool,
694 return cs ? 0 : -1; 766 return cs ? 0 : -1;
695} 767}
696 768
769#define __NON_SAMPLE_SET_FIELD(_name, _type, _field) \
770do { \
771 ret = value_set_##_type(cw, event, #_field, _event->_name._field);\
772 if (ret) \
773 return -1; \
774} while(0)
775
776#define __FUNC_PROCESS_NON_SAMPLE(_name, body) \
777static int process_##_name##_event(struct perf_tool *tool, \
778 union perf_event *_event, \
779 struct perf_sample *sample, \
780 struct machine *machine) \
781{ \
782 struct convert *c = container_of(tool, struct convert, tool);\
783 struct ctf_writer *cw = &c->writer; \
784 struct bt_ctf_event_class *event_class = cw->_name##_class;\
785 struct bt_ctf_event *event; \
786 struct ctf_stream *cs; \
787 int ret; \
788 \
789 c->non_sample_count++; \
790 c->events_size += _event->header.size; \
791 event = bt_ctf_event_create(event_class); \
792 if (!event) { \
793 pr_err("Failed to create an CTF event\n"); \
794 return -1; \
795 } \
796 \
797 bt_ctf_clock_set_time(cw->clock, sample->time); \
798 body \
799 cs = ctf_stream(cw, 0); \
800 if (cs) { \
801 if (is_flush_needed(cs)) \
802 ctf_stream__flush(cs); \
803 \
804 cs->count++; \
805 bt_ctf_stream_append_event(cs->stream, event); \
806 } \
807 bt_ctf_event_put(event); \
808 \
809 return perf_event__process_##_name(tool, _event, sample, machine);\
810}
811
812__FUNC_PROCESS_NON_SAMPLE(comm,
813 __NON_SAMPLE_SET_FIELD(comm, u32, pid);
814 __NON_SAMPLE_SET_FIELD(comm, u32, tid);
815 __NON_SAMPLE_SET_FIELD(comm, string, comm);
816)
817__FUNC_PROCESS_NON_SAMPLE(fork,
818 __NON_SAMPLE_SET_FIELD(fork, u32, pid);
819 __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
820 __NON_SAMPLE_SET_FIELD(fork, u32, tid);
821 __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
822 __NON_SAMPLE_SET_FIELD(fork, u64, time);
823)
824
825__FUNC_PROCESS_NON_SAMPLE(exit,
826 __NON_SAMPLE_SET_FIELD(fork, u32, pid);
827 __NON_SAMPLE_SET_FIELD(fork, u32, ppid);
828 __NON_SAMPLE_SET_FIELD(fork, u32, tid);
829 __NON_SAMPLE_SET_FIELD(fork, u32, ptid);
830 __NON_SAMPLE_SET_FIELD(fork, u64, time);
831)
832#undef __NON_SAMPLE_SET_FIELD
833#undef __FUNC_PROCESS_NON_SAMPLE
834
697/* If dup < 0, add a prefix. Else, add _dupl_X suffix. */ 835/* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
698static char *change_name(char *name, char *orig_name, int dup) 836static char *change_name(char *name, char *orig_name, int dup)
699{ 837{
@@ -960,7 +1098,7 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
960 struct perf_evsel *evsel; 1098 struct perf_evsel *evsel;
961 int ret; 1099 int ret;
962 1100
963 evlist__for_each(evlist, evsel) { 1101 evlist__for_each_entry(evlist, evsel) {
964 ret = add_event(cw, evsel); 1102 ret = add_event(cw, evsel);
965 if (ret) 1103 if (ret)
966 return ret; 1104 return ret;
@@ -968,12 +1106,86 @@ static int setup_events(struct ctf_writer *cw, struct perf_session *session)
968 return 0; 1106 return 0;
969} 1107}
970 1108
1109#define __NON_SAMPLE_ADD_FIELD(t, n) \
1110 do { \
1111 pr2(" field '%s'\n", #n); \
1112 if (bt_ctf_event_class_add_field(event_class, cw->data.t, #n)) {\
1113 pr_err("Failed to add field '%s';\n", #n);\
1114 return -1; \
1115 } \
1116 } while(0)
1117
1118#define __FUNC_ADD_NON_SAMPLE_EVENT_CLASS(_name, body) \
1119static int add_##_name##_event(struct ctf_writer *cw) \
1120{ \
1121 struct bt_ctf_event_class *event_class; \
1122 int ret; \
1123 \
1124 pr("Adding "#_name" event\n"); \
1125 event_class = bt_ctf_event_class_create("perf_" #_name);\
1126 if (!event_class) \
1127 return -1; \
1128 body \
1129 \
1130 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);\
1131 if (ret) { \
1132 pr("Failed to add event class '"#_name"' into stream.\n");\
1133 return ret; \
1134 } \
1135 \
1136 cw->_name##_class = event_class; \
1137 bt_ctf_event_class_put(event_class); \
1138 return 0; \
1139}
1140
1141__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(comm,
1142 __NON_SAMPLE_ADD_FIELD(u32, pid);
1143 __NON_SAMPLE_ADD_FIELD(u32, tid);
1144 __NON_SAMPLE_ADD_FIELD(string, comm);
1145)
1146
1147__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(fork,
1148 __NON_SAMPLE_ADD_FIELD(u32, pid);
1149 __NON_SAMPLE_ADD_FIELD(u32, ppid);
1150 __NON_SAMPLE_ADD_FIELD(u32, tid);
1151 __NON_SAMPLE_ADD_FIELD(u32, ptid);
1152 __NON_SAMPLE_ADD_FIELD(u64, time);
1153)
1154
1155__FUNC_ADD_NON_SAMPLE_EVENT_CLASS(exit,
1156 __NON_SAMPLE_ADD_FIELD(u32, pid);
1157 __NON_SAMPLE_ADD_FIELD(u32, ppid);
1158 __NON_SAMPLE_ADD_FIELD(u32, tid);
1159 __NON_SAMPLE_ADD_FIELD(u32, ptid);
1160 __NON_SAMPLE_ADD_FIELD(u64, time);
1161)
1162
1163#undef __NON_SAMPLE_ADD_FIELD
1164#undef __FUNC_ADD_NON_SAMPLE_EVENT_CLASS
1165
1166static int setup_non_sample_events(struct ctf_writer *cw,
1167 struct perf_session *session __maybe_unused)
1168{
1169 int ret;
1170
1171 ret = add_comm_event(cw);
1172 if (ret)
1173 return ret;
1174 ret = add_exit_event(cw);
1175 if (ret)
1176 return ret;
1177 ret = add_fork_event(cw);
1178 if (ret)
1179 return ret;
1180 return 0;
1181}
1182
971static void cleanup_events(struct perf_session *session) 1183static void cleanup_events(struct perf_session *session)
972{ 1184{
973 struct perf_evlist *evlist = session->evlist; 1185 struct perf_evlist *evlist = session->evlist;
974 struct perf_evsel *evsel; 1186 struct perf_evsel *evsel;
975 1187
976 evlist__for_each(evlist, evsel) { 1188 evlist__for_each_entry(evlist, evsel) {
977 struct evsel_priv *priv; 1189 struct evsel_priv *priv;
978 1190
979 priv = evsel->priv; 1191 priv = evsel->priv;
@@ -1236,13 +1448,14 @@ static int convert__config(const char *var, const char *value, void *cb)
1236 return 0; 1448 return 0;
1237} 1449}
1238 1450
1239int bt_convert__perf2ctf(const char *input, const char *path, bool force) 1451int bt_convert__perf2ctf(const char *input, const char *path,
1452 struct perf_data_convert_opts *opts)
1240{ 1453{
1241 struct perf_session *session; 1454 struct perf_session *session;
1242 struct perf_data_file file = { 1455 struct perf_data_file file = {
1243 .path = input, 1456 .path = input,
1244 .mode = PERF_DATA_MODE_READ, 1457 .mode = PERF_DATA_MODE_READ,
1245 .force = force, 1458 .force = opts->force,
1246 }; 1459 };
1247 struct convert c = { 1460 struct convert c = {
1248 .tool = { 1461 .tool = {
@@ -1262,6 +1475,12 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
1262 struct ctf_writer *cw = &c.writer; 1475 struct ctf_writer *cw = &c.writer;
1263 int err = -1; 1476 int err = -1;
1264 1477
1478 if (opts->all) {
1479 c.tool.comm = process_comm_event;
1480 c.tool.exit = process_exit_event;
1481 c.tool.fork = process_fork_event;
1482 }
1483
1265 perf_config(convert__config, &c); 1484 perf_config(convert__config, &c);
1266 1485
1267 /* CTF writer */ 1486 /* CTF writer */
@@ -1286,6 +1505,9 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
1286 if (setup_events(cw, session)) 1505 if (setup_events(cw, session))
1287 goto free_session; 1506 goto free_session;
1288 1507
1508 if (opts->all && setup_non_sample_events(cw, session))
1509 goto free_session;
1510
1289 if (setup_streams(cw, session)) 1511 if (setup_streams(cw, session))
1290 goto free_session; 1512 goto free_session;
1291 1513
@@ -1300,10 +1522,15 @@ int bt_convert__perf2ctf(const char *input, const char *path, bool force)
1300 file.path, path); 1522 file.path, path);
1301 1523
1302 fprintf(stderr, 1524 fprintf(stderr,
1303 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n", 1525 "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples",
1304 (double) c.events_size / 1024.0 / 1024.0, 1526 (double) c.events_size / 1024.0 / 1024.0,
1305 c.events_count); 1527 c.events_count);
1306 1528
1529 if (!c.non_sample_count)
1530 fprintf(stderr, ") ]\n");
1531 else
1532 fprintf(stderr, ", %" PRIu64 " non-samples) ]\n", c.non_sample_count);
1533
1307 cleanup_events(session); 1534 cleanup_events(session);
1308 perf_session__delete(session); 1535 perf_session__delete(session);
1309 ctf_writer__cleanup(cw); 1536 ctf_writer__cleanup(cw);
diff --git a/tools/perf/util/data-convert-bt.h b/tools/perf/util/data-convert-bt.h
index 4c204342a9d8..9a3b587f76c1 100644
--- a/tools/perf/util/data-convert-bt.h
+++ b/tools/perf/util/data-convert-bt.h
@@ -1,8 +1,10 @@
1#ifndef __DATA_CONVERT_BT_H 1#ifndef __DATA_CONVERT_BT_H
2#define __DATA_CONVERT_BT_H 2#define __DATA_CONVERT_BT_H
3#include "data-convert.h"
3#ifdef HAVE_LIBBABELTRACE_SUPPORT 4#ifdef HAVE_LIBBABELTRACE_SUPPORT
4 5
5int bt_convert__perf2ctf(const char *input_name, const char *to_ctf, bool force); 6int bt_convert__perf2ctf(const char *input_name, const char *to_ctf,
7 struct perf_data_convert_opts *opts);
6 8
7#endif /* HAVE_LIBBABELTRACE_SUPPORT */ 9#endif /* HAVE_LIBBABELTRACE_SUPPORT */
8#endif /* __DATA_CONVERT_BT_H */ 10#endif /* __DATA_CONVERT_BT_H */
diff --git a/tools/perf/util/data-convert.h b/tools/perf/util/data-convert.h
new file mode 100644
index 000000000000..5314962fe95b
--- /dev/null
+++ b/tools/perf/util/data-convert.h
@@ -0,0 +1,9 @@
1#ifndef __DATA_CONVERT_H
2#define __DATA_CONVERT_H
3
4struct perf_data_convert_opts {
5 bool force;
6 bool all;
7};
8
9#endif /* __DATA_CONVERT_H */
diff --git a/tools/perf/util/data.c b/tools/perf/util/data.c
index 1921942fc2e0..60bfc9ca1e22 100644
--- a/tools/perf/util/data.c
+++ b/tools/perf/util/data.c
@@ -57,7 +57,7 @@ static int open_file_read(struct perf_data_file *file)
57 int err = errno; 57 int err = errno;
58 58
59 pr_err("failed to open %s: %s", file->path, 59 pr_err("failed to open %s: %s", file->path,
60 strerror_r(err, sbuf, sizeof(sbuf))); 60 str_error_r(err, sbuf, sizeof(sbuf)));
61 if (err == ENOENT && !strcmp(file->path, "perf.data")) 61 if (err == ENOENT && !strcmp(file->path, "perf.data"))
62 pr_err(" (try 'perf record' first)"); 62 pr_err(" (try 'perf record' first)");
63 pr_err("\n"); 63 pr_err("\n");
@@ -99,7 +99,7 @@ static int open_file_write(struct perf_data_file *file)
99 99
100 if (fd < 0) 100 if (fd < 0)
101 pr_err("failed to open %s : %s\n", file->path, 101 pr_err("failed to open %s : %s\n", file->path,
102 strerror_r(errno, sbuf, sizeof(sbuf))); 102 str_error_r(errno, sbuf, sizeof(sbuf)));
103 103
104 return fd; 104 return fd;
105} 105}
@@ -136,3 +136,44 @@ ssize_t perf_data_file__write(struct perf_data_file *file,
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}
diff --git a/tools/perf/util/data.h b/tools/perf/util/data.h
index 2b15d0c95c7f..ae510ce16cb1 100644
--- a/tools/perf/util/data.h
+++ b/tools/perf/util/data.h
@@ -46,5 +46,14 @@ int perf_data_file__open(struct perf_data_file *file);
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 */
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index 049438d51b9a..b0c2b5c5d337 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -23,6 +23,8 @@
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 {
@@ -231,17 +233,6 @@ int db_export__symbol(struct db_export *dbe, struct symbol *sym,
231 return 0; 233 return 0;
232} 234}
233 235
234static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
235{
236 if (thread->pid_ == thread->tid)
237 return thread__get(thread);
238
239 if (thread->pid_ == -1)
240 return NULL;
241
242 return machine__find_thread(machine, thread->pid_, thread->pid_);
243}
244
245static int db_ids_from_al(struct db_export *dbe, struct addr_location *al, 236static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
246 u64 *dso_db_id, u64 *sym_db_id, u64 *offset) 237 u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
247{ 238{
@@ -258,8 +249,7 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
258 if (!al->sym) { 249 if (!al->sym) {
259 al->sym = symbol__new(al->addr, 0, 0, "unknown"); 250 al->sym = symbol__new(al->addr, 0, 0, "unknown");
260 if (al->sym) 251 if (al->sym)
261 symbols__insert(&dso->symbols[al->map->type], 252 dso__insert_symbol(dso, al->map->type, al->sym);
262 al->sym);
263 } 253 }
264 254
265 if (al->sym) { 255 if (al->sym) {
@@ -276,6 +266,79 @@ static int db_ids_from_al(struct db_export *dbe, struct addr_location *al,
276 return 0; 266 return 0;
277} 267}
278 268
269static struct call_path *call_path_from_sample(struct db_export *dbe,
270 struct machine *machine,
271 struct thread *thread,
272 struct perf_sample *sample,
273 struct perf_evsel *evsel)
274{
275 u64 kernel_start = machine__kernel_start(machine);
276 struct call_path *current = &dbe->cpr->call_path;
277 enum chain_order saved_order = callchain_param.order;
278 int err;
279
280 if (!symbol_conf.use_callchain || !sample->callchain)
281 return NULL;
282
283 /*
284 * Since the call path tree must be built starting with the root, we
285 * must use ORDER_CALL for call chain resolution, in order to process
286 * the callchain starting with the root node and ending with the leaf.
287 */
288 callchain_param.order = ORDER_CALLER;
289 err = thread__resolve_callchain(thread, &callchain_cursor, evsel,
290 sample, NULL, NULL, PERF_MAX_STACK_DEPTH);
291 if (err) {
292 callchain_param.order = saved_order;
293 return NULL;
294 }
295 callchain_cursor_commit(&callchain_cursor);
296
297 while (1) {
298 struct callchain_cursor_node *node;
299 struct addr_location al;
300 u64 dso_db_id = 0, sym_db_id = 0, offset = 0;
301
302 memset(&al, 0, sizeof(al));
303
304 node = callchain_cursor_current(&callchain_cursor);
305 if (!node)
306 break;
307 /*
308 * Handle export of symbol and dso for this node by
309 * constructing an addr_location struct and then passing it to
310 * db_ids_from_al() to perform the export.
311 */
312 al.sym = node->sym;
313 al.map = node->map;
314 al.machine = machine;
315 al.addr = node->ip;
316
317 if (al.map && !al.sym)
318 al.sym = dso__find_symbol(al.map->dso, MAP__FUNCTION,
319 al.addr);
320
321 db_ids_from_al(dbe, &al, &dso_db_id, &sym_db_id, &offset);
322
323 /* add node to the call path tree if it doesn't exist */
324 current = call_path__findnew(dbe->cpr, current,
325 al.sym, node->ip,
326 kernel_start);
327
328 callchain_cursor_advance(&callchain_cursor);
329 }
330
331 /* Reset the callchain order to its prior value. */
332 callchain_param.order = saved_order;
333
334 if (current == &dbe->cpr->call_path) {
335 /* Bail because the callchain was empty. */
336 return NULL;
337 }
338
339 return current;
340}
341
279int db_export__branch_type(struct db_export *dbe, u32 branch_type, 342int db_export__branch_type(struct db_export *dbe, u32 branch_type,
280 const char *name) 343 const char *name)
281{ 344{
@@ -308,7 +371,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
308 if (err) 371 if (err)
309 return err; 372 return err;
310 373
311 main_thread = get_main_thread(al->machine, thread); 374 main_thread = thread__main_thread(al->machine, thread);
312 if (main_thread) 375 if (main_thread)
313 comm = machine__thread_exec_comm(al->machine, main_thread); 376 comm = machine__thread_exec_comm(al->machine, main_thread);
314 377
@@ -329,6 +392,16 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
329 if (err) 392 if (err)
330 goto out_put; 393 goto out_put;
331 394
395 if (dbe->cpr) {
396 struct call_path *cp = call_path_from_sample(dbe, al->machine,
397 thread, sample,
398 evsel);
399 if (cp) {
400 db_export__call_path(dbe, cp);
401 es.call_path_id = cp->db_id;
402 }
403 }
404
332 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 405 if ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
333 sample_addr_correlates_sym(&evsel->attr)) { 406 sample_addr_correlates_sym(&evsel->attr)) {
334 struct addr_location addr_al; 407 struct addr_location addr_al;
diff --git a/tools/perf/util/db-export.h b/tools/perf/util/db-export.h
index 25e22fd76aca..67bc6b8ad2d6 100644
--- a/tools/perf/util/db-export.h
+++ b/tools/perf/util/db-export.h
@@ -27,6 +27,7 @@ struct dso;
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 {
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 {
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;
diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index 14bafda79eda..d242adc3d5a2 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -38,7 +38,7 @@ extern int debug_data_convert;
38#define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__) 38#define pr_oe_time(t, fmt, ...) pr_time_N(1, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
39#define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__) 39#define pr_oe_time2(t, fmt, ...) pr_time_N(2, debug_ordered_events, t, pr_fmt(fmt), ##__VA_ARGS__)
40 40
41#define STRERR_BUFSIZE 128 /* For the buffer size of strerror_r */ 41#define STRERR_BUFSIZE 128 /* For the buffer size of str_error_r */
42 42
43int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2))); 43int dump_printf(const char *fmt, ...) __attribute__((format(printf, 1, 2)));
44void trace_event(union perf_event *event); 44void trace_event(union perf_event *event);
diff --git a/tools/perf/util/demangle-rust.c b/tools/perf/util/demangle-rust.c
new file mode 100644
index 000000000000..f9dafa888c06
--- /dev/null
+++ b/tools/perf/util/demangle-rust.c
@@ -0,0 +1,269 @@
1#include <string.h>
2#include "util.h"
3#include "debug.h"
4
5#include "demangle-rust.h"
6
7/*
8 * Mangled Rust symbols look like this:
9 *
10 * _$LT$std..sys..fd..FileDesc$u20$as$u20$core..ops..Drop$GT$::drop::hc68340e1baa4987a
11 *
12 * The original symbol is:
13 *
14 * <std::sys::fd::FileDesc as core::ops::Drop>::drop
15 *
16 * The last component of the path is a 64-bit hash in lowercase hex, prefixed
17 * with "h". Rust does not have a global namespace between crates, an illusion
18 * which Rust maintains by using the hash to distinguish things that would
19 * otherwise have the same symbol.
20 *
21 * Any path component not starting with a XID_Start character is prefixed with
22 * "_".
23 *
24 * The following escape sequences are used:
25 *
26 * "," => $C$
27 * "@" => $SP$
28 * "*" => $BP$
29 * "&" => $RF$
30 * "<" => $LT$
31 * ">" => $GT$
32 * "(" => $LP$
33 * ")" => $RP$
34 * " " => $u20$
35 * "'" => $u27$
36 * "[" => $u5b$
37 * "]" => $u5d$
38 * "~" => $u7e$
39 *
40 * A double ".." means "::" and a single "." means "-".
41 *
42 * The only characters allowed in the mangled symbol are a-zA-Z0-9 and _.:$
43 */
44
45static const char *hash_prefix = "::h";
46static const size_t hash_prefix_len = 3;
47static const size_t hash_len = 16;
48
49static bool is_prefixed_hash(const char *start);
50static bool looks_like_rust(const char *sym, size_t len);
51static bool unescape(const char **in, char **out, const char *seq, char value);
52
53/*
54 * INPUT:
55 * sym: symbol that has been through BFD-demangling
56 *
57 * This function looks for the following indicators:
58 *
59 * 1. The hash must consist of "h" followed by 16 lowercase hex digits.
60 *
61 * 2. As a sanity check, the hash must use between 5 and 15 of the 16 possible
62 * hex digits. This is true of 99.9998% of hashes so once in your life you
63 * may see a false negative. The point is to notice path components that
64 * could be Rust hashes but are probably not, like "haaaaaaaaaaaaaaaa". In
65 * this case a false positive (non-Rust symbol has an important path
66 * component removed because it looks like a Rust hash) is worse than a
67 * false negative (the rare Rust symbol is not demangled) so this sets the
68 * balance in favor of false negatives.
69 *
70 * 3. There must be no characters other than a-zA-Z0-9 and _.:$
71 *
72 * 4. There must be no unrecognized $-sign sequences.
73 *
74 * 5. There must be no sequence of three or more dots in a row ("...").
75 */
76bool
77rust_is_mangled(const char *sym)
78{
79 size_t len, len_without_hash;
80
81 if (!sym)
82 return false;
83
84 len = strlen(sym);
85 if (len <= hash_prefix_len + hash_len)
86 /* Not long enough to contain "::h" + hash + something else */
87 return false;
88
89 len_without_hash = len - (hash_prefix_len + hash_len);
90 if (!is_prefixed_hash(sym + len_without_hash))
91 return false;
92
93 return looks_like_rust(sym, len_without_hash);
94}
95
96/*
97 * A hash is the prefix "::h" followed by 16 lowercase hex digits. The hex
98 * digits must comprise between 5 and 15 (inclusive) distinct digits.
99 */
100static bool is_prefixed_hash(const char *str)
101{
102 const char *end;
103 bool seen[16];
104 size_t i;
105 int count;
106
107 if (strncmp(str, hash_prefix, hash_prefix_len))
108 return false;
109 str += hash_prefix_len;
110
111 memset(seen, false, sizeof(seen));
112 for (end = str + hash_len; str < end; str++)
113 if (*str >= '0' && *str <= '9')
114 seen[*str - '0'] = true;
115 else if (*str >= 'a' && *str <= 'f')
116 seen[*str - 'a' + 10] = true;
117 else
118 return false;
119
120 /* Count how many distinct digits seen */
121 count = 0;
122 for (i = 0; i < 16; i++)
123 if (seen[i])
124 count++;
125
126 return count >= 5 && count <= 15;
127}
128
129static bool looks_like_rust(const char *str, size_t len)
130{
131 const char *end = str + len;
132
133 while (str < end)
134 switch (*str) {
135 case '$':
136 if (!strncmp(str, "$C$", 3))
137 str += 3;
138 else if (!strncmp(str, "$SP$", 4)
139 || !strncmp(str, "$BP$", 4)
140 || !strncmp(str, "$RF$", 4)
141 || !strncmp(str, "$LT$", 4)
142 || !strncmp(str, "$GT$", 4)
143 || !strncmp(str, "$LP$", 4)
144 || !strncmp(str, "$RP$", 4))
145 str += 4;
146 else if (!strncmp(str, "$u20$", 5)
147 || !strncmp(str, "$u27$", 5)
148 || !strncmp(str, "$u5b$", 5)
149 || !strncmp(str, "$u5d$", 5)
150 || !strncmp(str, "$u7e$", 5))
151 str += 5;
152 else
153 return false;
154 break;
155 case '.':
156 /* Do not allow three or more consecutive dots */
157 if (!strncmp(str, "...", 3))
158 return false;
159 /* Fall through */
160 case 'a' ... 'z':
161 case 'A' ... 'Z':
162 case '0' ... '9':
163 case '_':
164 case ':':
165 str++;
166 break;
167 default:
168 return false;
169 }
170
171 return true;
172}
173
174/*
175 * INPUT:
176 * sym: symbol for which rust_is_mangled(sym) returns true
177 *
178 * The input is demangled in-place because the mangled name is always longer
179 * than the demangled one.
180 */
181void
182rust_demangle_sym(char *sym)
183{
184 const char *in;
185 char *out;
186 const char *end;
187
188 if (!sym)
189 return;
190
191 in = sym;
192 out = sym;
193 end = sym + strlen(sym) - (hash_prefix_len + hash_len);
194
195 while (in < end)
196 switch (*in) {
197 case '$':
198 if (!(unescape(&in, &out, "$C$", ',')
199 || unescape(&in, &out, "$SP$", '@')
200 || unescape(&in, &out, "$BP$", '*')
201 || unescape(&in, &out, "$RF$", '&')
202 || unescape(&in, &out, "$LT$", '<')
203 || unescape(&in, &out, "$GT$", '>')
204 || unescape(&in, &out, "$LP$", '(')
205 || unescape(&in, &out, "$RP$", ')')
206 || unescape(&in, &out, "$u20$", ' ')
207 || unescape(&in, &out, "$u27$", '\'')
208 || unescape(&in, &out, "$u5b$", '[')
209 || unescape(&in, &out, "$u5d$", ']')
210 || unescape(&in, &out, "$u7e$", '~'))) {
211 pr_err("demangle-rust: unexpected escape sequence");
212 goto done;
213 }
214 break;
215 case '_':
216 /*
217 * If this is the start of a path component and the next
218 * character is an escape sequence, ignore the
219 * underscore. The mangler inserts an underscore to make
220 * sure the path component begins with a XID_Start
221 * character.
222 */
223 if ((in == sym || in[-1] == ':') && in[1] == '$')
224 in++;
225 else
226 *out++ = *in++;
227 break;
228 case '.':
229 if (in[1] == '.') {
230 /* ".." becomes "::" */
231 *out++ = ':';
232 *out++ = ':';
233 in += 2;
234 } else {
235 /* "." becomes "-" */
236 *out++ = '-';
237 in++;
238 }
239 break;
240 case 'a' ... 'z':
241 case 'A' ... 'Z':
242 case '0' ... '9':
243 case ':':
244 *out++ = *in++;
245 break;
246 default:
247 pr_err("demangle-rust: unexpected character '%c' in symbol\n",
248 *in);
249 goto done;
250 }
251
252done:
253 *out = '\0';
254}
255
256static bool unescape(const char **in, char **out, const char *seq, char value)
257{
258 size_t len = strlen(seq);
259
260 if (strncmp(*in, seq, len))
261 return false;
262
263 **out = value;
264
265 *in += len;
266 *out += 1;
267
268 return true;
269}
diff --git a/tools/perf/util/demangle-rust.h b/tools/perf/util/demangle-rust.h
new file mode 100644
index 000000000000..7b41ead7e0dd
--- /dev/null
+++ b/tools/perf/util/demangle-rust.h
@@ -0,0 +1,7 @@
1#ifndef __PERF_DEMANGLE_RUST
2#define __PERF_DEMANGLE_RUST 1
3
4bool rust_is_mangled(const char *str);
5void rust_demangle_sym(char *str);
6
7#endif /* __PERF_DEMANGLE_RUST */
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 8e6395439ca0..774f6ec884d5 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -7,6 +7,7 @@
7#include "auxtrace.h" 7#include "auxtrace.h"
8#include "util.h" 8#include "util.h"
9#include "debug.h" 9#include "debug.h"
10#include "vdso.h"
10 11
11char dso__symtab_origin(const struct dso *dso) 12char dso__symtab_origin(const struct dso *dso)
12{ 13{
@@ -38,7 +39,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
38 enum dso_binary_type type, 39 enum dso_binary_type type,
39 char *root_dir, char *filename, size_t size) 40 char *root_dir, char *filename, size_t size)
40{ 41{
41 char build_id_hex[BUILD_ID_SIZE * 2 + 1]; 42 char build_id_hex[SBUILD_ID_SIZE];
42 int ret = 0; 43 int ret = 0;
43 size_t len; 44 size_t len;
44 45
@@ -62,9 +63,7 @@ int dso__read_binary_type_filename(const struct dso *dso,
62 } 63 }
63 break; 64 break;
64 case DSO_BINARY_TYPE__BUILD_ID_CACHE: 65 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
65 /* skip the locally configured cache if a symfs is given */ 66 if (dso__build_id_filename(dso, filename, size) == NULL)
66 if (symbol_conf.symfs[0] ||
67 (dso__build_id_filename(dso, filename, size) == NULL))
68 ret = -1; 67 ret = -1;
69 break; 68 break;
70 69
@@ -336,7 +335,7 @@ static int do_open(char *name)
336 return fd; 335 return fd;
337 336
338 pr_debug("dso open failed: %s\n", 337 pr_debug("dso open failed: %s\n",
339 strerror_r(errno, sbuf, sizeof(sbuf))); 338 str_error_r(errno, sbuf, sizeof(sbuf)));
340 if (!dso__data_open_cnt || errno != EMFILE) 339 if (!dso__data_open_cnt || errno != EMFILE)
341 break; 340 break;
342 341
@@ -443,17 +442,27 @@ static rlim_t get_fd_limit(void)
443 return limit; 442 return limit;
444} 443}
445 444
446static bool may_cache_fd(void) 445static rlim_t fd_limit;
446
447/*
448 * Used only by tests/dso-data.c to reset the environment
449 * for tests. I dont expect we should change this during
450 * standard runtime.
451 */
452void reset_fd_limit(void)
447{ 453{
448 static rlim_t limit; 454 fd_limit = 0;
455}
449 456
450 if (!limit) 457static bool may_cache_fd(void)
451 limit = get_fd_limit(); 458{
459 if (!fd_limit)
460 fd_limit = get_fd_limit();
452 461
453 if (limit == RLIM_INFINITY) 462 if (fd_limit == RLIM_INFINITY)
454 return true; 463 return true;
455 464
456 return limit > (rlim_t) dso__data_open_cnt; 465 return fd_limit > (rlim_t) dso__data_open_cnt;
457} 466}
458 467
459/* 468/*
@@ -777,7 +786,7 @@ static int data_file_size(struct dso *dso, struct machine *machine)
777 if (fstat(dso->data.fd, &st) < 0) { 786 if (fstat(dso->data.fd, &st) < 0) {
778 ret = -errno; 787 ret = -errno;
779 pr_err("dso cache fstat failed: %s\n", 788 pr_err("dso cache fstat failed: %s\n",
780 strerror_r(errno, sbuf, sizeof(sbuf))); 789 str_error_r(errno, sbuf, sizeof(sbuf)));
781 dso->data.status = DSO_DATA_STATUS_ERROR; 790 dso->data.status = DSO_DATA_STATUS_ERROR;
782 goto out; 791 goto out;
783 } 792 }
@@ -1169,7 +1178,7 @@ bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1169 struct dso *pos; 1178 struct dso *pos;
1170 1179
1171 list_for_each_entry(pos, head, node) { 1180 list_for_each_entry(pos, head, node) {
1172 if (with_hits && !pos->hit) 1181 if (with_hits && !pos->hit && !dso__is_vdso(pos))
1173 continue; 1182 continue;
1174 if (pos->has_build_id) { 1183 if (pos->has_build_id) {
1175 have_build_id = true; 1184 have_build_id = true;
@@ -1301,7 +1310,7 @@ size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1301 1310
1302size_t dso__fprintf_buildid(struct dso *dso, FILE *fp) 1311size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
1303{ 1312{
1304 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1313 char sbuild_id[SBUILD_ID_SIZE];
1305 1314
1306 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1315 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1307 return fprintf(fp, "%s", sbuild_id); 1316 return fprintf(fp, "%s", sbuild_id);
@@ -1357,7 +1366,7 @@ int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
1357 BUG_ON(buflen == 0); 1366 BUG_ON(buflen == 0);
1358 1367
1359 if (errnum >= 0) { 1368 if (errnum >= 0) {
1360 const char *err = strerror_r(errnum, buf, buflen); 1369 const char *err = str_error_r(errnum, buf, buflen);
1361 1370
1362 if (err != buf) 1371 if (err != buf)
1363 scnprintf(buf, buflen, "%s", err); 1372 scnprintf(buf, buflen, "%s", err);
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index 0953280629cf..ecc4bbd3f82e 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -4,6 +4,7 @@
4#include <linux/atomic.h> 4#include <linux/atomic.h>
5#include <linux/types.h> 5#include <linux/types.h>
6#include <linux/rbtree.h> 6#include <linux/rbtree.h>
7#include <sys/types.h>
7#include <stdbool.h> 8#include <stdbool.h>
8#include <pthread.h> 9#include <pthread.h>
9#include <linux/types.h> 10#include <linux/types.h>
@@ -349,10 +350,17 @@ static inline bool dso__is_kcore(struct dso *dso)
349 dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE; 350 dso->binary_type == DSO_BINARY_TYPE__GUEST_KCORE;
350} 351}
351 352
353static inline bool dso__is_kallsyms(struct dso *dso)
354{
355 return dso->kernel && dso->long_name[0] != '/';
356}
357
352void dso__free_a2l(struct dso *dso); 358void dso__free_a2l(struct dso *dso);
353 359
354enum dso_type dso__type(struct dso *dso, struct machine *machine); 360enum dso_type dso__type(struct dso *dso, struct machine *machine);
355 361
356int dso__strerror_load(struct dso *dso, char *buf, size_t buflen); 362int dso__strerror_load(struct dso *dso, char *buf, size_t buflen);
357 363
364void reset_fd_limit(void);
365
358#endif /* __PERF_DSO */ 366#endif /* __PERF_DSO */
diff --git a/tools/perf/util/dwarf-aux.c b/tools/perf/util/dwarf-aux.c
index aea189b41cc8..a347b19c961a 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -915,8 +915,7 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf)
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)
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)
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_GETLOCATIONS 955#ifdef HAVE_DWARF_GETLOCATIONS
@@ -999,22 +992,24 @@ static int die_get_var_innermost_scope(Dwarf_Die *sp_die, Dwarf_Die *vr_die,
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)
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#else 1080#else
diff --git a/tools/perf/util/env.c b/tools/perf/util/env.c
index 49a11d9d8b8f..bb964e86b09d 100644
--- a/tools/perf/util/env.c
+++ b/tools/perf/util/env.c
@@ -18,10 +18,13 @@ void perf_env__exit(struct perf_env *env)
18 zfree(&env->cmdline_argv); 18 zfree(&env->cmdline_argv);
19 zfree(&env->sibling_cores); 19 zfree(&env->sibling_cores);
20 zfree(&env->sibling_threads); 20 zfree(&env->sibling_threads);
21 zfree(&env->numa_nodes);
22 zfree(&env->pmu_mappings); 21 zfree(&env->pmu_mappings);
23 zfree(&env->cpu); 22 zfree(&env->cpu);
24 23
24 for (i = 0; i < env->nr_numa_nodes; i++)
25 cpu_map__put(env->numa_nodes[i].map);
26 zfree(&env->numa_nodes);
27
25 for (i = 0; i < env->caches_cnt; i++) 28 for (i = 0; i < env->caches_cnt; i++)
26 cpu_cache_level__free(&env->caches[i]); 29 cpu_cache_level__free(&env->caches[i]);
27 zfree(&env->caches); 30 zfree(&env->caches);
diff --git a/tools/perf/util/env.h b/tools/perf/util/env.h
index 56cffb60a0b4..b164dfd2dcbf 100644
--- a/tools/perf/util/env.h
+++ b/tools/perf/util/env.h
@@ -2,6 +2,7 @@
2#define __PERF_ENV_H 2#define __PERF_ENV_H
3 3
4#include <linux/types.h> 4#include <linux/types.h>
5#include "cpumap.h"
5 6
6struct cpu_topology_map { 7struct cpu_topology_map {
7 int socket_id; 8 int socket_id;
@@ -18,6 +19,13 @@ struct cpu_cache_level {
18 char *map; 19 char *map;
19}; 20};
20 21
22struct numa_node {
23 u32 node;
24 u64 mem_total;
25 u64 mem_free;
26 struct cpu_map *map;
27};
28
21struct perf_env { 29struct perf_env {
22 char *hostname; 30 char *hostname;
23 char *os_release; 31 char *os_release;
@@ -40,11 +48,11 @@ struct perf_env {
40 const char **cmdline_argv; 48 const char **cmdline_argv;
41 char *sibling_cores; 49 char *sibling_cores;
42 char *sibling_threads; 50 char *sibling_threads;
43 char *numa_nodes;
44 char *pmu_mappings; 51 char *pmu_mappings;
45 struct cpu_topology_map *cpu; 52 struct cpu_topology_map *cpu;
46 struct cpu_cache_level *caches; 53 struct cpu_cache_level *caches;
47 int caches_cnt; 54 int caches_cnt;
55 struct numa_node *numa_nodes;
48}; 56};
49 57
50extern struct perf_env perf_env; 58extern struct perf_env perf_env;
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index edcf4ed4e99c..e20438b784be 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -45,6 +45,7 @@ static const char *perf_event__names[] = {
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)
@@ -672,6 +673,8 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
672 int err; 673 int err;
673 union perf_event *event; 674 union perf_event *event;
674 675
676 if (symbol_conf.kptr_restrict)
677 return -1;
675 if (map == NULL) 678 if (map == NULL)
676 return -1; 679 return -1;
677 680
@@ -1089,7 +1092,7 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
1089 struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data); 1092 struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
1090 size_t ret; 1093 size_t ret;
1091 1094
1092 ret = fprintf(fp, " nr: "); 1095 ret = fprintf(fp, ": ");
1093 1096
1094 if (cpus) 1097 if (cpus)
1095 ret += cpu_map__fprintf(cpus, fp); 1098 ret += cpu_map__fprintf(cpus, fp);
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 6bb1c928350d..8d363d5e65a2 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -233,6 +233,7 @@ enum perf_user_event_type { /* above any possible kernel type */
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_MAX 237 PERF_RECORD_HEADER_MAX
237}; 238};
238 239
@@ -469,6 +470,13 @@ struct stat_round_event {
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 {
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);
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 86a03836a83f..097b3ed77fdd 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -15,6 +15,7 @@
15#include "evlist.h" 15#include "evlist.h"
16#include "evsel.h" 16#include "evsel.h"
17#include "debug.h" 17#include "debug.h"
18#include "asm/bug.h"
18#include <unistd.h> 19#include <unistd.h>
19 20
20#include "parse-events.h" 21#include "parse-events.h"
@@ -27,8 +28,8 @@
27#include <linux/log2.h> 28#include <linux/log2.h>
28#include <linux/err.h> 29#include <linux/err.h>
29 30
30static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx); 31static void perf_mmap__munmap(struct perf_mmap *map);
31static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx); 32static void perf_mmap__put(struct perf_mmap *map);
32 33
33#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y)) 34#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
34#define SID(e, x, y) xyarray__entry(e->sample_id, x, y) 35#define SID(e, x, y) xyarray__entry(e->sample_id, x, y)
@@ -44,6 +45,7 @@ void perf_evlist__init(struct perf_evlist *evlist, struct cpu_map *cpus,
44 perf_evlist__set_maps(evlist, cpus, threads); 45 perf_evlist__set_maps(evlist, cpus, threads);
45 fdarray__init(&evlist->pollfd, 64); 46 fdarray__init(&evlist->pollfd, 64);
46 evlist->workload.pid = -1; 47 evlist->workload.pid = -1;
48 evlist->bkw_mmap_state = BKW_MMAP_NOTREADY;
47} 49}
48 50
49struct perf_evlist *perf_evlist__new(void) 51struct perf_evlist *perf_evlist__new(void)
@@ -99,7 +101,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
99{ 101{
100 struct perf_evsel *evsel; 102 struct perf_evsel *evsel;
101 103
102 evlist__for_each(evlist, evsel) 104 evlist__for_each_entry(evlist, evsel)
103 perf_evsel__calc_id_pos(evsel); 105 perf_evsel__calc_id_pos(evsel);
104 106
105 perf_evlist__set_id_pos(evlist); 107 perf_evlist__set_id_pos(evlist);
@@ -109,7 +111,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
109{ 111{
110 struct perf_evsel *pos, *n; 112 struct perf_evsel *pos, *n;
111 113
112 evlist__for_each_safe(evlist, n, pos) { 114 evlist__for_each_entry_safe(evlist, n, pos) {
113 list_del_init(&pos->node); 115 list_del_init(&pos->node);
114 pos->evlist = NULL; 116 pos->evlist = NULL;
115 perf_evsel__delete(pos); 117 perf_evsel__delete(pos);
@@ -121,11 +123,15 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
121void perf_evlist__exit(struct perf_evlist *evlist) 123void perf_evlist__exit(struct perf_evlist *evlist)
122{ 124{
123 zfree(&evlist->mmap); 125 zfree(&evlist->mmap);
126 zfree(&evlist->backward_mmap);
124 fdarray__exit(&evlist->pollfd); 127 fdarray__exit(&evlist->pollfd);
125} 128}
126 129
127void perf_evlist__delete(struct perf_evlist *evlist) 130void perf_evlist__delete(struct perf_evlist *evlist)
128{ 131{
132 if (evlist == NULL)
133 return;
134
129 perf_evlist__munmap(evlist); 135 perf_evlist__munmap(evlist);
130 perf_evlist__close(evlist); 136 perf_evlist__close(evlist);
131 cpu_map__put(evlist->cpus); 137 cpu_map__put(evlist->cpus);
@@ -160,7 +166,7 @@ static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
160{ 166{
161 struct perf_evsel *evsel; 167 struct perf_evsel *evsel;
162 168
163 evlist__for_each(evlist, evsel) 169 evlist__for_each_entry(evlist, evsel)
164 __perf_evlist__propagate_maps(evlist, evsel); 170 __perf_evlist__propagate_maps(evlist, evsel);
165} 171}
166 172
@@ -189,7 +195,7 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
189{ 195{
190 struct perf_evsel *evsel, *temp; 196 struct perf_evsel *evsel, *temp;
191 197
192 __evlist__for_each_safe(list, temp, evsel) { 198 __evlist__for_each_entry_safe(list, temp, evsel) {
193 list_del_init(&evsel->node); 199 list_del_init(&evsel->node);
194 perf_evlist__add(evlist, evsel); 200 perf_evlist__add(evlist, evsel);
195 } 201 }
@@ -204,7 +210,7 @@ void __perf_evlist__set_leader(struct list_head *list)
204 210
205 leader->nr_members = evsel->idx - leader->idx + 1; 211 leader->nr_members = evsel->idx - leader->idx + 1;
206 212
207 __evlist__for_each(list, evsel) { 213 __evlist__for_each_entry(list, evsel) {
208 evsel->leader = leader; 214 evsel->leader = leader;
209 } 215 }
210} 216}
@@ -233,31 +239,13 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
233 239
234int perf_evlist__add_default(struct perf_evlist *evlist) 240int perf_evlist__add_default(struct perf_evlist *evlist)
235{ 241{
236 struct perf_event_attr attr = { 242 struct perf_evsel *evsel = perf_evsel__new_cycles();
237 .type = PERF_TYPE_HARDWARE,
238 .config = PERF_COUNT_HW_CPU_CYCLES,
239 };
240 struct perf_evsel *evsel;
241
242 event_attr_init(&attr);
243 243
244 perf_event_attr__set_max_precise_ip(&attr);
245
246 evsel = perf_evsel__new(&attr);
247 if (evsel == NULL) 244 if (evsel == NULL)
248 goto error; 245 return -ENOMEM;
249
250 /* use asprintf() because free(evsel) assumes name is allocated */
251 if (asprintf(&evsel->name, "cycles%.*s",
252 attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
253 goto error_free;
254 246
255 perf_evlist__add(evlist, evsel); 247 perf_evlist__add(evlist, evsel);
256 return 0; 248 return 0;
257error_free:
258 perf_evsel__delete(evsel);
259error:
260 return -ENOMEM;
261} 249}
262 250
263int perf_evlist__add_dummy(struct perf_evlist *evlist) 251int perf_evlist__add_dummy(struct perf_evlist *evlist)
@@ -295,7 +283,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
295 return 0; 283 return 0;
296 284
297out_delete_partial_list: 285out_delete_partial_list:
298 __evlist__for_each_safe(&head, n, evsel) 286 __evlist__for_each_entry_safe(&head, n, evsel)
299 perf_evsel__delete(evsel); 287 perf_evsel__delete(evsel);
300 return -1; 288 return -1;
301} 289}
@@ -316,7 +304,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
316{ 304{
317 struct perf_evsel *evsel; 305 struct perf_evsel *evsel;
318 306
319 evlist__for_each(evlist, evsel) { 307 evlist__for_each_entry(evlist, evsel) {
320 if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 308 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
321 (int)evsel->attr.config == id) 309 (int)evsel->attr.config == id)
322 return evsel; 310 return evsel;
@@ -331,7 +319,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
331{ 319{
332 struct perf_evsel *evsel; 320 struct perf_evsel *evsel;
333 321
334 evlist__for_each(evlist, evsel) { 322 evlist__for_each_entry(evlist, evsel) {
335 if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && 323 if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
336 (strcmp(evsel->name, name) == 0)) 324 (strcmp(evsel->name, name) == 0))
337 return evsel; 325 return evsel;
@@ -366,7 +354,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
366{ 354{
367 struct perf_evsel *pos; 355 struct perf_evsel *pos;
368 356
369 evlist__for_each(evlist, pos) { 357 evlist__for_each_entry(evlist, pos) {
370 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 358 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
371 continue; 359 continue;
372 perf_evsel__disable(pos); 360 perf_evsel__disable(pos);
@@ -379,7 +367,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
379{ 367{
380 struct perf_evsel *pos; 368 struct perf_evsel *pos;
381 369
382 evlist__for_each(evlist, pos) { 370 evlist__for_each_entry(evlist, pos) {
383 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 371 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
384 continue; 372 continue;
385 perf_evsel__enable(pos); 373 perf_evsel__enable(pos);
@@ -447,7 +435,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
447 int nfds = 0; 435 int nfds = 0;
448 struct perf_evsel *evsel; 436 struct perf_evsel *evsel;
449 437
450 evlist__for_each(evlist, evsel) { 438 evlist__for_each_entry(evlist, evsel) {
451 if (evsel->system_wide) 439 if (evsel->system_wide)
452 nfds += nr_cpus; 440 nfds += nr_cpus;
453 else 441 else
@@ -461,15 +449,16 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
461 return 0; 449 return 0;
462} 450}
463 451
464static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx) 452static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd,
453 struct perf_mmap *map, short revent)
465{ 454{
466 int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP); 455 int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP);
467 /* 456 /*
468 * Save the idx so that when we filter out fds POLLHUP'ed we can 457 * Save the idx so that when we filter out fds POLLHUP'ed we can
469 * close the associated evlist->mmap[] entry. 458 * close the associated evlist->mmap[] entry.
470 */ 459 */
471 if (pos >= 0) { 460 if (pos >= 0) {
472 evlist->pollfd.priv[pos].idx = idx; 461 evlist->pollfd.priv[pos].ptr = map;
473 462
474 fcntl(fd, F_SETFL, O_NONBLOCK); 463 fcntl(fd, F_SETFL, O_NONBLOCK);
475 } 464 }
@@ -479,20 +468,22 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx
479 468
480int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 469int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
481{ 470{
482 return __perf_evlist__add_pollfd(evlist, fd, -1); 471 return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN);
483} 472}
484 473
485static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd) 474static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd,
475 void *arg __maybe_unused)
486{ 476{
487 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd); 477 struct perf_mmap *map = fda->priv[fd].ptr;
488 478
489 perf_evlist__mmap_put(evlist, fda->priv[fd].idx); 479 if (map)
480 perf_mmap__put(map);
490} 481}
491 482
492int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) 483int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
493{ 484{
494 return fdarray__filter(&evlist->pollfd, revents_and_mask, 485 return fdarray__filter(&evlist->pollfd, revents_and_mask,
495 perf_evlist__munmap_filtered); 486 perf_evlist__munmap_filtered, NULL);
496} 487}
497 488
498int perf_evlist__poll(struct perf_evlist *evlist, int timeout) 489int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
@@ -646,8 +637,8 @@ static int perf_evlist__event2id(struct perf_evlist *evlist,
646 return 0; 637 return 0;
647} 638}
648 639
649static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, 640struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
650 union perf_event *event) 641 union perf_event *event)
651{ 642{
652 struct perf_evsel *first = perf_evlist__first(evlist); 643 struct perf_evsel *first = perf_evlist__first(evlist);
653 struct hlist_head *head; 644 struct hlist_head *head;
@@ -679,53 +670,82 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
679 return NULL; 670 return NULL;
680} 671}
681 672
682union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 673static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
674{
675 int i;
676
677 if (!evlist->backward_mmap)
678 return 0;
679
680 for (i = 0; i < evlist->nr_mmaps; i++) {
681 int fd = evlist->backward_mmap[i].fd;
682 int err;
683
684 if (fd < 0)
685 continue;
686 err = ioctl(fd, PERF_EVENT_IOC_PAUSE_OUTPUT, value ? 1 : 0);
687 if (err)
688 return err;
689 }
690 return 0;
691}
692
693static int perf_evlist__pause(struct perf_evlist *evlist)
694{
695 return perf_evlist__set_paused(evlist, true);
696}
697
698static int perf_evlist__resume(struct perf_evlist *evlist)
699{
700 return perf_evlist__set_paused(evlist, false);
701}
702
703/* When check_messup is true, 'end' must points to a good entry */
704static union perf_event *
705perf_mmap__read(struct perf_mmap *md, bool check_messup, u64 start,
706 u64 end, u64 *prev)
683{ 707{
684 struct perf_mmap *md = &evlist->mmap[idx];
685 u64 head;
686 u64 old = md->prev;
687 unsigned char *data = md->base + page_size; 708 unsigned char *data = md->base + page_size;
688 union perf_event *event = NULL; 709 union perf_event *event = NULL;
710 int diff = end - start;
689 711
690 /* 712 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 /* 713 /*
699 * If we're further behind than half the buffer, there's a chance 714 * 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. 715 * the writer will bite our tail and mess up the samples under us.
701 * 716 *
702 * If we somehow ended up ahead of the head, we got messed up. 717 * If we somehow ended up ahead of the 'end', we got messed up.
703 * 718 *
704 * In either case, truncate and restart at head. 719 * In either case, truncate and restart at 'end'.
705 */ 720 */
706 int diff = head - old;
707 if (diff > md->mask / 2 || diff < 0) { 721 if (diff > md->mask / 2 || diff < 0) {
708 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n"); 722 fprintf(stderr, "WARNING: failed to keep up with mmap data.\n");
709 723
710 /* 724 /*
711 * head points to a known good entry, start there. 725 * 'end' points to a known good entry, start there.
712 */ 726 */
713 old = head; 727 start = end;
728 diff = 0;
714 } 729 }
715 } 730 }
716 731
717 if (old != head) { 732 if (diff >= (int)sizeof(event->header)) {
718 size_t size; 733 size_t size;
719 734
720 event = (union perf_event *)&data[old & md->mask]; 735 event = (union perf_event *)&data[start & md->mask];
721 size = event->header.size; 736 size = event->header.size;
722 737
738 if (size < sizeof(event->header) || diff < (int)size) {
739 event = NULL;
740 goto broken_event;
741 }
742
723 /* 743 /*
724 * Event straddles the mmap boundary -- header should always 744 * Event straddles the mmap boundary -- header should always
725 * be inside due to u64 alignment of output. 745 * be inside due to u64 alignment of output.
726 */ 746 */
727 if ((old & md->mask) + size != ((old + size) & md->mask)) { 747 if ((start & md->mask) + size != ((start + size) & md->mask)) {
728 unsigned int offset = old; 748 unsigned int offset = start;
729 unsigned int len = min(sizeof(*event), size), cpy; 749 unsigned int len = min(sizeof(*event), size), cpy;
730 void *dst = md->event_copy; 750 void *dst = md->event_copy;
731 751
@@ -740,44 +760,148 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
740 event = (union perf_event *) md->event_copy; 760 event = (union perf_event *) md->event_copy;
741 } 761 }
742 762
743 old += size; 763 start += size;
744 } 764 }
745 765
746 md->prev = old; 766broken_event:
767 if (prev)
768 *prev = start;
747 769
748 return event; 770 return event;
749} 771}
750 772
751static bool perf_mmap__empty(struct perf_mmap *md) 773union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messup)
752{ 774{
753 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; 775 u64 head;
776 u64 old = md->prev;
777
778 /*
779 * Check if event was unmapped due to a POLLHUP/POLLERR.
780 */
781 if (!atomic_read(&md->refcnt))
782 return NULL;
783
784 head = perf_mmap__read_head(md);
785
786 return perf_mmap__read(md, check_messup, old, head, &md->prev);
754} 787}
755 788
756static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 789union perf_event *
790perf_mmap__read_backward(struct perf_mmap *md)
757{ 791{
758 atomic_inc(&evlist->mmap[idx].refcnt); 792 u64 head, end;
793 u64 start = md->prev;
794
795 /*
796 * Check if event was unmapped due to a POLLHUP/POLLERR.
797 */
798 if (!atomic_read(&md->refcnt))
799 return NULL;
800
801 head = perf_mmap__read_head(md);
802 if (!head)
803 return NULL;
804
805 /*
806 * 'head' pointer starts from 0. Kernel minus sizeof(record) form
807 * it each time when kernel writes to it, so in fact 'head' is
808 * negative. 'end' pointer is made manually by adding the size of
809 * the ring buffer to 'head' pointer, means the validate data can
810 * read is the whole ring buffer. If 'end' is positive, the ring
811 * buffer has not fully filled, so we must adjust 'end' to 0.
812 *
813 * However, since both 'head' and 'end' is unsigned, we can't
814 * simply compare 'end' against 0. Here we compare '-head' and
815 * the size of the ring buffer, where -head is the number of bytes
816 * kernel write to the ring buffer.
817 */
818 if (-head < (u64)(md->mask + 1))
819 end = 0;
820 else
821 end = head + md->mask + 1;
822
823 return perf_mmap__read(md, false, start, end, &md->prev);
759} 824}
760 825
761static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) 826union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
762{ 827{
763 BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0); 828 struct perf_mmap *md = &evlist->mmap[idx];
764 829
765 if (atomic_dec_and_test(&evlist->mmap[idx].refcnt)) 830 /*
766 __perf_evlist__munmap(evlist, idx); 831 * Check messup is required for forward overwritable ring buffer:
832 * memory pointed by md->prev can be overwritten in this case.
833 * No need for read-write ring buffer: kernel stop outputting when
834 * it hit md->prev (perf_mmap__consume()).
835 */
836 return perf_mmap__read_forward(md, evlist->overwrite);
767} 837}
768 838
769void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 839union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
770{ 840{
771 struct perf_mmap *md = &evlist->mmap[idx]; 841 struct perf_mmap *md = &evlist->mmap[idx];
772 842
773 if (!evlist->overwrite) { 843 /*
844 * No need to check messup for backward ring buffer:
845 * We can always read arbitrary long data from a backward
846 * ring buffer unless we forget to pause it before reading.
847 */
848 return perf_mmap__read_backward(md);
849}
850
851union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
852{
853 return perf_evlist__mmap_read_forward(evlist, idx);
854}
855
856void perf_mmap__read_catchup(struct perf_mmap *md)
857{
858 u64 head;
859
860 if (!atomic_read(&md->refcnt))
861 return;
862
863 head = perf_mmap__read_head(md);
864 md->prev = head;
865}
866
867void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
868{
869 perf_mmap__read_catchup(&evlist->mmap[idx]);
870}
871
872static bool perf_mmap__empty(struct perf_mmap *md)
873{
874 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
875}
876
877static void perf_mmap__get(struct perf_mmap *map)
878{
879 atomic_inc(&map->refcnt);
880}
881
882static void perf_mmap__put(struct perf_mmap *md)
883{
884 BUG_ON(md->base && atomic_read(&md->refcnt) == 0);
885
886 if (atomic_dec_and_test(&md->refcnt))
887 perf_mmap__munmap(md);
888}
889
890void perf_mmap__consume(struct perf_mmap *md, bool overwrite)
891{
892 if (!overwrite) {
774 u64 old = md->prev; 893 u64 old = md->prev;
775 894
776 perf_mmap__write_tail(md, old); 895 perf_mmap__write_tail(md, old);
777 } 896 }
778 897
779 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) 898 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
780 perf_evlist__mmap_put(evlist, idx); 899 perf_mmap__put(md);
900}
901
902void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
903{
904 perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite);
781} 905}
782 906
783int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused, 907int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
@@ -808,36 +932,52 @@ void __weak auxtrace_mmap_params__set_idx(
808{ 932{
809} 933}
810 934
811static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 935static void perf_mmap__munmap(struct perf_mmap *map)
812{ 936{
813 if (evlist->mmap[idx].base != NULL) { 937 if (map->base != NULL) {
814 munmap(evlist->mmap[idx].base, evlist->mmap_len); 938 munmap(map->base, perf_mmap__mmap_len(map));
815 evlist->mmap[idx].base = NULL; 939 map->base = NULL;
816 atomic_set(&evlist->mmap[idx].refcnt, 0); 940 map->fd = -1;
941 atomic_set(&map->refcnt, 0);
817 } 942 }
818 auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); 943 auxtrace_mmap__munmap(&map->auxtrace_mmap);
819} 944}
820 945
821void perf_evlist__munmap(struct perf_evlist *evlist) 946static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
822{ 947{
823 int i; 948 int i;
824 949
825 if (evlist->mmap == NULL) 950 if (evlist->mmap)
826 return; 951 for (i = 0; i < evlist->nr_mmaps; i++)
952 perf_mmap__munmap(&evlist->mmap[i]);
827 953
828 for (i = 0; i < evlist->nr_mmaps; i++) 954 if (evlist->backward_mmap)
829 __perf_evlist__munmap(evlist, i); 955 for (i = 0; i < evlist->nr_mmaps; i++)
956 perf_mmap__munmap(&evlist->backward_mmap[i]);
957}
830 958
959void perf_evlist__munmap(struct perf_evlist *evlist)
960{
961 perf_evlist__munmap_nofree(evlist);
831 zfree(&evlist->mmap); 962 zfree(&evlist->mmap);
963 zfree(&evlist->backward_mmap);
832} 964}
833 965
834static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 966static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
835{ 967{
968 int i;
969 struct perf_mmap *map;
970
836 evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 971 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
837 if (cpu_map__empty(evlist->cpus)) 972 if (cpu_map__empty(evlist->cpus))
838 evlist->nr_mmaps = thread_map__nr(evlist->threads); 973 evlist->nr_mmaps = thread_map__nr(evlist->threads);
839 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 974 map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
840 return evlist->mmap != NULL ? 0 : -ENOMEM; 975 if (!map)
976 return NULL;
977
978 for (i = 0; i < evlist->nr_mmaps; i++)
979 map[i].fd = -1;
980 return map;
841} 981}
842 982
843struct mmap_params { 983struct mmap_params {
@@ -846,8 +986,8 @@ struct mmap_params {
846 struct auxtrace_mmap_params auxtrace_mp; 986 struct auxtrace_mmap_params auxtrace_mp;
847}; 987};
848 988
849static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 989static int perf_mmap__mmap(struct perf_mmap *map,
850 struct mmap_params *mp, int fd) 990 struct mmap_params *mp, int fd)
851{ 991{
852 /* 992 /*
853 * The last one will be done at perf_evlist__mmap_consume(), so that we 993 * The last one will be done at perf_evlist__mmap_consume(), so that we
@@ -862,34 +1002,61 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
862 * evlist layer can't just drop it when filtering events in 1002 * evlist layer can't just drop it when filtering events in
863 * perf_evlist__filter_pollfd(). 1003 * perf_evlist__filter_pollfd().
864 */ 1004 */
865 atomic_set(&evlist->mmap[idx].refcnt, 2); 1005 atomic_set(&map->refcnt, 2);
866 evlist->mmap[idx].prev = 0; 1006 map->prev = 0;
867 evlist->mmap[idx].mask = mp->mask; 1007 map->mask = mp->mask;
868 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 1008 map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
869 MAP_SHARED, fd, 0); 1009 MAP_SHARED, fd, 0);
870 if (evlist->mmap[idx].base == MAP_FAILED) { 1010 if (map->base == MAP_FAILED) {
871 pr_debug2("failed to mmap perf event ring buffer, error %d\n", 1011 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
872 errno); 1012 errno);
873 evlist->mmap[idx].base = NULL; 1013 map->base = NULL;
874 return -1; 1014 return -1;
875 } 1015 }
1016 map->fd = fd;
876 1017
877 if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, 1018 if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
878 &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) 1019 &mp->auxtrace_mp, map->base, fd))
879 return -1; 1020 return -1;
880 1021
881 return 0; 1022 return 0;
882} 1023}
883 1024
1025static bool
1026perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
1027 struct perf_evsel *evsel)
1028{
1029 if (evsel->attr.write_backward)
1030 return false;
1031 return true;
1032}
1033
884static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 1034static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
885 struct mmap_params *mp, int cpu, 1035 struct mmap_params *mp, int cpu,
886 int thread, int *output) 1036 int thread, int *_output, int *_output_backward)
887{ 1037{
888 struct perf_evsel *evsel; 1038 struct perf_evsel *evsel;
1039 int revent;
889 1040
890 evlist__for_each(evlist, evsel) { 1041 evlist__for_each_entry(evlist, evsel) {
1042 struct perf_mmap *maps = evlist->mmap;
1043 int *output = _output;
891 int fd; 1044 int fd;
892 1045
1046 if (evsel->attr.write_backward) {
1047 output = _output_backward;
1048 maps = evlist->backward_mmap;
1049
1050 if (!maps) {
1051 maps = perf_evlist__alloc_mmap(evlist);
1052 if (!maps)
1053 return -1;
1054 evlist->backward_mmap = maps;
1055 if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
1056 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
1057 }
1058 }
1059
893 if (evsel->system_wide && thread) 1060 if (evsel->system_wide && thread)
894 continue; 1061 continue;
895 1062
@@ -897,15 +1064,18 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
897 1064
898 if (*output == -1) { 1065 if (*output == -1) {
899 *output = fd; 1066 *output = fd;
900 if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) 1067
1068 if (perf_mmap__mmap(&maps[idx], mp, *output) < 0)
901 return -1; 1069 return -1;
902 } else { 1070 } else {
903 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 1071 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
904 return -1; 1072 return -1;
905 1073
906 perf_evlist__mmap_get(evlist, idx); 1074 perf_mmap__get(&maps[idx]);
907 } 1075 }
908 1076
1077 revent = perf_evlist__should_poll(evlist, evsel) ? POLLIN : 0;
1078
909 /* 1079 /*
910 * The system_wide flag causes a selected event to be opened 1080 * The system_wide flag causes a selected event to be opened
911 * always without a pid. Consequently it will never get a 1081 * always without a pid. Consequently it will never get a
@@ -914,8 +1084,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
914 * Therefore don't add it for polling. 1084 * Therefore don't add it for polling.
915 */ 1085 */
916 if (!evsel->system_wide && 1086 if (!evsel->system_wide &&
917 __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { 1087 __perf_evlist__add_pollfd(evlist, fd, &maps[idx], revent) < 0) {
918 perf_evlist__mmap_put(evlist, idx); 1088 perf_mmap__put(&maps[idx]);
919 return -1; 1089 return -1;
920 } 1090 }
921 1091
@@ -941,13 +1111,14 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
941 pr_debug2("perf event ring buffer mmapped per cpu\n"); 1111 pr_debug2("perf event ring buffer mmapped per cpu\n");
942 for (cpu = 0; cpu < nr_cpus; cpu++) { 1112 for (cpu = 0; cpu < nr_cpus; cpu++) {
943 int output = -1; 1113 int output = -1;
1114 int output_backward = -1;
944 1115
945 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu, 1116 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
946 true); 1117 true);
947 1118
948 for (thread = 0; thread < nr_threads; thread++) { 1119 for (thread = 0; thread < nr_threads; thread++) {
949 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, 1120 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
950 thread, &output)) 1121 thread, &output, &output_backward))
951 goto out_unmap; 1122 goto out_unmap;
952 } 1123 }
953 } 1124 }
@@ -955,8 +1126,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
955 return 0; 1126 return 0;
956 1127
957out_unmap: 1128out_unmap:
958 for (cpu = 0; cpu < nr_cpus; cpu++) 1129 perf_evlist__munmap_nofree(evlist);
959 __perf_evlist__munmap(evlist, cpu);
960 return -1; 1130 return -1;
961} 1131}
962 1132
@@ -969,43 +1139,51 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
969 pr_debug2("perf event ring buffer mmapped per thread\n"); 1139 pr_debug2("perf event ring buffer mmapped per thread\n");
970 for (thread = 0; thread < nr_threads; thread++) { 1140 for (thread = 0; thread < nr_threads; thread++) {
971 int output = -1; 1141 int output = -1;
1142 int output_backward = -1;
972 1143
973 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, 1144 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
974 false); 1145 false);
975 1146
976 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, 1147 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
977 &output)) 1148 &output, &output_backward))
978 goto out_unmap; 1149 goto out_unmap;
979 } 1150 }
980 1151
981 return 0; 1152 return 0;
982 1153
983out_unmap: 1154out_unmap:
984 for (thread = 0; thread < nr_threads; thread++) 1155 perf_evlist__munmap_nofree(evlist);
985 __perf_evlist__munmap(evlist, thread);
986 return -1; 1156 return -1;
987} 1157}
988 1158
989static size_t perf_evlist__mmap_size(unsigned long pages) 1159unsigned long perf_event_mlock_kb_in_pages(void)
990{ 1160{
991 if (pages == UINT_MAX) { 1161 unsigned long pages;
992 int max; 1162 int max;
993 1163
994 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) { 1164 if (sysctl__read_int("kernel/perf_event_mlock_kb", &max) < 0) {
995 /* 1165 /*
996 * Pick a once upon a time good value, i.e. things look 1166 * Pick a once upon a time good value, i.e. things look
997 * strange since we can't read a sysctl value, but lets not 1167 * strange since we can't read a sysctl value, but lets not
998 * die yet... 1168 * die yet...
999 */ 1169 */
1000 max = 512; 1170 max = 512;
1001 } else { 1171 } else {
1002 max -= (page_size / 1024); 1172 max -= (page_size / 1024);
1003 } 1173 }
1174
1175 pages = (max * 1024) / page_size;
1176 if (!is_power_of_2(pages))
1177 pages = rounddown_pow_of_two(pages);
1004 1178
1005 pages = (max * 1024) / page_size; 1179 return pages;
1006 if (!is_power_of_2(pages)) 1180}
1007 pages = rounddown_pow_of_two(pages); 1181
1008 } else if (!is_power_of_2(pages)) 1182static size_t perf_evlist__mmap_size(unsigned long pages)
1183{
1184 if (pages == UINT_MAX)
1185 pages = perf_event_mlock_kb_in_pages();
1186 else if (!is_power_of_2(pages))
1009 return 0; 1187 return 0;
1010 1188
1011 return (pages + 1) * page_size; 1189 return (pages + 1) * page_size;
@@ -1107,7 +1285,9 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1107 .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), 1285 .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
1108 }; 1286 };
1109 1287
1110 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 1288 if (!evlist->mmap)
1289 evlist->mmap = perf_evlist__alloc_mmap(evlist);
1290 if (!evlist->mmap)
1111 return -ENOMEM; 1291 return -ENOMEM;
1112 1292
1113 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 1293 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
@@ -1121,7 +1301,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1121 auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len, 1301 auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
1122 auxtrace_pages, auxtrace_overwrite); 1302 auxtrace_pages, auxtrace_overwrite);
1123 1303
1124 evlist__for_each(evlist, evsel) { 1304 evlist__for_each_entry(evlist, evsel) {
1125 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 1305 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
1126 evsel->sample_id == NULL && 1306 evsel->sample_id == NULL &&
1127 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) 1307 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
@@ -1192,6 +1372,24 @@ void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus,
1192 perf_evlist__propagate_maps(evlist); 1372 perf_evlist__propagate_maps(evlist);
1193} 1373}
1194 1374
1375void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
1376 enum perf_event_sample_format bit)
1377{
1378 struct perf_evsel *evsel;
1379
1380 evlist__for_each_entry(evlist, evsel)
1381 __perf_evsel__set_sample_bit(evsel, bit);
1382}
1383
1384void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
1385 enum perf_event_sample_format bit)
1386{
1387 struct perf_evsel *evsel;
1388
1389 evlist__for_each_entry(evlist, evsel)
1390 __perf_evsel__reset_sample_bit(evsel, bit);
1391}
1392
1195int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel) 1393int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **err_evsel)
1196{ 1394{
1197 struct perf_evsel *evsel; 1395 struct perf_evsel *evsel;
@@ -1199,7 +1397,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
1199 const int ncpus = cpu_map__nr(evlist->cpus), 1397 const int ncpus = cpu_map__nr(evlist->cpus),
1200 nthreads = thread_map__nr(evlist->threads); 1398 nthreads = thread_map__nr(evlist->threads);
1201 1399
1202 evlist__for_each(evlist, evsel) { 1400 evlist__for_each_entry(evlist, evsel) {
1203 if (evsel->filter == NULL) 1401 if (evsel->filter == NULL)
1204 continue; 1402 continue;
1205 1403
@@ -1222,7 +1420,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
1222 struct perf_evsel *evsel; 1420 struct perf_evsel *evsel;
1223 int err = 0; 1421 int err = 0;
1224 1422
1225 evlist__for_each(evlist, evsel) { 1423 evlist__for_each_entry(evlist, evsel) {
1226 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 1424 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1227 continue; 1425 continue;
1228 1426
@@ -1276,7 +1474,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
1276 if (evlist->id_pos < 0 || evlist->is_pos < 0) 1474 if (evlist->id_pos < 0 || evlist->is_pos < 0)
1277 return false; 1475 return false;
1278 1476
1279 evlist__for_each(evlist, pos) { 1477 evlist__for_each_entry(evlist, pos) {
1280 if (pos->id_pos != evlist->id_pos || 1478 if (pos->id_pos != evlist->id_pos ||
1281 pos->is_pos != evlist->is_pos) 1479 pos->is_pos != evlist->is_pos)
1282 return false; 1480 return false;
@@ -1292,7 +1490,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
1292 if (evlist->combined_sample_type) 1490 if (evlist->combined_sample_type)
1293 return evlist->combined_sample_type; 1491 return evlist->combined_sample_type;
1294 1492
1295 evlist__for_each(evlist, evsel) 1493 evlist__for_each_entry(evlist, evsel)
1296 evlist->combined_sample_type |= evsel->attr.sample_type; 1494 evlist->combined_sample_type |= evsel->attr.sample_type;
1297 1495
1298 return evlist->combined_sample_type; 1496 return evlist->combined_sample_type;
@@ -1309,7 +1507,7 @@ u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist)
1309 struct perf_evsel *evsel; 1507 struct perf_evsel *evsel;
1310 u64 branch_type = 0; 1508 u64 branch_type = 0;
1311 1509
1312 evlist__for_each(evlist, evsel) 1510 evlist__for_each_entry(evlist, evsel)
1313 branch_type |= evsel->attr.branch_sample_type; 1511 branch_type |= evsel->attr.branch_sample_type;
1314 return branch_type; 1512 return branch_type;
1315} 1513}
@@ -1320,7 +1518,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
1320 u64 read_format = first->attr.read_format; 1518 u64 read_format = first->attr.read_format;
1321 u64 sample_type = first->attr.sample_type; 1519 u64 sample_type = first->attr.sample_type;
1322 1520
1323 evlist__for_each(evlist, pos) { 1521 evlist__for_each_entry(evlist, pos) {
1324 if (read_format != pos->attr.read_format) 1522 if (read_format != pos->attr.read_format)
1325 return false; 1523 return false;
1326 } 1524 }
@@ -1377,7 +1575,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
1377{ 1575{
1378 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 1576 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
1379 1577
1380 evlist__for_each_continue(evlist, pos) { 1578 evlist__for_each_entry_continue(evlist, pos) {
1381 if (first->attr.sample_id_all != pos->attr.sample_id_all) 1579 if (first->attr.sample_id_all != pos->attr.sample_id_all)
1382 return false; 1580 return false;
1383 } 1581 }
@@ -1404,7 +1602,7 @@ void perf_evlist__close(struct perf_evlist *evlist)
1404 int nthreads = thread_map__nr(evlist->threads); 1602 int nthreads = thread_map__nr(evlist->threads);
1405 int n; 1603 int n;
1406 1604
1407 evlist__for_each_reverse(evlist, evsel) { 1605 evlist__for_each_entry_reverse(evlist, evsel) {
1408 n = evsel->cpus ? evsel->cpus->nr : ncpus; 1606 n = evsel->cpus ? evsel->cpus->nr : ncpus;
1409 perf_evsel__close(evsel, n, nthreads); 1607 perf_evsel__close(evsel, n, nthreads);
1410 } 1608 }
@@ -1458,7 +1656,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
1458 1656
1459 perf_evlist__update_id_pos(evlist); 1657 perf_evlist__update_id_pos(evlist);
1460 1658
1461 evlist__for_each(evlist, evsel) { 1659 evlist__for_each_entry(evlist, evsel) {
1462 err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); 1660 err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
1463 if (err < 0) 1661 if (err < 0)
1464 goto out_err; 1662 goto out_err;
@@ -1619,7 +1817,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1619 struct perf_evsel *evsel; 1817 struct perf_evsel *evsel;
1620 size_t printed = 0; 1818 size_t printed = 0;
1621 1819
1622 evlist__for_each(evlist, evsel) { 1820 evlist__for_each_entry(evlist, evsel) {
1623 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 1821 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
1624 perf_evsel__name(evsel)); 1822 perf_evsel__name(evsel));
1625 } 1823 }
@@ -1631,7 +1829,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist,
1631 int err, char *buf, size_t size) 1829 int err, char *buf, size_t size)
1632{ 1830{
1633 int printed, value; 1831 int printed, value;
1634 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1832 char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
1635 1833
1636 switch (err) { 1834 switch (err) {
1637 case EACCES: 1835 case EACCES:
@@ -1683,7 +1881,7 @@ out_default:
1683 1881
1684int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) 1882int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
1685{ 1883{
1686 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1884 char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
1687 int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0; 1885 int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
1688 1886
1689 switch (err) { 1887 switch (err) {
@@ -1721,7 +1919,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
1721 if (move_evsel == perf_evlist__first(evlist)) 1919 if (move_evsel == perf_evlist__first(evlist))
1722 return; 1920 return;
1723 1921
1724 evlist__for_each_safe(evlist, n, evsel) { 1922 evlist__for_each_entry_safe(evlist, n, evsel) {
1725 if (evsel->leader == move_evsel->leader) 1923 if (evsel->leader == move_evsel->leader)
1726 list_move_tail(&evsel->node, &move); 1924 list_move_tail(&evsel->node, &move);
1727 } 1925 }
@@ -1737,7 +1935,7 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
1737 if (tracking_evsel->tracking) 1935 if (tracking_evsel->tracking)
1738 return; 1936 return;
1739 1937
1740 evlist__for_each(evlist, evsel) { 1938 evlist__for_each_entry(evlist, evsel) {
1741 if (evsel != tracking_evsel) 1939 if (evsel != tracking_evsel)
1742 evsel->tracking = false; 1940 evsel->tracking = false;
1743 } 1941 }
@@ -1751,7 +1949,7 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
1751{ 1949{
1752 struct perf_evsel *evsel; 1950 struct perf_evsel *evsel;
1753 1951
1754 evlist__for_each(evlist, evsel) { 1952 evlist__for_each_entry(evlist, evsel) {
1755 if (!evsel->name) 1953 if (!evsel->name)
1756 continue; 1954 continue;
1757 if (strcmp(str, evsel->name) == 0) 1955 if (strcmp(str, evsel->name) == 0)
@@ -1760,3 +1958,61 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
1760 1958
1761 return NULL; 1959 return NULL;
1762} 1960}
1961
1962void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist,
1963 enum bkw_mmap_state state)
1964{
1965 enum bkw_mmap_state old_state = evlist->bkw_mmap_state;
1966 enum action {
1967 NONE,
1968 PAUSE,
1969 RESUME,
1970 } action = NONE;
1971
1972 if (!evlist->backward_mmap)
1973 return;
1974
1975 switch (old_state) {
1976 case BKW_MMAP_NOTREADY: {
1977 if (state != BKW_MMAP_RUNNING)
1978 goto state_err;;
1979 break;
1980 }
1981 case BKW_MMAP_RUNNING: {
1982 if (state != BKW_MMAP_DATA_PENDING)
1983 goto state_err;
1984 action = PAUSE;
1985 break;
1986 }
1987 case BKW_MMAP_DATA_PENDING: {
1988 if (state != BKW_MMAP_EMPTY)
1989 goto state_err;
1990 break;
1991 }
1992 case BKW_MMAP_EMPTY: {
1993 if (state != BKW_MMAP_RUNNING)
1994 goto state_err;
1995 action = RESUME;
1996 break;
1997 }
1998 default:
1999 WARN_ONCE(1, "Shouldn't get there\n");
2000 }
2001
2002 evlist->bkw_mmap_state = state;
2003
2004 switch (action) {
2005 case PAUSE:
2006 perf_evlist__pause(evlist);
2007 break;
2008 case RESUME:
2009 perf_evlist__resume(evlist);
2010 break;
2011 case NONE:
2012 default:
2013 break;
2014 }
2015
2016state_err:
2017 return;
2018}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index a0d15221db6e..4fd034f22d2f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -28,12 +28,47 @@ struct record_opts;
28struct perf_mmap { 28struct perf_mmap {
29 void *base; 29 void *base;
30 int mask; 30 int mask;
31 int fd;
31 atomic_t refcnt; 32 atomic_t refcnt;
32 u64 prev; 33 u64 prev;
33 struct auxtrace_mmap auxtrace_mmap; 34 struct auxtrace_mmap auxtrace_mmap;
34 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 35 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
35}; 36};
36 37
38static inline size_t
39perf_mmap__mmap_len(struct perf_mmap *map)
40{
41 return map->mask + 1 + page_size;
42}
43
44/*
45 * State machine of bkw_mmap_state:
46 *
47 * .________________(forbid)_____________.
48 * | V
49 * NOTREADY --(0)--> RUNNING --(1)--> DATA_PENDING --(2)--> EMPTY
50 * ^ ^ | ^ |
51 * | |__(forbid)____/ |___(forbid)___/|
52 * | |
53 * \_________________(3)_______________/
54 *
55 * NOTREADY : Backward ring buffers are not ready
56 * RUNNING : Backward ring buffers are recording
57 * DATA_PENDING : We are required to collect data from backward ring buffers
58 * EMPTY : We have collected data from backward ring buffers.
59 *
60 * (0): Setup backward ring buffer
61 * (1): Pause ring buffers for reading
62 * (2): Read from ring buffers
63 * (3): Resume ring buffers for recording
64 */
65enum bkw_mmap_state {
66 BKW_MMAP_NOTREADY,
67 BKW_MMAP_RUNNING,
68 BKW_MMAP_DATA_PENDING,
69 BKW_MMAP_EMPTY,
70};
71
37struct perf_evlist { 72struct perf_evlist {
38 struct list_head entries; 73 struct list_head entries;
39 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 74 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
@@ -47,12 +82,14 @@ struct perf_evlist {
47 int id_pos; 82 int id_pos;
48 int is_pos; 83 int is_pos;
49 u64 combined_sample_type; 84 u64 combined_sample_type;
85 enum bkw_mmap_state bkw_mmap_state;
50 struct { 86 struct {
51 int cork_fd; 87 int cork_fd;
52 pid_t pid; 88 pid_t pid;
53 } workload; 89 } workload;
54 struct fdarray pollfd; 90 struct fdarray pollfd;
55 struct perf_mmap *mmap; 91 struct perf_mmap *mmap;
92 struct perf_mmap *backward_mmap;
56 struct thread_map *threads; 93 struct thread_map *threads;
57 struct cpu_map *cpus; 94 struct cpu_map *cpus;
58 struct perf_evsel *selected; 95 struct perf_evsel *selected;
@@ -87,6 +124,17 @@ int perf_evlist__add_dummy(struct perf_evlist *evlist);
87int perf_evlist__add_newtp(struct perf_evlist *evlist, 124int perf_evlist__add_newtp(struct perf_evlist *evlist,
88 const char *sys, const char *name, void *handler); 125 const char *sys, const char *name, void *handler);
89 126
127void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
128 enum perf_event_sample_format bit);
129void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
130 enum perf_event_sample_format bit);
131
132#define perf_evlist__set_sample_bit(evlist, bit) \
133 __perf_evlist__set_sample_bit(evlist, PERF_SAMPLE_##bit)
134
135#define perf_evlist__reset_sample_bit(evlist, bit) \
136 __perf_evlist__reset_sample_bit(evlist, PERF_SAMPLE_##bit)
137
90int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter); 138int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter);
91int perf_evlist__set_filter_pid(struct perf_evlist *evlist, pid_t pid); 139int 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); 140int perf_evlist__set_filter_pids(struct perf_evlist *evlist, size_t npids, pid_t *pids);
@@ -116,18 +164,35 @@ struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
116 164
117struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id); 165struct perf_sample_id *perf_evlist__id2sid(struct perf_evlist *evlist, u64 id);
118 166
167void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist, enum bkw_mmap_state state);
168
169union perf_event *perf_mmap__read_forward(struct perf_mmap *map, bool check_messup);
170union perf_event *perf_mmap__read_backward(struct perf_mmap *map);
171
172void perf_mmap__read_catchup(struct perf_mmap *md);
173void perf_mmap__consume(struct perf_mmap *md, bool overwrite);
174
119union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx); 175union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx);
120 176
177union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
178 int idx);
179union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
180 int idx);
181void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
182
121void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 183void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
122 184
123int perf_evlist__open(struct perf_evlist *evlist); 185int perf_evlist__open(struct perf_evlist *evlist);
124void perf_evlist__close(struct perf_evlist *evlist); 186void perf_evlist__close(struct perf_evlist *evlist);
125 187
188struct callchain_param;
189
126void perf_evlist__set_id_pos(struct perf_evlist *evlist); 190void perf_evlist__set_id_pos(struct perf_evlist *evlist);
127bool perf_can_sample_identifier(void); 191bool perf_can_sample_identifier(void);
128bool perf_can_record_switch_events(void); 192bool perf_can_record_switch_events(void);
129bool perf_can_record_cpu_wide(void); 193bool perf_can_record_cpu_wide(void);
130void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts); 194void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
195 struct callchain_param *callchain);
131int record_opts__config(struct record_opts *opts); 196int record_opts__config(struct record_opts *opts);
132 197
133int perf_evlist__prepare_workload(struct perf_evlist *evlist, 198int perf_evlist__prepare_workload(struct perf_evlist *evlist,
@@ -144,6 +209,8 @@ int perf_evlist__parse_mmap_pages(const struct option *opt,
144 const char *str, 209 const char *str,
145 int unset); 210 int unset);
146 211
212unsigned long perf_event_mlock_kb_in_pages(void);
213
147int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages, 214int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
148 bool overwrite, unsigned int auxtrace_pages, 215 bool overwrite, unsigned int auxtrace_pages,
149 bool auxtrace_overwrite); 216 bool auxtrace_overwrite);
@@ -225,70 +292,70 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
225 struct perf_evsel *move_evsel); 292 struct perf_evsel *move_evsel);
226 293
227/** 294/**
228 * __evlist__for_each - iterate thru all the evsels 295 * __evlist__for_each_entry - iterate thru all the evsels
229 * @list: list_head instance to iterate 296 * @list: list_head instance to iterate
230 * @evsel: struct evsel iterator 297 * @evsel: struct evsel iterator
231 */ 298 */
232#define __evlist__for_each(list, evsel) \ 299#define __evlist__for_each_entry(list, evsel) \
233 list_for_each_entry(evsel, list, node) 300 list_for_each_entry(evsel, list, node)
234 301
235/** 302/**
236 * evlist__for_each - iterate thru all the evsels 303 * evlist__for_each_entry - iterate thru all the evsels
237 * @evlist: evlist instance to iterate 304 * @evlist: evlist instance to iterate
238 * @evsel: struct evsel iterator 305 * @evsel: struct evsel iterator
239 */ 306 */
240#define evlist__for_each(evlist, evsel) \ 307#define evlist__for_each_entry(evlist, evsel) \
241 __evlist__for_each(&(evlist)->entries, evsel) 308 __evlist__for_each_entry(&(evlist)->entries, evsel)
242 309
243/** 310/**
244 * __evlist__for_each_continue - continue iteration thru all the evsels 311 * __evlist__for_each_entry_continue - continue iteration thru all the evsels
245 * @list: list_head instance to iterate 312 * @list: list_head instance to iterate
246 * @evsel: struct evsel iterator 313 * @evsel: struct evsel iterator
247 */ 314 */
248#define __evlist__for_each_continue(list, evsel) \ 315#define __evlist__for_each_entry_continue(list, evsel) \
249 list_for_each_entry_continue(evsel, list, node) 316 list_for_each_entry_continue(evsel, list, node)
250 317
251/** 318/**
252 * evlist__for_each_continue - continue iteration thru all the evsels 319 * evlist__for_each_entry_continue - continue iteration thru all the evsels
253 * @evlist: evlist instance to iterate 320 * @evlist: evlist instance to iterate
254 * @evsel: struct evsel iterator 321 * @evsel: struct evsel iterator
255 */ 322 */
256#define evlist__for_each_continue(evlist, evsel) \ 323#define evlist__for_each_entry_continue(evlist, evsel) \
257 __evlist__for_each_continue(&(evlist)->entries, evsel) 324 __evlist__for_each_entry_continue(&(evlist)->entries, evsel)
258 325
259/** 326/**
260 * __evlist__for_each_reverse - iterate thru all the evsels in reverse order 327 * __evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
261 * @list: list_head instance to iterate 328 * @list: list_head instance to iterate
262 * @evsel: struct evsel iterator 329 * @evsel: struct evsel iterator
263 */ 330 */
264#define __evlist__for_each_reverse(list, evsel) \ 331#define __evlist__for_each_entry_reverse(list, evsel) \
265 list_for_each_entry_reverse(evsel, list, node) 332 list_for_each_entry_reverse(evsel, list, node)
266 333
267/** 334/**
268 * evlist__for_each_reverse - iterate thru all the evsels in reverse order 335 * evlist__for_each_entry_reverse - iterate thru all the evsels in reverse order
269 * @evlist: evlist instance to iterate 336 * @evlist: evlist instance to iterate
270 * @evsel: struct evsel iterator 337 * @evsel: struct evsel iterator
271 */ 338 */
272#define evlist__for_each_reverse(evlist, evsel) \ 339#define evlist__for_each_entry_reverse(evlist, evsel) \
273 __evlist__for_each_reverse(&(evlist)->entries, evsel) 340 __evlist__for_each_entry_reverse(&(evlist)->entries, evsel)
274 341
275/** 342/**
276 * __evlist__for_each_safe - safely iterate thru all the evsels 343 * __evlist__for_each_entry_safe - safely iterate thru all the evsels
277 * @list: list_head instance to iterate 344 * @list: list_head instance to iterate
278 * @tmp: struct evsel temp iterator 345 * @tmp: struct evsel temp iterator
279 * @evsel: struct evsel iterator 346 * @evsel: struct evsel iterator
280 */ 347 */
281#define __evlist__for_each_safe(list, tmp, evsel) \ 348#define __evlist__for_each_entry_safe(list, tmp, evsel) \
282 list_for_each_entry_safe(evsel, tmp, list, node) 349 list_for_each_entry_safe(evsel, tmp, list, node)
283 350
284/** 351/**
285 * evlist__for_each_safe - safely iterate thru all the evsels 352 * evlist__for_each_entry_safe - safely iterate thru all the evsels
286 * @evlist: evlist instance to iterate 353 * @evlist: evlist instance to iterate
287 * @evsel: struct evsel iterator 354 * @evsel: struct evsel iterator
288 * @tmp: struct evsel temp iterator 355 * @tmp: struct evsel temp iterator
289 */ 356 */
290#define evlist__for_each_safe(evlist, tmp, evsel) \ 357#define evlist__for_each_entry_safe(evlist, tmp, evsel) \
291 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) 358 __evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel)
292 359
293void perf_evlist__set_tracking_event(struct perf_evlist *evlist, 360void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
294 struct perf_evsel *tracking_evsel); 361 struct perf_evsel *tracking_evsel);
@@ -297,4 +364,7 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr);
297 364
298struct perf_evsel * 365struct perf_evsel *
299perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str); 366perf_evlist__find_evsel_by_str(struct perf_evlist *evlist, const char *str);
367
368struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
369 union perf_event *event);
300#endif /* __PERF_EVLIST_H */ 370#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 645dc1828836..21fd573106ed 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -37,6 +37,7 @@ static struct {
37 bool clockid; 37 bool clockid;
38 bool clockid_wrong; 38 bool clockid_wrong;
39 bool lbr_flags; 39 bool lbr_flags;
40 bool write_backward;
40} perf_missing_features; 41} perf_missing_features;
41 42
42static clockid_t clockid; 43static clockid_t clockid;
@@ -199,6 +200,24 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
199 evsel->attr.read_format |= PERF_FORMAT_ID; 200 evsel->attr.read_format |= PERF_FORMAT_ID;
200} 201}
201 202
203/**
204 * perf_evsel__is_function_event - Return whether given evsel is a function
205 * trace event
206 *
207 * @evsel - evsel selector to be tested
208 *
209 * Return %true if event is function trace event
210 */
211bool perf_evsel__is_function_event(struct perf_evsel *evsel)
212{
213#define FUNCTION_EVENT "ftrace:function"
214
215 return evsel->name &&
216 !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT));
217
218#undef FUNCTION_EVENT
219}
220
202void perf_evsel__init(struct perf_evsel *evsel, 221void perf_evsel__init(struct perf_evsel *evsel,
203 struct perf_event_attr *attr, int idx) 222 struct perf_event_attr *attr, int idx)
204{ 223{
@@ -226,13 +245,42 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
226 perf_evsel__init(evsel, attr, idx); 245 perf_evsel__init(evsel, attr, idx);
227 246
228 if (perf_evsel__is_bpf_output(evsel)) { 247 if (perf_evsel__is_bpf_output(evsel)) {
229 evsel->attr.sample_type |= PERF_SAMPLE_RAW; 248 evsel->attr.sample_type |= (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
249 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD),
230 evsel->attr.sample_period = 1; 250 evsel->attr.sample_period = 1;
231 } 251 }
232 252
233 return evsel; 253 return evsel;
234} 254}
235 255
256struct perf_evsel *perf_evsel__new_cycles(void)
257{
258 struct perf_event_attr attr = {
259 .type = PERF_TYPE_HARDWARE,
260 .config = PERF_COUNT_HW_CPU_CYCLES,
261 };
262 struct perf_evsel *evsel;
263
264 event_attr_init(&attr);
265
266 perf_event_attr__set_max_precise_ip(&attr);
267
268 evsel = perf_evsel__new(&attr);
269 if (evsel == NULL)
270 goto out;
271
272 /* use asprintf() because free(evsel) assumes name is allocated */
273 if (asprintf(&evsel->name, "cycles%.*s",
274 attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
275 goto error_free;
276out:
277 return evsel;
278error_free:
279 perf_evsel__delete(evsel);
280 evsel = NULL;
281 goto out;
282}
283
236/* 284/*
237 * Returns pointer with encoded error via <linux/err.h> interface. 285 * Returns pointer with encoded error via <linux/err.h> interface.
238 */ 286 */
@@ -459,17 +507,17 @@ static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
459 u8 op, result, type = (config >> 0) & 0xff; 507 u8 op, result, type = (config >> 0) & 0xff;
460 const char *err = "unknown-ext-hardware-cache-type"; 508 const char *err = "unknown-ext-hardware-cache-type";
461 509
462 if (type > PERF_COUNT_HW_CACHE_MAX) 510 if (type >= PERF_COUNT_HW_CACHE_MAX)
463 goto out_err; 511 goto out_err;
464 512
465 op = (config >> 8) & 0xff; 513 op = (config >> 8) & 0xff;
466 err = "unknown-ext-hardware-cache-op"; 514 err = "unknown-ext-hardware-cache-op";
467 if (op > PERF_COUNT_HW_CACHE_OP_MAX) 515 if (op >= PERF_COUNT_HW_CACHE_OP_MAX)
468 goto out_err; 516 goto out_err;
469 517
470 result = (config >> 16) & 0xff; 518 result = (config >> 16) & 0xff;
471 err = "unknown-ext-hardware-cache-result"; 519 err = "unknown-ext-hardware-cache-result";
472 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX) 520 if (result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
473 goto out_err; 521 goto out_err;
474 522
475 err = "invalid-cache"; 523 err = "invalid-cache";
@@ -561,16 +609,17 @@ int perf_evsel__group_desc(struct perf_evsel *evsel, char *buf, size_t size)
561 return ret; 609 return ret;
562} 610}
563 611
564static void 612void perf_evsel__config_callchain(struct perf_evsel *evsel,
565perf_evsel__config_callgraph(struct perf_evsel *evsel, 613 struct record_opts *opts,
566 struct record_opts *opts, 614 struct callchain_param *param)
567 struct callchain_param *param)
568{ 615{
569 bool function = perf_evsel__is_function_event(evsel); 616 bool function = perf_evsel__is_function_event(evsel);
570 struct perf_event_attr *attr = &evsel->attr; 617 struct perf_event_attr *attr = &evsel->attr;
571 618
572 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 619 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
573 620
621 attr->sample_max_stack = param->max_stack;
622
574 if (param->record_mode == CALLCHAIN_LBR) { 623 if (param->record_mode == CALLCHAIN_LBR) {
575 if (!opts->branch_stack) { 624 if (!opts->branch_stack) {
576 if (attr->exclude_user) { 625 if (attr->exclude_user) {
@@ -634,7 +683,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
634 struct perf_event_attr *attr = &evsel->attr; 683 struct perf_event_attr *attr = &evsel->attr;
635 struct callchain_param param; 684 struct callchain_param param;
636 u32 dump_size = 0; 685 u32 dump_size = 0;
637 char *callgraph_buf = NULL; 686 int max_stack = 0;
687 const char *callgraph_buf = NULL;
638 688
639 /* callgraph default */ 689 /* callgraph default */
640 param.record_mode = callchain_param.record_mode; 690 param.record_mode = callchain_param.record_mode;
@@ -661,6 +711,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
661 case PERF_EVSEL__CONFIG_TERM_STACK_USER: 711 case PERF_EVSEL__CONFIG_TERM_STACK_USER:
662 dump_size = term->val.stack_user; 712 dump_size = term->val.stack_user;
663 break; 713 break;
714 case PERF_EVSEL__CONFIG_TERM_MAX_STACK:
715 max_stack = term->val.max_stack;
716 break;
664 case PERF_EVSEL__CONFIG_TERM_INHERIT: 717 case PERF_EVSEL__CONFIG_TERM_INHERIT:
665 /* 718 /*
666 * attr->inherit should has already been set by 719 * attr->inherit should has already been set by
@@ -670,13 +723,21 @@ static void apply_config_terms(struct perf_evsel *evsel,
670 */ 723 */
671 attr->inherit = term->val.inherit ? 1 : 0; 724 attr->inherit = term->val.inherit ? 1 : 0;
672 break; 725 break;
726 case PERF_EVSEL__CONFIG_TERM_OVERWRITE:
727 attr->write_backward = term->val.overwrite ? 1 : 0;
728 break;
673 default: 729 default:
674 break; 730 break;
675 } 731 }
676 } 732 }
677 733
678 /* User explicitly set per-event callgraph, clear the old setting and reset. */ 734 /* User explicitly set per-event callgraph, clear the old setting and reset. */
679 if ((callgraph_buf != NULL) || (dump_size > 0)) { 735 if ((callgraph_buf != NULL) || (dump_size > 0) || max_stack) {
736 if (max_stack) {
737 param.max_stack = max_stack;
738 if (callgraph_buf == NULL)
739 callgraph_buf = "fp";
740 }
680 741
681 /* parse callgraph parameters */ 742 /* parse callgraph parameters */
682 if (callgraph_buf != NULL) { 743 if (callgraph_buf != NULL) {
@@ -704,7 +765,7 @@ static void apply_config_terms(struct perf_evsel *evsel,
704 765
705 /* set perf-event callgraph */ 766 /* set perf-event callgraph */
706 if (param.enabled) 767 if (param.enabled)
707 perf_evsel__config_callgraph(evsel, opts, &param); 768 perf_evsel__config_callchain(evsel, opts, &param);
708 } 769 }
709} 770}
710 771
@@ -736,7 +797,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
736 * enable/disable events specifically, as there's no 797 * enable/disable events specifically, as there's no
737 * initial traced exec call. 798 * initial traced exec call.
738 */ 799 */
739void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts) 800void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
801 struct callchain_param *callchain)
740{ 802{
741 struct perf_evsel *leader = evsel->leader; 803 struct perf_evsel *leader = evsel->leader;
742 struct perf_event_attr *attr = &evsel->attr; 804 struct perf_event_attr *attr = &evsel->attr;
@@ -745,6 +807,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
745 807
746 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1; 808 attr->sample_id_all = perf_missing_features.sample_id_all ? 0 : 1;
747 attr->inherit = !opts->no_inherit; 809 attr->inherit = !opts->no_inherit;
810 attr->write_backward = opts->overwrite ? 1 : 0;
748 811
749 perf_evsel__set_sample_bit(evsel, IP); 812 perf_evsel__set_sample_bit(evsel, IP);
750 perf_evsel__set_sample_bit(evsel, TID); 813 perf_evsel__set_sample_bit(evsel, TID);
@@ -811,22 +874,22 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts)
811 if (perf_evsel__is_function_event(evsel)) 874 if (perf_evsel__is_function_event(evsel))
812 evsel->attr.exclude_callchain_user = 1; 875 evsel->attr.exclude_callchain_user = 1;
813 876
814 if (callchain_param.enabled && !evsel->no_aux_samples) 877 if (callchain && callchain->enabled && !evsel->no_aux_samples)
815 perf_evsel__config_callgraph(evsel, opts, &callchain_param); 878 perf_evsel__config_callchain(evsel, opts, callchain);
816 879
817 if (opts->sample_intr_regs) { 880 if (opts->sample_intr_regs) {
818 attr->sample_regs_intr = opts->sample_intr_regs; 881 attr->sample_regs_intr = opts->sample_intr_regs;
819 perf_evsel__set_sample_bit(evsel, REGS_INTR); 882 perf_evsel__set_sample_bit(evsel, REGS_INTR);
820 } 883 }
821 884
822 if (target__has_cpu(&opts->target)) 885 if (target__has_cpu(&opts->target) || opts->sample_cpu)
823 perf_evsel__set_sample_bit(evsel, CPU); 886 perf_evsel__set_sample_bit(evsel, CPU);
824 887
825 if (opts->period) 888 if (opts->period)
826 perf_evsel__set_sample_bit(evsel, PERIOD); 889 perf_evsel__set_sample_bit(evsel, PERIOD);
827 890
828 /* 891 /*
829 * When the user explicitely disabled time don't force it here. 892 * When the user explicitly disabled time don't force it here.
830 */ 893 */
831 if (opts->sample_time && 894 if (opts->sample_time &&
832 (!perf_missing_features.sample_id_all && 895 (!perf_missing_features.sample_id_all &&
@@ -1230,6 +1293,21 @@ static void __p_sample_type(char *buf, size_t size, u64 value)
1230 __p_bits(buf, size, value, bits); 1293 __p_bits(buf, size, value, bits);
1231} 1294}
1232 1295
1296static void __p_branch_sample_type(char *buf, size_t size, u64 value)
1297{
1298#define bit_name(n) { PERF_SAMPLE_BRANCH_##n, #n }
1299 struct bit_names bits[] = {
1300 bit_name(USER), bit_name(KERNEL), bit_name(HV), bit_name(ANY),
1301 bit_name(ANY_CALL), bit_name(ANY_RETURN), bit_name(IND_CALL),
1302 bit_name(ABORT_TX), bit_name(IN_TX), bit_name(NO_TX),
1303 bit_name(COND), bit_name(CALL_STACK), bit_name(IND_JUMP),
1304 bit_name(CALL), bit_name(NO_FLAGS), bit_name(NO_CYCLES),
1305 { .name = NULL, }
1306 };
1307#undef bit_name
1308 __p_bits(buf, size, value, bits);
1309}
1310
1233static void __p_read_format(char *buf, size_t size, u64 value) 1311static void __p_read_format(char *buf, size_t size, u64 value)
1234{ 1312{
1235#define bit_name(n) { PERF_FORMAT_##n, #n } 1313#define bit_name(n) { PERF_FORMAT_##n, #n }
@@ -1248,6 +1326,7 @@ static void __p_read_format(char *buf, size_t size, u64 value)
1248#define p_unsigned(val) snprintf(buf, BUF_SIZE, "%"PRIu64, (uint64_t)(val)) 1326#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)) 1327#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) 1328#define p_sample_type(val) __p_sample_type(buf, BUF_SIZE, val)
1329#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) 1330#define p_read_format(val) __p_read_format(buf, BUF_SIZE, val)
1252 1331
1253#define PRINT_ATTRn(_n, _f, _p) \ 1332#define PRINT_ATTRn(_n, _f, _p) \
@@ -1299,17 +1378,19 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1299 PRINT_ATTRf(comm_exec, p_unsigned); 1378 PRINT_ATTRf(comm_exec, p_unsigned);
1300 PRINT_ATTRf(use_clockid, p_unsigned); 1379 PRINT_ATTRf(use_clockid, p_unsigned);
1301 PRINT_ATTRf(context_switch, p_unsigned); 1380 PRINT_ATTRf(context_switch, p_unsigned);
1381 PRINT_ATTRf(write_backward, p_unsigned);
1302 1382
1303 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned); 1383 PRINT_ATTRn("{ wakeup_events, wakeup_watermark }", wakeup_events, p_unsigned);
1304 PRINT_ATTRf(bp_type, p_unsigned); 1384 PRINT_ATTRf(bp_type, p_unsigned);
1305 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex); 1385 PRINT_ATTRn("{ bp_addr, config1 }", bp_addr, p_hex);
1306 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex); 1386 PRINT_ATTRn("{ bp_len, config2 }", bp_len, p_hex);
1307 PRINT_ATTRf(branch_sample_type, p_unsigned); 1387 PRINT_ATTRf(branch_sample_type, p_branch_sample_type);
1308 PRINT_ATTRf(sample_regs_user, p_hex); 1388 PRINT_ATTRf(sample_regs_user, p_hex);
1309 PRINT_ATTRf(sample_stack_user, p_unsigned); 1389 PRINT_ATTRf(sample_stack_user, p_unsigned);
1310 PRINT_ATTRf(clockid, p_signed); 1390 PRINT_ATTRf(clockid, p_signed);
1311 PRINT_ATTRf(sample_regs_intr, p_hex); 1391 PRINT_ATTRf(sample_regs_intr, p_hex);
1312 PRINT_ATTRf(aux_watermark, p_unsigned); 1392 PRINT_ATTRf(aux_watermark, p_unsigned);
1393 PRINT_ATTRf(sample_max_stack, p_unsigned);
1313 1394
1314 return ret; 1395 return ret;
1315} 1396}
@@ -1328,6 +1409,9 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1328 int pid = -1, err; 1409 int pid = -1, err;
1329 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1410 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1330 1411
1412 if (perf_missing_features.write_backward && evsel->attr.write_backward)
1413 return -EINVAL;
1414
1331 if (evsel->system_wide) 1415 if (evsel->system_wide)
1332 nthreads = 1; 1416 nthreads = 1;
1333 else 1417 else
@@ -1457,7 +1541,10 @@ try_fallback:
1457 * Must probe features in the order they were added to the 1541 * Must probe features in the order they were added to the
1458 * perf_event_attr interface. 1542 * perf_event_attr interface.
1459 */ 1543 */
1460 if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { 1544 if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
1545 perf_missing_features.write_backward = true;
1546 goto out_close;
1547 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1461 perf_missing_features.clockid_wrong = true; 1548 perf_missing_features.clockid_wrong = true;
1462 goto fallback_missing_features; 1549 goto fallback_missing_features;
1463 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { 1550 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
@@ -1483,7 +1570,6 @@ try_fallback:
1483 perf_missing_features.lbr_flags = true; 1570 perf_missing_features.lbr_flags = true;
1484 goto fallback_missing_features; 1571 goto fallback_missing_features;
1485 } 1572 }
1486
1487out_close: 1573out_close:
1488 do { 1574 do {
1489 while (--thread >= 0) { 1575 while (--thread >= 0) {
@@ -2208,17 +2294,11 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2208 return sample->raw_data + offset; 2294 return sample->raw_data + offset;
2209} 2295}
2210 2296
2211u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, 2297u64 format_field__intval(struct format_field *field, struct perf_sample *sample,
2212 const char *name) 2298 bool needs_swap)
2213{ 2299{
2214 struct format_field *field = perf_evsel__field(evsel, name);
2215 void *ptr;
2216 u64 value; 2300 u64 value;
2217 2301 void *ptr = sample->raw_data + field->offset;
2218 if (!field)
2219 return 0;
2220
2221 ptr = sample->raw_data + field->offset;
2222 2302
2223 switch (field->size) { 2303 switch (field->size) {
2224 case 1: 2304 case 1:
@@ -2236,7 +2316,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2236 return 0; 2316 return 0;
2237 } 2317 }
2238 2318
2239 if (!evsel->needs_swap) 2319 if (!needs_swap)
2240 return value; 2320 return value;
2241 2321
2242 switch (field->size) { 2322 switch (field->size) {
@@ -2253,93 +2333,15 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2253 return 0; 2333 return 0;
2254} 2334}
2255 2335
2256static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...) 2336u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2257{ 2337 const char *name)
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{ 2338{
2282 bool first = true; 2339 struct format_field *field = perf_evsel__field(evsel, name);
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 2340
2332 printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name); 2341 if (!field)
2342 return 0;
2333 2343
2334 field = field->next; 2344 return field ? format_field__intval(field, sample, evsel->needs_swap) : 0;
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} 2345}
2344 2346
2345bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 2347bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
@@ -2416,12 +2418,23 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2416 "Probably the maximum number of open file descriptors has been reached.\n" 2418 "Probably the maximum number of open file descriptors has been reached.\n"
2417 "Hint: Try again after reducing the number of events.\n" 2419 "Hint: Try again after reducing the number of events.\n"
2418 "Hint: Try increasing the limit with 'ulimit -n <limit>'"); 2420 "Hint: Try increasing the limit with 'ulimit -n <limit>'");
2421 case ENOMEM:
2422 if ((evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) != 0 &&
2423 access("/proc/sys/kernel/perf_event_max_stack", F_OK) == 0)
2424 return scnprintf(msg, size,
2425 "Not enough memory to setup event with callchain.\n"
2426 "Hint: Try tweaking /proc/sys/kernel/perf_event_max_stack\n"
2427 "Hint: Current value: %d", sysctl_perf_event_max_stack);
2428 break;
2419 case ENODEV: 2429 case ENODEV:
2420 if (target->cpu_list) 2430 if (target->cpu_list)
2421 return scnprintf(msg, size, "%s", 2431 return scnprintf(msg, size, "%s",
2422 "No such device - did you specify an out-of-range profile CPU?\n"); 2432 "No such device - did you specify an out-of-range profile CPU?");
2423 break; 2433 break;
2424 case EOPNOTSUPP: 2434 case EOPNOTSUPP:
2435 if (evsel->attr.sample_period != 0)
2436 return scnprintf(msg, size, "%s",
2437 "PMU Hardware doesn't support sampling/overflow-interrupts.");
2425 if (evsel->attr.precise_ip) 2438 if (evsel->attr.precise_ip)
2426 return scnprintf(msg, size, "%s", 2439 return scnprintf(msg, size, "%s",
2427 "\'precise\' request may not be supported. Try removing 'p' modifier."); 2440 "\'precise\' request may not be supported. Try removing 'p' modifier.");
@@ -2439,6 +2452,8 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2439 "We found oprofile daemon running, please stop it and try again."); 2452 "We found oprofile daemon running, please stop it and try again.");
2440 break; 2453 break;
2441 case EINVAL: 2454 case EINVAL:
2455 if (evsel->attr.write_backward && perf_missing_features.write_backward)
2456 return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel.");
2442 if (perf_missing_features.clockid) 2457 if (perf_missing_features.clockid)
2443 return scnprintf(msg, size, "clockid feature not supported."); 2458 return scnprintf(msg, size, "clockid feature not supported.");
2444 if (perf_missing_features.clockid_wrong) 2459 if (perf_missing_features.clockid_wrong)
@@ -2451,7 +2466,14 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2451 return scnprintf(msg, size, 2466 return scnprintf(msg, size,
2452 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" 2467 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2453 "/bin/dmesg may provide additional information.\n" 2468 "/bin/dmesg may provide additional information.\n"
2454 "No CONFIG_PERF_EVENTS=y kernel support configured?\n", 2469 "No CONFIG_PERF_EVENTS=y kernel support configured?",
2455 err, strerror_r(err, sbuf, sizeof(sbuf)), 2470 err, str_error_r(err, sbuf, sizeof(sbuf)),
2456 perf_evsel__name(evsel)); 2471 perf_evsel__name(evsel));
2457} 2472}
2473
2474char *perf_evsel__env_arch(struct perf_evsel *evsel)
2475{
2476 if (evsel && evsel->evlist && evsel->evlist->env)
2477 return evsel->evlist->env->arch;
2478 return NULL;
2479}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 501ea6e565f1..4d44129e050b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -44,6 +44,8 @@ enum {
44 PERF_EVSEL__CONFIG_TERM_CALLGRAPH, 44 PERF_EVSEL__CONFIG_TERM_CALLGRAPH,
45 PERF_EVSEL__CONFIG_TERM_STACK_USER, 45 PERF_EVSEL__CONFIG_TERM_STACK_USER,
46 PERF_EVSEL__CONFIG_TERM_INHERIT, 46 PERF_EVSEL__CONFIG_TERM_INHERIT,
47 PERF_EVSEL__CONFIG_TERM_MAX_STACK,
48 PERF_EVSEL__CONFIG_TERM_OVERWRITE,
47 PERF_EVSEL__CONFIG_TERM_MAX, 49 PERF_EVSEL__CONFIG_TERM_MAX,
48}; 50};
49 51
@@ -56,7 +58,9 @@ struct perf_evsel_config_term {
56 bool time; 58 bool time;
57 char *callgraph; 59 char *callgraph;
58 u64 stack_user; 60 u64 stack_user;
61 int max_stack;
59 bool inherit; 62 bool inherit;
63 bool overwrite;
60 } val; 64 } val;
61}; 65};
62 66
@@ -171,6 +175,8 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
171 return perf_evsel__newtp_idx(sys, name, 0); 175 return perf_evsel__newtp_idx(sys, name, 0);
172} 176}
173 177
178struct perf_evsel *perf_evsel__new_cycles(void);
179
174struct event_format *event_format__new(const char *sys, const char *name); 180struct event_format *event_format__new(const char *sys, const char *name);
175 181
176void perf_evsel__init(struct perf_evsel *evsel, 182void perf_evsel__init(struct perf_evsel *evsel,
@@ -178,8 +184,14 @@ void perf_evsel__init(struct perf_evsel *evsel,
178void perf_evsel__exit(struct perf_evsel *evsel); 184void perf_evsel__exit(struct perf_evsel *evsel);
179void perf_evsel__delete(struct perf_evsel *evsel); 185void perf_evsel__delete(struct perf_evsel *evsel);
180 186
187struct callchain_param;
188
181void perf_evsel__config(struct perf_evsel *evsel, 189void perf_evsel__config(struct perf_evsel *evsel,
182 struct record_opts *opts); 190 struct record_opts *opts,
191 struct callchain_param *callchain);
192void perf_evsel__config_callchain(struct perf_evsel *evsel,
193 struct record_opts *opts,
194 struct callchain_param *callchain);
183 195
184int __perf_evsel__sample_size(u64 sample_type); 196int __perf_evsel__sample_size(u64 sample_type);
185void perf_evsel__calc_id_pos(struct perf_evsel *evsel); 197void perf_evsel__calc_id_pos(struct perf_evsel *evsel);
@@ -252,6 +264,8 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel,
252 264
253struct format_field; 265struct format_field;
254 266
267u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap);
268
255struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); 269struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
256 270
257#define perf_evsel__match(evsel, t, c) \ 271#define perf_evsel__match(evsel, t, c) \
@@ -344,23 +358,7 @@ static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel)
344 return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; 358 return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1;
345} 359}
346 360
347/** 361bool perf_evsel__is_function_event(struct perf_evsel *evsel);
348 * perf_evsel__is_function_event - Return whether given evsel is a function
349 * trace event
350 *
351 * @evsel - evsel selector to be tested
352 *
353 * Return %true if event is function trace event
354 */
355static inline bool perf_evsel__is_function_event(struct perf_evsel *evsel)
356{
357#define FUNCTION_EVENT "ftrace:function"
358
359 return evsel->name &&
360 !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT));
361
362#undef FUNCTION_EVENT
363}
364 362
365static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel) 363static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel)
366{ 364{
@@ -381,6 +379,24 @@ struct perf_attr_details {
381int perf_evsel__fprintf(struct perf_evsel *evsel, 379int perf_evsel__fprintf(struct perf_evsel *evsel,
382 struct perf_attr_details *details, FILE *fp); 380 struct perf_attr_details *details, FILE *fp);
383 381
382#define EVSEL__PRINT_IP (1<<0)
383#define EVSEL__PRINT_SYM (1<<1)
384#define EVSEL__PRINT_DSO (1<<2)
385#define EVSEL__PRINT_SYMOFFSET (1<<3)
386#define EVSEL__PRINT_ONELINE (1<<4)
387#define EVSEL__PRINT_SRCLINE (1<<5)
388#define EVSEL__PRINT_UNKNOWN_AS_ADDR (1<<6)
389
390struct callchain_cursor;
391
392int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
393 unsigned int print_opts,
394 struct callchain_cursor *cursor, FILE *fp);
395
396int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
397 int left_alignment, unsigned int print_opts,
398 struct callchain_cursor *cursor, FILE *fp);
399
384bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 400bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
385 char *msg, size_t msgsize); 401 char *msg, size_t msgsize);
386int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target, 402int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
@@ -396,7 +412,7 @@ for ((_evsel) = list_entry((_leader)->node.next, struct perf_evsel, node); \
396 (_evsel) && (_evsel)->leader == (_leader); \ 412 (_evsel) && (_evsel)->leader == (_leader); \
397 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node)) 413 (_evsel) = list_entry((_evsel)->node.next, struct perf_evsel, node))
398 414
399static inline bool has_branch_callstack(struct perf_evsel *evsel) 415static inline bool perf_evsel__has_branch_callstack(const struct perf_evsel *evsel)
400{ 416{
401 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK; 417 return evsel->attr.branch_sample_type & PERF_SAMPLE_BRANCH_CALL_STACK;
402} 418}
@@ -406,4 +422,6 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
406int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, 422int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
407 attr__fprintf_f attr__fprintf, void *priv); 423 attr__fprintf_f attr__fprintf, void *priv);
408 424
425char *perf_evsel__env_arch(struct perf_evsel *evsel);
426
409#endif /* __PERF_EVSEL_H */ 427#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
new file mode 100644
index 000000000000..3674e77ad640
--- /dev/null
+++ b/tools/perf/util/evsel_fprintf.c
@@ -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}
diff --git a/tools/perf/util/group.h b/tools/perf/util/group.h
new file mode 100644
index 000000000000..116debe7a995
--- /dev/null
+++ b/tools/perf/util/group.h
@@ -0,0 +1,7 @@
1#ifndef GROUP_H
2#define GROUP_H 1
3
4bool arch_topdown_check_group(bool *warn);
5void arch_topdown_group_warn(void);
6
7#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 90680ec9f8b8..8f0db4007282 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -336,7 +336,7 @@ static int write_event_desc(int fd, struct perf_header *h __maybe_unused,
336 if (ret < 0) 336 if (ret < 0)
337 return ret; 337 return ret;
338 338
339 evlist__for_each(evlist, evsel) { 339 evlist__for_each_entry(evlist, evsel) {
340 ret = do_write(fd, &evsel->attr, sz); 340 ret = do_write(fd, &evsel->attr, sz);
341 if (ret < 0) 341 if (ret < 0)
342 return ret; 342 return ret;
@@ -801,7 +801,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
801 if (ret < 0) 801 if (ret < 0)
802 return ret; 802 return ret;
803 803
804 evlist__for_each(evlist, evsel) { 804 evlist__for_each_entry(evlist, evsel) {
805 if (perf_evsel__is_group_leader(evsel) && 805 if (perf_evsel__is_group_leader(evsel) &&
806 evsel->nr_members > 1) { 806 evsel->nr_members > 1) {
807 const char *name = evsel->group_name ?: "{anon_group}"; 807 const char *name = evsel->group_name ?: "{anon_group}";
@@ -1306,42 +1306,19 @@ static void print_total_mem(struct perf_header *ph, int fd __maybe_unused,
1306static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused, 1306static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
1307 FILE *fp) 1307 FILE *fp)
1308{ 1308{
1309 u32 nr, c, i; 1309 int i;
1310 char *str, *tmp; 1310 struct numa_node *n;
1311 uint64_t mem_total, mem_free;
1312
1313 /* nr nodes */
1314 nr = ph->env.nr_numa_nodes;
1315 str = ph->env.numa_nodes;
1316
1317 for (i = 0; i < nr; i++) {
1318 /* node number */
1319 c = strtoul(str, &tmp, 0);
1320 if (*tmp != ':')
1321 goto error;
1322
1323 str = tmp + 1;
1324 mem_total = strtoull(str, &tmp, 0);
1325 if (*tmp != ':')
1326 goto error;
1327 1311
1328 str = tmp + 1; 1312 for (i = 0; i < ph->env.nr_numa_nodes; i++) {
1329 mem_free = strtoull(str, &tmp, 0); 1313 n = &ph->env.numa_nodes[i];
1330 if (*tmp != ':')
1331 goto error;
1332 1314
1333 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," 1315 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1334 " free = %"PRIu64" kB\n", 1316 " free = %"PRIu64" kB\n",
1335 c, mem_total, mem_free); 1317 n->node, n->mem_total, n->mem_free);
1336
1337 str = tmp + 1;
1338 fprintf(fp, "# node%u cpu list : %s\n", c, str);
1339 1318
1340 str += strlen(str) + 1; 1319 fprintf(fp, "# node%u cpu list : ", n->node);
1320 cpu_map__fprintf(n->map, fp);
1341 } 1321 }
1342 return;
1343error:
1344 fprintf(fp, "# numa topology : not available\n");
1345} 1322}
1346 1323
1347static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) 1324static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
@@ -1425,7 +1402,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
1425 1402
1426 session = container_of(ph, struct perf_session, header); 1403 session = container_of(ph, struct perf_session, header);
1427 1404
1428 evlist__for_each(session->evlist, evsel) { 1405 evlist__for_each_entry(session->evlist, evsel) {
1429 if (perf_evsel__is_group_leader(evsel) && 1406 if (perf_evsel__is_group_leader(evsel) &&
1430 evsel->nr_members > 1) { 1407 evsel->nr_members > 1) {
1431 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", 1408 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
@@ -1474,7 +1451,7 @@ static int __event_process_build_id(struct build_id_event *bev,
1474 1451
1475 dso = machine__findnew_dso(machine, filename); 1452 dso = machine__findnew_dso(machine, filename);
1476 if (dso != NULL) { 1453 if (dso != NULL) {
1477 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1454 char sbuild_id[SBUILD_ID_SIZE];
1478 1455
1479 dso__set_build_id(dso, &bev->build_id); 1456 dso__set_build_id(dso, &bev->build_id);
1480 1457
@@ -1703,7 +1680,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1703{ 1680{
1704 struct perf_evsel *evsel; 1681 struct perf_evsel *evsel;
1705 1682
1706 evlist__for_each(evlist, evsel) { 1683 evlist__for_each_entry(evlist, evsel) {
1707 if (evsel->idx == idx) 1684 if (evsel->idx == idx)
1708 return evsel; 1685 return evsel;
1709 } 1686 }
@@ -1819,7 +1796,8 @@ static int process_cpu_topology(struct perf_file_section *section,
1819 1796
1820 ph->env.nr_sibling_cores = nr; 1797 ph->env.nr_sibling_cores = nr;
1821 size += sizeof(u32); 1798 size += sizeof(u32);
1822 strbuf_init(&sb, 128); 1799 if (strbuf_init(&sb, 128) < 0)
1800 goto free_cpu;
1823 1801
1824 for (i = 0; i < nr; i++) { 1802 for (i = 0; i < nr; i++) {
1825 str = do_read_string(fd, ph); 1803 str = do_read_string(fd, ph);
@@ -1827,7 +1805,8 @@ static int process_cpu_topology(struct perf_file_section *section,
1827 goto error; 1805 goto error;
1828 1806
1829 /* include a NULL character at the end */ 1807 /* include a NULL character at the end */
1830 strbuf_add(&sb, str, strlen(str) + 1); 1808 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1809 goto error;
1831 size += string_size(str); 1810 size += string_size(str);
1832 free(str); 1811 free(str);
1833 } 1812 }
@@ -1849,7 +1828,8 @@ static int process_cpu_topology(struct perf_file_section *section,
1849 goto error; 1828 goto error;
1850 1829
1851 /* include a NULL character at the end */ 1830 /* include a NULL character at the end */
1852 strbuf_add(&sb, str, strlen(str) + 1); 1831 if (strbuf_add(&sb, str, strlen(str) + 1) < 0)
1832 goto error;
1853 size += string_size(str); 1833 size += string_size(str);
1854 free(str); 1834 free(str);
1855 } 1835 }
@@ -1903,59 +1883,61 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1903 struct perf_header *ph, int fd, 1883 struct perf_header *ph, int fd,
1904 void *data __maybe_unused) 1884 void *data __maybe_unused)
1905{ 1885{
1886 struct numa_node *nodes, *n;
1906 ssize_t ret; 1887 ssize_t ret;
1907 u32 nr, node, i; 1888 u32 nr, i;
1908 char *str; 1889 char *str;
1909 uint64_t mem_total, mem_free;
1910 struct strbuf sb;
1911 1890
1912 /* nr nodes */ 1891 /* nr nodes */
1913 ret = readn(fd, &nr, sizeof(nr)); 1892 ret = readn(fd, &nr, sizeof(nr));
1914 if (ret != sizeof(nr)) 1893 if (ret != sizeof(nr))
1915 goto error; 1894 return -1;
1916 1895
1917 if (ph->needs_swap) 1896 if (ph->needs_swap)
1918 nr = bswap_32(nr); 1897 nr = bswap_32(nr);
1919 1898
1920 ph->env.nr_numa_nodes = nr; 1899 ph->env.nr_numa_nodes = nr;
1921 strbuf_init(&sb, 256); 1900 nodes = zalloc(sizeof(*nodes) * nr);
1901 if (!nodes)
1902 return -ENOMEM;
1922 1903
1923 for (i = 0; i < nr; i++) { 1904 for (i = 0; i < nr; i++) {
1905 n = &nodes[i];
1906
1924 /* node number */ 1907 /* node number */
1925 ret = readn(fd, &node, sizeof(node)); 1908 ret = readn(fd, &n->node, sizeof(u32));
1926 if (ret != sizeof(node)) 1909 if (ret != sizeof(n->node))
1927 goto error; 1910 goto error;
1928 1911
1929 ret = readn(fd, &mem_total, sizeof(u64)); 1912 ret = readn(fd, &n->mem_total, sizeof(u64));
1930 if (ret != sizeof(u64)) 1913 if (ret != sizeof(u64))
1931 goto error; 1914 goto error;
1932 1915
1933 ret = readn(fd, &mem_free, sizeof(u64)); 1916 ret = readn(fd, &n->mem_free, sizeof(u64));
1934 if (ret != sizeof(u64)) 1917 if (ret != sizeof(u64))
1935 goto error; 1918 goto error;
1936 1919
1937 if (ph->needs_swap) { 1920 if (ph->needs_swap) {
1938 node = bswap_32(node); 1921 n->node = bswap_32(n->node);
1939 mem_total = bswap_64(mem_total); 1922 n->mem_total = bswap_64(n->mem_total);
1940 mem_free = bswap_64(mem_free); 1923 n->mem_free = bswap_64(n->mem_free);
1941 } 1924 }
1942 1925
1943 strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
1944 node, mem_total, mem_free);
1945
1946 str = do_read_string(fd, ph); 1926 str = do_read_string(fd, ph);
1947 if (!str) 1927 if (!str)
1948 goto error; 1928 goto error;
1949 1929
1950 /* include a NULL character at the end */ 1930 n->map = cpu_map__new(str);
1951 strbuf_add(&sb, str, strlen(str) + 1); 1931 if (!n->map)
1932 goto error;
1933
1952 free(str); 1934 free(str);
1953 } 1935 }
1954 ph->env.numa_nodes = strbuf_detach(&sb, NULL); 1936 ph->env.numa_nodes = nodes;
1955 return 0; 1937 return 0;
1956 1938
1957error: 1939error:
1958 strbuf_release(&sb); 1940 free(nodes);
1959 return -1; 1941 return -1;
1960} 1942}
1961 1943
@@ -1982,7 +1964,8 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
1982 } 1964 }
1983 1965
1984 ph->env.nr_pmu_mappings = pmu_num; 1966 ph->env.nr_pmu_mappings = pmu_num;
1985 strbuf_init(&sb, 128); 1967 if (strbuf_init(&sb, 128) < 0)
1968 return -1;
1986 1969
1987 while (pmu_num) { 1970 while (pmu_num) {
1988 if (readn(fd, &type, sizeof(type)) != sizeof(type)) 1971 if (readn(fd, &type, sizeof(type)) != sizeof(type))
@@ -1994,9 +1977,11 @@ static int process_pmu_mappings(struct perf_file_section *section __maybe_unused
1994 if (!name) 1977 if (!name)
1995 goto error; 1978 goto error;
1996 1979
1997 strbuf_addf(&sb, "%u:%s", type, name); 1980 if (strbuf_addf(&sb, "%u:%s", type, name) < 0)
1981 goto error;
1998 /* include a NULL character at the end */ 1982 /* include a NULL character at the end */
1999 strbuf_add(&sb, "", 1); 1983 if (strbuf_add(&sb, "", 1) < 0)
1984 goto error;
2000 1985
2001 if (!strcmp(name, "msr")) 1986 if (!strcmp(name, "msr"))
2002 ph->env.msr_pmu_type = type; 1987 ph->env.msr_pmu_type = type;
@@ -2066,7 +2051,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2066 session->evlist->nr_groups = nr_groups; 2051 session->evlist->nr_groups = nr_groups;
2067 2052
2068 i = nr = 0; 2053 i = nr = 0;
2069 evlist__for_each(session->evlist, evsel) { 2054 evlist__for_each_entry(session->evlist, evsel) {
2070 if (evsel->idx == (int) desc[i].leader_idx) { 2055 if (evsel->idx == (int) desc[i].leader_idx) {
2071 evsel->leader = evsel; 2056 evsel->leader = evsel;
2072 /* {anon_group} is a dummy name */ 2057 /* {anon_group} is a dummy name */
@@ -2374,7 +2359,7 @@ int perf_session__write_header(struct perf_session *session,
2374 2359
2375 lseek(fd, sizeof(f_header), SEEK_SET); 2360 lseek(fd, sizeof(f_header), SEEK_SET);
2376 2361
2377 evlist__for_each(session->evlist, evsel) { 2362 evlist__for_each_entry(session->evlist, evsel) {
2378 evsel->id_offset = lseek(fd, 0, SEEK_CUR); 2363 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2379 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 2364 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
2380 if (err < 0) { 2365 if (err < 0) {
@@ -2385,7 +2370,7 @@ int perf_session__write_header(struct perf_session *session,
2385 2370
2386 attr_offset = lseek(fd, 0, SEEK_CUR); 2371 attr_offset = lseek(fd, 0, SEEK_CUR);
2387 2372
2388 evlist__for_each(evlist, evsel) { 2373 evlist__for_each_entry(evlist, evsel) {
2389 f_attr = (struct perf_file_attr){ 2374 f_attr = (struct perf_file_attr){
2390 .attr = evsel->attr, 2375 .attr = evsel->attr,
2391 .ids = { 2376 .ids = {
@@ -2819,7 +2804,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2819{ 2804{
2820 struct perf_evsel *pos; 2805 struct perf_evsel *pos;
2821 2806
2822 evlist__for_each(evlist, pos) { 2807 evlist__for_each_entry(evlist, pos) {
2823 if (pos->attr.type == PERF_TYPE_TRACEPOINT && 2808 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2824 perf_evsel__prepare_tracepoint_event(pos, pevent)) 2809 perf_evsel__prepare_tracepoint_event(pos, pevent))
2825 return -1; 2810 return -1;
@@ -3118,7 +3103,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
3118 struct perf_evsel *evsel; 3103 struct perf_evsel *evsel;
3119 int err = 0; 3104 int err = 0;
3120 3105
3121 evlist__for_each(session->evlist, evsel) { 3106 evlist__for_each_entry(session->evlist, evsel) {
3122 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, 3107 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
3123 evsel->id, process); 3108 evsel->id, process);
3124 if (err) { 3109 if (err) {
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
index 43a98a4dc1e1..2821f8d77e52 100644
--- a/tools/perf/util/help-unknown-cmd.c
+++ b/tools/perf/util/help-unknown-cmd.c
@@ -1,4 +1,6 @@
1#include "cache.h" 1#include "cache.h"
2#include "config.h"
3#include <stdio.h>
2#include <subcmd/help.h> 4#include <subcmd/help.h>
3#include "../builtin.h" 5#include "../builtin.h"
4#include "levenshtein.h" 6#include "levenshtein.h"
@@ -27,16 +29,27 @@ static int levenshtein_compare(const void *p1, const void *p2)
27 return l1 != l2 ? l1 - l2 : strcmp(s1, s2); 29 return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
28} 30}
29 31
30static void add_cmd_list(struct cmdnames *cmds, struct cmdnames *old) 32static int add_cmd_list(struct cmdnames *cmds, struct cmdnames *old)
31{ 33{
32 unsigned int i; 34 unsigned int i, nr = cmds->cnt + old->cnt;
33 35 void *tmp;
34 ALLOC_GROW(cmds->names, cmds->cnt + old->cnt, cmds->alloc); 36
35 37 if (nr > cmds->alloc) {
38 /* Choose bigger one to alloc */
39 if (alloc_nr(cmds->alloc) < nr)
40 cmds->alloc = nr;
41 else
42 cmds->alloc = alloc_nr(cmds->alloc);
43 tmp = realloc(cmds->names, cmds->alloc * sizeof(*cmds->names));
44 if (!tmp)
45 return -1;
46 cmds->names = tmp;
47 }
36 for (i = 0; i < old->cnt; i++) 48 for (i = 0; i < old->cnt; i++)
37 cmds->names[cmds->cnt++] = old->names[i]; 49 cmds->names[cmds->cnt++] = old->names[i];
38 zfree(&old->names); 50 zfree(&old->names);
39 old->cnt = 0; 51 old->cnt = 0;
52 return 0;
40} 53}
41 54
42const char *help_unknown_cmd(const char *cmd) 55const char *help_unknown_cmd(const char *cmd)
@@ -52,8 +65,11 @@ const char *help_unknown_cmd(const char *cmd)
52 65
53 load_command_list("perf-", &main_cmds, &other_cmds); 66 load_command_list("perf-", &main_cmds, &other_cmds);
54 67
55 add_cmd_list(&main_cmds, &aliases); 68 if (add_cmd_list(&main_cmds, &aliases) < 0 ||
56 add_cmd_list(&main_cmds, &other_cmds); 69 add_cmd_list(&main_cmds, &other_cmds) < 0) {
70 fprintf(stderr, "ERROR: Failed to allocate command list for unknown command.\n");
71 goto end;
72 }
57 qsort(main_cmds.names, main_cmds.cnt, 73 qsort(main_cmds.names, main_cmds.cnt,
58 sizeof(main_cmds.names), cmdname_compare); 74 sizeof(main_cmds.names), cmdname_compare);
59 uniq(&main_cmds); 75 uniq(&main_cmds);
@@ -99,6 +115,6 @@ const char *help_unknown_cmd(const char *cmd)
99 for (i = 0; i < n; i++) 115 for (i = 0; i < n; i++)
100 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name); 116 fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
101 } 117 }
102 118end:
103 exit(1); 119 exit(1);
104} 120}
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 31c4641fe5ff..de15dbcdcecf 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -79,7 +79,7 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
79 79
80 len = thread__comm_len(h->thread); 80 len = thread__comm_len(h->thread);
81 if (hists__new_col_len(hists, HISTC_COMM, len)) 81 if (hists__new_col_len(hists, HISTC_COMM, len))
82 hists__set_col_len(hists, HISTC_THREAD, len + 6); 82 hists__set_col_len(hists, HISTC_THREAD, len + 8);
83 83
84 if (h->ms.map) { 84 if (h->ms.map) {
85 len = dso__name_len(h->ms.map->dso); 85 len = dso__name_len(h->ms.map->dso);
@@ -117,6 +117,13 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
117 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen); 117 hists__new_col_len(hists, HISTC_SYMBOL_TO, symlen);
118 hists__set_unres_dso_col_len(hists, HISTC_DSO_TO); 118 hists__set_unres_dso_col_len(hists, HISTC_DSO_TO);
119 } 119 }
120
121 if (h->branch_info->srcline_from)
122 hists__new_col_len(hists, HISTC_SRCLINE_FROM,
123 strlen(h->branch_info->srcline_from));
124 if (h->branch_info->srcline_to)
125 hists__new_col_len(hists, HISTC_SRCLINE_TO,
126 strlen(h->branch_info->srcline_to));
120 } 127 }
121 128
122 if (h->mem_info) { 129 if (h->mem_info) {
@@ -295,7 +302,7 @@ static void hists__delete_entry(struct hists *hists, struct hist_entry *he)
295 root_in = &he->parent_he->hroot_in; 302 root_in = &he->parent_he->hroot_in;
296 root_out = &he->parent_he->hroot_out; 303 root_out = &he->parent_he->hroot_out;
297 } else { 304 } else {
298 if (sort__need_collapse) 305 if (hists__has(hists, need_collapse))
299 root_in = &hists->entries_collapsed; 306 root_in = &hists->entries_collapsed;
300 else 307 else
301 root_in = hists->entries_in; 308 root_in = hists->entries_in;
@@ -345,86 +352,114 @@ void hists__delete_entries(struct hists *hists)
345 * histogram, sorted on item, collects periods 352 * histogram, sorted on item, collects periods
346 */ 353 */
347 354
348static struct hist_entry *hist_entry__new(struct hist_entry *template, 355static int hist_entry__init(struct hist_entry *he,
349 bool sample_self) 356 struct hist_entry *template,
357 bool sample_self)
350{ 358{
351 size_t callchain_size = 0; 359 *he = *template;
352 struct hist_entry *he;
353 360
354 if (symbol_conf.use_callchain) 361 if (symbol_conf.cumulate_callchain) {
355 callchain_size = sizeof(struct callchain_root); 362 he->stat_acc = malloc(sizeof(he->stat));
363 if (he->stat_acc == NULL)
364 return -ENOMEM;
365 memcpy(he->stat_acc, &he->stat, sizeof(he->stat));
366 if (!sample_self)
367 memset(&he->stat, 0, sizeof(he->stat));
368 }
369
370 map__get(he->ms.map);
371
372 if (he->branch_info) {
373 /*
374 * This branch info is (a part of) allocated from
375 * sample__resolve_bstack() and will be freed after
376 * adding new entries. So we need to save a copy.
377 */
378 he->branch_info = malloc(sizeof(*he->branch_info));
379 if (he->branch_info == NULL) {
380 map__zput(he->ms.map);
381 free(he->stat_acc);
382 return -ENOMEM;
383 }
384
385 memcpy(he->branch_info, template->branch_info,
386 sizeof(*he->branch_info));
356 387
357 he = zalloc(sizeof(*he) + callchain_size); 388 map__get(he->branch_info->from.map);
389 map__get(he->branch_info->to.map);
390 }
391
392 if (he->mem_info) {
393 map__get(he->mem_info->iaddr.map);
394 map__get(he->mem_info->daddr.map);
395 }
358 396
359 if (he != NULL) { 397 if (symbol_conf.use_callchain)
360 *he = *template; 398 callchain_init(he->callchain);
399
400 if (he->raw_data) {
401 he->raw_data = memdup(he->raw_data, he->raw_size);
361 402
362 if (symbol_conf.cumulate_callchain) { 403 if (he->raw_data == NULL) {
363 he->stat_acc = malloc(sizeof(he->stat)); 404 map__put(he->ms.map);
364 if (he->stat_acc == NULL) { 405 if (he->branch_info) {
365 free(he); 406 map__put(he->branch_info->from.map);
366 return NULL; 407 map__put(he->branch_info->to.map);
408 free(he->branch_info);
367 } 409 }
368 memcpy(he->stat_acc, &he->stat, sizeof(he->stat)); 410 if (he->mem_info) {
369 if (!sample_self) 411 map__put(he->mem_info->iaddr.map);
370 memset(&he->stat, 0, sizeof(he->stat)); 412 map__put(he->mem_info->daddr.map);
413 }
414 free(he->stat_acc);
415 return -ENOMEM;
371 } 416 }
417 }
418 INIT_LIST_HEAD(&he->pairs.node);
419 thread__get(he->thread);
372 420
373 map__get(he->ms.map); 421 if (!symbol_conf.report_hierarchy)
422 he->leaf = true;
374 423
375 if (he->branch_info) { 424 return 0;
376 /* 425}
377 * This branch info is (a part of) allocated from 426
378 * sample__resolve_bstack() and will be freed after 427static void *hist_entry__zalloc(size_t size)
379 * adding new entries. So we need to save a copy. 428{
380 */ 429 return zalloc(size + sizeof(struct hist_entry));
381 he->branch_info = malloc(sizeof(*he->branch_info)); 430}
382 if (he->branch_info == NULL) {
383 map__zput(he->ms.map);
384 free(he->stat_acc);
385 free(he);
386 return NULL;
387 }
388 431
389 memcpy(he->branch_info, template->branch_info, 432static void hist_entry__free(void *ptr)
390 sizeof(*he->branch_info)); 433{
434 free(ptr);
435}
391 436
392 map__get(he->branch_info->from.map); 437static struct hist_entry_ops default_ops = {
393 map__get(he->branch_info->to.map); 438 .new = hist_entry__zalloc,
394 } 439 .free = hist_entry__free,
440};
395 441
396 if (he->mem_info) { 442static struct hist_entry *hist_entry__new(struct hist_entry *template,
397 map__get(he->mem_info->iaddr.map); 443 bool sample_self)
398 map__get(he->mem_info->daddr.map); 444{
399 } 445 struct hist_entry_ops *ops = template->ops;
446 size_t callchain_size = 0;
447 struct hist_entry *he;
448 int err = 0;
400 449
401 if (symbol_conf.use_callchain) 450 if (!ops)
402 callchain_init(he->callchain); 451 ops = template->ops = &default_ops;
403 452
404 if (he->raw_data) { 453 if (symbol_conf.use_callchain)
405 he->raw_data = memdup(he->raw_data, he->raw_size); 454 callchain_size = sizeof(struct callchain_root);
406 455
407 if (he->raw_data == NULL) { 456 he = ops->new(callchain_size);
408 map__put(he->ms.map); 457 if (he) {
409 if (he->branch_info) { 458 err = hist_entry__init(he, template, sample_self);
410 map__put(he->branch_info->from.map); 459 if (err) {
411 map__put(he->branch_info->to.map); 460 ops->free(he);
412 free(he->branch_info); 461 he = NULL;
413 }
414 if (he->mem_info) {
415 map__put(he->mem_info->iaddr.map);
416 map__put(he->mem_info->daddr.map);
417 }
418 free(he->stat_acc);
419 free(he);
420 return NULL;
421 }
422 } 462 }
423 INIT_LIST_HEAD(&he->pairs.node);
424 thread__get(he->thread);
425
426 if (!symbol_conf.report_hierarchy)
427 he->leaf = true;
428 } 463 }
429 464
430 return he; 465 return he;
@@ -524,13 +559,15 @@ out:
524 return he; 559 return he;
525} 560}
526 561
527struct hist_entry *__hists__add_entry(struct hists *hists, 562static struct hist_entry*
528 struct addr_location *al, 563__hists__add_entry(struct hists *hists,
529 struct symbol *sym_parent, 564 struct addr_location *al,
530 struct branch_info *bi, 565 struct symbol *sym_parent,
531 struct mem_info *mi, 566 struct branch_info *bi,
532 struct perf_sample *sample, 567 struct mem_info *mi,
533 bool sample_self) 568 struct perf_sample *sample,
569 bool sample_self,
570 struct hist_entry_ops *ops)
534{ 571{
535 struct hist_entry entry = { 572 struct hist_entry entry = {
536 .thread = al->thread, 573 .thread = al->thread,
@@ -557,11 +594,37 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
557 .transaction = sample->transaction, 594 .transaction = sample->transaction,
558 .raw_data = sample->raw_data, 595 .raw_data = sample->raw_data,
559 .raw_size = sample->raw_size, 596 .raw_size = sample->raw_size,
597 .ops = ops,
560 }; 598 };
561 599
562 return hists__findnew_entry(hists, &entry, al, sample_self); 600 return hists__findnew_entry(hists, &entry, al, sample_self);
563} 601}
564 602
603struct hist_entry *hists__add_entry(struct hists *hists,
604 struct addr_location *al,
605 struct symbol *sym_parent,
606 struct branch_info *bi,
607 struct mem_info *mi,
608 struct perf_sample *sample,
609 bool sample_self)
610{
611 return __hists__add_entry(hists, al, sym_parent, bi, mi,
612 sample, sample_self, NULL);
613}
614
615struct hist_entry *hists__add_entry_ops(struct hists *hists,
616 struct hist_entry_ops *ops,
617 struct addr_location *al,
618 struct symbol *sym_parent,
619 struct branch_info *bi,
620 struct mem_info *mi,
621 struct perf_sample *sample,
622 bool sample_self)
623{
624 return __hists__add_entry(hists, al, sym_parent, bi, mi,
625 sample, sample_self, ops);
626}
627
565static int 628static int
566iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused, 629iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused,
567 struct addr_location *al __maybe_unused) 630 struct addr_location *al __maybe_unused)
@@ -615,8 +678,8 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
615 */ 678 */
616 sample->period = cost; 679 sample->period = cost;
617 680
618 he = __hists__add_entry(hists, al, iter->parent, NULL, mi, 681 he = hists__add_entry(hists, al, iter->parent, NULL, mi,
619 sample, true); 682 sample, true);
620 if (!he) 683 if (!he)
621 return -ENOMEM; 684 return -ENOMEM;
622 685
@@ -720,8 +783,8 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
720 sample->period = 1; 783 sample->period = 1;
721 sample->weight = bi->flags.cycles ? bi->flags.cycles : 1; 784 sample->weight = bi->flags.cycles ? bi->flags.cycles : 1;
722 785
723 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL, 786 he = hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
724 sample, true); 787 sample, true);
725 if (he == NULL) 788 if (he == NULL)
726 return -ENOMEM; 789 return -ENOMEM;
727 790
@@ -757,8 +820,8 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
757 struct perf_sample *sample = iter->sample; 820 struct perf_sample *sample = iter->sample;
758 struct hist_entry *he; 821 struct hist_entry *he;
759 822
760 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 823 he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
761 sample, true); 824 sample, true);
762 if (he == NULL) 825 if (he == NULL)
763 return -ENOMEM; 826 return -ENOMEM;
764 827
@@ -818,8 +881,8 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
818 struct hist_entry *he; 881 struct hist_entry *he;
819 int err = 0; 882 int err = 0;
820 883
821 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL, 884 he = hists__add_entry(hists, al, iter->parent, NULL, NULL,
822 sample, true); 885 sample, true);
823 if (he == NULL) 886 if (he == NULL)
824 return -ENOMEM; 887 return -ENOMEM;
825 888
@@ -893,8 +956,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
893 } 956 }
894 } 957 }
895 958
896 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 959 he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
897 sample, false); 960 sample, false);
898 if (he == NULL) 961 if (he == NULL)
899 return -ENOMEM; 962 return -ENOMEM;
900 963
@@ -953,7 +1016,7 @@ int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
953{ 1016{
954 int err, err2; 1017 int err, err2;
955 1018
956 err = sample__resolve_callchain(iter->sample, &iter->parent, 1019 err = sample__resolve_callchain(iter->sample, &callchain_cursor, &iter->parent,
957 iter->evsel, al, max_stack_depth); 1020 iter->evsel, al, max_stack_depth);
958 if (err) 1021 if (err)
959 return err; 1022 return err;
@@ -1036,12 +1099,16 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
1036 1099
1037void hist_entry__delete(struct hist_entry *he) 1100void hist_entry__delete(struct hist_entry *he)
1038{ 1101{
1102 struct hist_entry_ops *ops = he->ops;
1103
1039 thread__zput(he->thread); 1104 thread__zput(he->thread);
1040 map__zput(he->ms.map); 1105 map__zput(he->ms.map);
1041 1106
1042 if (he->branch_info) { 1107 if (he->branch_info) {
1043 map__zput(he->branch_info->from.map); 1108 map__zput(he->branch_info->from.map);
1044 map__zput(he->branch_info->to.map); 1109 map__zput(he->branch_info->to.map);
1110 free_srcline(he->branch_info->srcline_from);
1111 free_srcline(he->branch_info->srcline_to);
1045 zfree(&he->branch_info); 1112 zfree(&he->branch_info);
1046 } 1113 }
1047 1114
@@ -1058,7 +1125,7 @@ void hist_entry__delete(struct hist_entry *he)
1058 free_callchain(he->callchain); 1125 free_callchain(he->callchain);
1059 free(he->trace_output); 1126 free(he->trace_output);
1060 free(he->raw_data); 1127 free(he->raw_data);
1061 free(he); 1128 ops->free(he);
1062} 1129}
1063 1130
1064/* 1131/*
@@ -1072,7 +1139,7 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
1072 struct perf_hpp_fmt *fmt, int printed) 1139 struct perf_hpp_fmt *fmt, int printed)
1073{ 1140{
1074 if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) { 1141 if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) {
1075 const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists)); 1142 const int width = fmt->width(fmt, hpp, he->hists);
1076 if (printed < width) { 1143 if (printed < width) {
1077 advance_hpp(hpp, printed); 1144 advance_hpp(hpp, printed);
1078 printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " "); 1145 printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " ");
@@ -1295,8 +1362,9 @@ static int hists__hierarchy_insert_entry(struct hists *hists,
1295 return ret; 1362 return ret;
1296} 1363}
1297 1364
1298int hists__collapse_insert_entry(struct hists *hists, struct rb_root *root, 1365static int hists__collapse_insert_entry(struct hists *hists,
1299 struct hist_entry *he) 1366 struct rb_root *root,
1367 struct hist_entry *he)
1300{ 1368{
1301 struct rb_node **p = &root->rb_node; 1369 struct rb_node **p = &root->rb_node;
1302 struct rb_node *parent = NULL; 1370 struct rb_node *parent = NULL;
@@ -1372,7 +1440,7 @@ int hists__collapse_resort(struct hists *hists, struct ui_progress *prog)
1372 struct hist_entry *n; 1440 struct hist_entry *n;
1373 int ret; 1441 int ret;
1374 1442
1375 if (!sort__need_collapse) 1443 if (!hists__has(hists, need_collapse))
1376 return 0; 1444 return 0;
1377 1445
1378 hists->nr_entries = 0; 1446 hists->nr_entries = 0;
@@ -1604,7 +1672,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
1604} 1672}
1605 1673
1606static void output_resort(struct hists *hists, struct ui_progress *prog, 1674static void output_resort(struct hists *hists, struct ui_progress *prog,
1607 bool use_callchain) 1675 bool use_callchain, hists__resort_cb_t cb)
1608{ 1676{
1609 struct rb_root *root; 1677 struct rb_root *root;
1610 struct rb_node *next; 1678 struct rb_node *next;
@@ -1631,7 +1699,7 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
1631 return; 1699 return;
1632 } 1700 }
1633 1701
1634 if (sort__need_collapse) 1702 if (hists__has(hists, need_collapse))
1635 root = &hists->entries_collapsed; 1703 root = &hists->entries_collapsed;
1636 else 1704 else
1637 root = hists->entries_in; 1705 root = hists->entries_in;
@@ -1643,6 +1711,9 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
1643 n = rb_entry(next, struct hist_entry, rb_node_in); 1711 n = rb_entry(next, struct hist_entry, rb_node_in);
1644 next = rb_next(&n->rb_node_in); 1712 next = rb_next(&n->rb_node_in);
1645 1713
1714 if (cb && cb(n))
1715 continue;
1716
1646 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain); 1717 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain);
1647 hists__inc_stats(hists, n); 1718 hists__inc_stats(hists, n);
1648 1719
@@ -1663,12 +1734,18 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1663 else 1734 else
1664 use_callchain = symbol_conf.use_callchain; 1735 use_callchain = symbol_conf.use_callchain;
1665 1736
1666 output_resort(evsel__hists(evsel), prog, use_callchain); 1737 output_resort(evsel__hists(evsel), prog, use_callchain, NULL);
1667} 1738}
1668 1739
1669void hists__output_resort(struct hists *hists, struct ui_progress *prog) 1740void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1670{ 1741{
1671 output_resort(hists, prog, symbol_conf.use_callchain); 1742 output_resort(hists, prog, symbol_conf.use_callchain, NULL);
1743}
1744
1745void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
1746 hists__resort_cb_t cb)
1747{
1748 output_resort(hists, prog, symbol_conf.use_callchain, cb);
1672} 1749}
1673 1750
1674static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd) 1751static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd)
@@ -2035,7 +2112,7 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
2035 struct hist_entry *he; 2112 struct hist_entry *he;
2036 int64_t cmp; 2113 int64_t cmp;
2037 2114
2038 if (sort__need_collapse) 2115 if (hists__has(hists, need_collapse))
2039 root = &hists->entries_collapsed; 2116 root = &hists->entries_collapsed;
2040 else 2117 else
2041 root = hists->entries_in; 2118 root = hists->entries_in;
@@ -2061,6 +2138,8 @@ static struct hist_entry *hists__add_dummy_entry(struct hists *hists,
2061 if (he) { 2138 if (he) {
2062 memset(&he->stat, 0, sizeof(he->stat)); 2139 memset(&he->stat, 0, sizeof(he->stat));
2063 he->hists = hists; 2140 he->hists = hists;
2141 if (symbol_conf.cumulate_callchain)
2142 memset(he->stat_acc, 0, sizeof(he->stat));
2064 rb_link_node(&he->rb_node_in, parent, p); 2143 rb_link_node(&he->rb_node_in, parent, p);
2065 rb_insert_color(&he->rb_node_in, root); 2144 rb_insert_color(&he->rb_node_in, root);
2066 hists__inc_stats(hists, he); 2145 hists__inc_stats(hists, he);
@@ -2075,7 +2154,7 @@ static struct hist_entry *hists__find_entry(struct hists *hists,
2075{ 2154{
2076 struct rb_node *n; 2155 struct rb_node *n;
2077 2156
2078 if (sort__need_collapse) 2157 if (hists__has(hists, need_collapse))
2079 n = hists->entries_collapsed.rb_node; 2158 n = hists->entries_collapsed.rb_node;
2080 else 2159 else
2081 n = hists->entries_in->rb_node; 2160 n = hists->entries_in->rb_node;
@@ -2104,7 +2183,7 @@ void hists__match(struct hists *leader, struct hists *other)
2104 struct rb_node *nd; 2183 struct rb_node *nd;
2105 struct hist_entry *pos, *pair; 2184 struct hist_entry *pos, *pair;
2106 2185
2107 if (sort__need_collapse) 2186 if (hists__has(leader, need_collapse))
2108 root = &leader->entries_collapsed; 2187 root = &leader->entries_collapsed;
2109 else 2188 else
2110 root = leader->entries_in; 2189 root = leader->entries_in;
@@ -2129,7 +2208,7 @@ int hists__link(struct hists *leader, struct hists *other)
2129 struct rb_node *nd; 2208 struct rb_node *nd;
2130 struct hist_entry *pos, *pair; 2209 struct hist_entry *pos, *pair;
2131 2210
2132 if (sort__need_collapse) 2211 if (hists__has(other, need_collapse))
2133 root = &other->entries_collapsed; 2212 root = &other->entries_collapsed;
2134 else 2213 else
2135 root = other->entries_in; 2214 root = other->entries_in;
@@ -2187,7 +2266,7 @@ size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
2187 struct perf_evsel *pos; 2266 struct perf_evsel *pos;
2188 size_t ret = 0; 2267 size_t ret = 0;
2189 2268
2190 evlist__for_each(evlist, pos) { 2269 evlist__for_each_entry(evlist, pos) {
2191 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); 2270 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
2192 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); 2271 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp);
2193 } 2272 }
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index bec0cd660fbd..0a1edf1ab450 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -10,6 +10,7 @@
10#include "ui/progress.h" 10#include "ui/progress.h"
11 11
12struct hist_entry; 12struct hist_entry;
13struct hist_entry_ops;
13struct addr_location; 14struct addr_location;
14struct symbol; 15struct symbol;
15 16
@@ -52,6 +53,8 @@ enum hist_column {
52 HISTC_MEM_IADDR_SYMBOL, 53 HISTC_MEM_IADDR_SYMBOL,
53 HISTC_TRANSACTION, 54 HISTC_TRANSACTION,
54 HISTC_CYCLES, 55 HISTC_CYCLES,
56 HISTC_SRCLINE_FROM,
57 HISTC_SRCLINE_TO,
55 HISTC_TRACE, 58 HISTC_TRACE,
56 HISTC_NR_COLS, /* Last entry */ 59 HISTC_NR_COLS, /* Last entry */
57}; 60};
@@ -82,6 +85,8 @@ struct hists {
82 int nr_hpp_node; 85 int nr_hpp_node;
83}; 86};
84 87
88#define hists__has(__h, __f) (__h)->hpp_list->__f
89
85struct hist_entry_iter; 90struct hist_entry_iter;
86 91
87struct hist_iter_ops { 92struct hist_iter_ops {
@@ -116,13 +121,23 @@ extern const struct hist_iter_ops hist_iter_branch;
116extern const struct hist_iter_ops hist_iter_mem; 121extern const struct hist_iter_ops hist_iter_mem;
117extern const struct hist_iter_ops hist_iter_cumulative; 122extern const struct hist_iter_ops hist_iter_cumulative;
118 123
119struct hist_entry *__hists__add_entry(struct hists *hists, 124struct hist_entry *hists__add_entry(struct hists *hists,
120 struct addr_location *al, 125 struct addr_location *al,
121 struct symbol *parent, 126 struct symbol *parent,
122 struct branch_info *bi, 127 struct branch_info *bi,
123 struct mem_info *mi, 128 struct mem_info *mi,
124 struct perf_sample *sample, 129 struct perf_sample *sample,
125 bool sample_self); 130 bool sample_self);
131
132struct hist_entry *hists__add_entry_ops(struct hists *hists,
133 struct hist_entry_ops *ops,
134 struct addr_location *al,
135 struct symbol *sym_parent,
136 struct branch_info *bi,
137 struct mem_info *mi,
138 struct perf_sample *sample,
139 bool sample_self);
140
126int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al, 141int hist_entry_iter__add(struct hist_entry_iter *iter, struct addr_location *al,
127 int max_stack_depth, void *arg); 142 int max_stack_depth, void *arg);
128 143
@@ -138,8 +153,12 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
138 struct perf_hpp_fmt *fmt, int printed); 153 struct perf_hpp_fmt *fmt, int printed);
139void hist_entry__delete(struct hist_entry *he); 154void hist_entry__delete(struct hist_entry *he);
140 155
156typedef int (*hists__resort_cb_t)(struct hist_entry *he);
157
141void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog); 158void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *prog);
142void hists__output_resort(struct hists *hists, struct ui_progress *prog); 159void hists__output_resort(struct hists *hists, struct ui_progress *prog);
160void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
161 hists__resort_cb_t cb);
143int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 162int hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
144 163
145void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel); 164void hists__decay_entries(struct hists *hists, bool zap_user, bool zap_kernel);
@@ -155,7 +174,8 @@ void events_stats__inc(struct events_stats *stats, u32 type);
155size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); 174size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
156 175
157size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 176size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
158 int max_cols, float min_pcnt, FILE *fp); 177 int max_cols, float min_pcnt, FILE *fp,
178 bool use_callchain);
159size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp); 179size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp);
160 180
161void hists__filter_by_dso(struct hists *hists); 181void hists__filter_by_dso(struct hists *hists);
@@ -199,8 +219,6 @@ int hists__init(void);
199int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list); 219int __hists__init(struct hists *hists, struct perf_hpp_list *hpp_list);
200 220
201struct rb_root *hists__get_rotate_entries_in(struct hists *hists); 221struct 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 222
205struct perf_hpp { 223struct perf_hpp {
206 char *buf; 224 char *buf;
@@ -212,9 +230,9 @@ struct perf_hpp {
212struct perf_hpp_fmt { 230struct perf_hpp_fmt {
213 const char *name; 231 const char *name;
214 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 232 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
215 struct perf_evsel *evsel); 233 struct hists *hists);
216 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 234 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
217 struct perf_evsel *evsel); 235 struct hists *hists);
218 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 236 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
219 struct hist_entry *he); 237 struct hist_entry *he);
220 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 238 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -240,6 +258,14 @@ struct perf_hpp_fmt {
240struct perf_hpp_list { 258struct perf_hpp_list {
241 struct list_head fields; 259 struct list_head fields;
242 struct list_head sorts; 260 struct list_head sorts;
261
262 int need_collapse;
263 int parent;
264 int sym;
265 int dso;
266 int socket;
267 int thread;
268 int comm;
243}; 269};
244 270
245extern struct perf_hpp_list perf_hpp_list; 271extern struct perf_hpp_list perf_hpp_list;
diff --git a/tools/perf/util/include/asm/alternative-asm.h b/tools/perf/util/include/asm/alternative-asm.h
deleted file mode 100644
index 3a3a0f16456a..000000000000
--- a/tools/perf/util/include/asm/alternative-asm.h
+++ /dev/null
@@ -1,9 +0,0 @@
1#ifndef _PERF_ASM_ALTERNATIVE_ASM_H
2#define _PERF_ASM_ALTERNATIVE_ASM_H
3
4/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */
5
6#define altinstruction_entry #
7#define ALTERNATIVE_2 #
8
9#endif
diff --git a/tools/perf/util/include/asm/byteorder.h b/tools/perf/util/include/asm/byteorder.h
deleted file mode 100644
index 2a9bdc066307..000000000000
--- a/tools/perf/util/include/asm/byteorder.h
+++ /dev/null
@@ -1,2 +0,0 @@
1#include <asm/types.h>
2#include "../../../../include/uapi/linux/swab.h"
diff --git a/tools/perf/util/include/asm/unistd_32.h b/tools/perf/util/include/asm/unistd_32.h
deleted file mode 100644
index 8b137891791f..000000000000
--- a/tools/perf/util/include/asm/unistd_32.h
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/tools/perf/util/include/asm/unistd_64.h b/tools/perf/util/include/asm/unistd_64.h
deleted file mode 100644
index 8b137891791f..000000000000
--- a/tools/perf/util/include/asm/unistd_64.h
+++ /dev/null
@@ -1 +0,0 @@
1
diff --git a/tools/perf/util/include/linux/const.h b/tools/perf/util/include/linux/const.h
deleted file mode 100644
index c10a35e1afb8..000000000000
--- a/tools/perf/util/include/linux/const.h
+++ /dev/null
@@ -1 +0,0 @@
1#include "../../../../include/uapi/linux/const.h"
diff --git a/tools/perf/util/intel-bts.c b/tools/perf/util/intel-bts.c
index abf1366e2a24..749e6f2e37ca 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -66,6 +66,7 @@ struct intel_bts {
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,
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);
@@ -417,7 +422,8 @@ static int intel_bts_get_branch_type(struct intel_bts_queue *btsq,
417} 422}
418 423
419static int intel_bts_process_buffer(struct intel_bts_queue *btsq, 424static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
420 struct auxtrace_buffer *buffer) 425 struct auxtrace_buffer *buffer,
426 struct thread *thread)
421{ 427{
422 struct branch *branch; 428 struct branch *branch;
423 size_t sz, bsz = sizeof(struct branch); 429 size_t sz, bsz = sizeof(struct branch);
@@ -439,6 +445,12 @@ static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
439 if (!branch->from && !branch->to) 445 if (!branch->from && !branch->to)
440 continue; 446 continue;
441 intel_bts_get_branch_type(btsq, branch); 447 intel_bts_get_branch_type(btsq, branch);
448 if (btsq->bts->synth_opts.thread_stack)
449 thread_stack__event(thread, btsq->sample_flags,
450 le64_to_cpu(branch->from),
451 le64_to_cpu(branch->to),
452 btsq->intel_pt_insn.length,
453 buffer->buffer_nr + 1);
442 if (filter && !(filter & btsq->sample_flags)) 454 if (filter && !(filter & btsq->sample_flags))
443 continue; 455 continue;
444 err = intel_bts_synth_branch_sample(btsq, branch); 456 err = intel_bts_synth_branch_sample(btsq, branch);
@@ -502,12 +514,13 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
502 goto out_put; 514 goto out_put;
503 } 515 }
504 516
505 if (!btsq->bts->synth_opts.callchain && thread && 517 if (!btsq->bts->synth_opts.callchain &&
518 !btsq->bts->synth_opts.thread_stack && thread &&
506 (!old_buffer || btsq->bts->sampling_mode || 519 (!old_buffer || btsq->bts->sampling_mode ||
507 (btsq->bts->snapshot_mode && !buffer->consecutive))) 520 (btsq->bts->snapshot_mode && !buffer->consecutive)))
508 thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1); 521 thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1);
509 522
510 err = intel_bts_process_buffer(btsq, buffer); 523 err = intel_bts_process_buffer(btsq, buffer, thread);
511 524
512 auxtrace_buffer__drop_data(buffer); 525 auxtrace_buffer__drop_data(buffer);
513 526
@@ -772,7 +785,7 @@ static int intel_bts_synth_events(struct intel_bts *bts,
772 u64 id; 785 u64 id;
773 int err; 786 int err;
774 787
775 evlist__for_each(evlist, evsel) { 788 evlist__for_each_entry(evlist, evsel) {
776 if (evsel->attr.type == bts->pmu_type && evsel->ids) { 789 if (evsel->attr.type == bts->pmu_type && evsel->ids) {
777 found = true; 790 found = true;
778 break; 791 break;
@@ -900,10 +913,14 @@ int intel_bts_process_auxtrace_info(union perf_event *event,
900 if (dump_trace) 913 if (dump_trace)
901 return 0; 914 return 0;
902 915
903 if (session->itrace_synth_opts && session->itrace_synth_opts->set) 916 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
904 bts->synth_opts = *session->itrace_synth_opts; 917 bts->synth_opts = *session->itrace_synth_opts;
905 else 918 } else {
906 itrace_synth_opts__set_default(&bts->synth_opts); 919 itrace_synth_opts__set_default(&bts->synth_opts);
920 if (session->itrace_synth_opts)
921 bts->synth_opts.thread_stack =
922 session->itrace_synth_opts->thread_stack;
923 }
907 924
908 if (bts->synth_opts.calls) 925 if (bts->synth_opts.calls)
909 bts->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | 926 bts->branches_filter |= PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC |
diff --git a/tools/perf/util/intel-pt-decoder/Build b/tools/perf/util/intel-pt-decoder/Build
index 0611d619a42e..9b742ea8bfe8 100644
--- a/tools/perf/util/intel-pt-decoder/Build
+++ b/tools/perf/util/intel-pt-decoder/Build
@@ -7,8 +7,11 @@ $(OUTPUT)util/intel-pt-decoder/inat-tables.c: $(inat_tables_script) $(inat_table
7 $(call rule_mkdir) 7 $(call rule_mkdir)
8 @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@ 8 @$(call echo-cmd,gen)$(AWK) -f $(inat_tables_script) $(inat_tables_maps) > $@ || rm -f $@
9 9
10# Busybox's diff doesn't have -I, avoid warning in the case
11
10$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/intel-pt-insn-decoder.c util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c 12$(OUTPUT)util/intel-pt-decoder/intel-pt-insn-decoder.o: util/intel-pt-decoder/intel-pt-insn-decoder.c util/intel-pt-decoder/inat.c $(OUTPUT)util/intel-pt-decoder/inat-tables.c
11 @(test -d ../../kernel -a -d ../../tools -a -d ../perf && (( \ 13 @(diff -I 2>&1 | grep -q 'option requires an argument' && \
14 test -d ../../kernel -a -d ../../tools -a -d ../perf && (( \
12 diff -B -I'^#include' util/intel-pt-decoder/insn.c ../../arch/x86/lib/insn.c >/dev/null && \ 15 diff -B -I'^#include' util/intel-pt-decoder/insn.c ../../arch/x86/lib/insn.c >/dev/null && \
13 diff -B -I'^#include' util/intel-pt-decoder/inat.c ../../arch/x86/lib/inat.c >/dev/null && \ 16 diff -B -I'^#include' util/intel-pt-decoder/inat.c ../../arch/x86/lib/inat.c >/dev/null && \
14 diff -B util/intel-pt-decoder/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \ 17 diff -B util/intel-pt-decoder/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \
diff --git a/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk b/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
index 517567347aac..54e961659514 100644
--- a/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
+++ b/tools/perf/util/intel-pt-decoder/gen-insn-attr-x86.awk
@@ -72,12 +72,14 @@ BEGIN {
72 lprefix_expr = "\\((66|F2|F3)\\)" 72 lprefix_expr = "\\((66|F2|F3)\\)"
73 max_lprefix = 4 73 max_lprefix = 4
74 74
75 # All opcodes starting with lower-case 'v' or with (v1) superscript 75 # All opcodes starting with lower-case 'v', 'k' or with (v1) superscript
76 # accepts VEX prefix 76 # accepts VEX prefix
77 vexok_opcode_expr = "^v.*" 77 vexok_opcode_expr = "^[vk].*"
78 vexok_expr = "\\(v1\\)" 78 vexok_expr = "\\(v1\\)"
79 # All opcodes with (v) superscript supports *only* VEX prefix 79 # All opcodes with (v) superscript supports *only* VEX prefix
80 vexonly_expr = "\\(v\\)" 80 vexonly_expr = "\\(v\\)"
81 # All opcodes with (ev) superscript supports *only* EVEX prefix
82 evexonly_expr = "\\(ev\\)"
81 83
82 prefix_expr = "\\(Prefix\\)" 84 prefix_expr = "\\(Prefix\\)"
83 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ" 85 prefix_num["Operand-Size"] = "INAT_PFX_OPNDSZ"
@@ -95,6 +97,7 @@ BEGIN {
95 prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ" 97 prefix_num["Address-Size"] = "INAT_PFX_ADDRSZ"
96 prefix_num["VEX+1byte"] = "INAT_PFX_VEX2" 98 prefix_num["VEX+1byte"] = "INAT_PFX_VEX2"
97 prefix_num["VEX+2byte"] = "INAT_PFX_VEX3" 99 prefix_num["VEX+2byte"] = "INAT_PFX_VEX3"
100 prefix_num["EVEX"] = "INAT_PFX_EVEX"
98 101
99 clear_vars() 102 clear_vars()
100} 103}
@@ -319,7 +322,9 @@ function convert_operands(count,opnd, i,j,imm,mod)
319 flags = add_flags(flags, "INAT_MODRM") 322 flags = add_flags(flags, "INAT_MODRM")
320 323
321 # check VEX codes 324 # check VEX codes
322 if (match(ext, vexonly_expr)) 325 if (match(ext, evexonly_expr))
326 flags = add_flags(flags, "INAT_VEXOK | INAT_EVEXONLY")
327 else if (match(ext, vexonly_expr))
323 flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY") 328 flags = add_flags(flags, "INAT_VEXOK | INAT_VEXONLY")
324 else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr)) 329 else if (match(ext, vexok_expr) || match(opcode, vexok_opcode_expr))
325 flags = add_flags(flags, "INAT_VEXOK") 330 flags = add_flags(flags, "INAT_VEXOK")
diff --git a/tools/perf/util/intel-pt-decoder/inat.h b/tools/perf/util/intel-pt-decoder/inat.h
index 611645e903a8..125ecd2a300d 100644
--- a/tools/perf/util/intel-pt-decoder/inat.h
+++ b/tools/perf/util/intel-pt-decoder/inat.h
@@ -48,6 +48,7 @@
48/* AVX VEX prefixes */ 48/* AVX VEX prefixes */
49#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */ 49#define INAT_PFX_VEX2 13 /* 2-bytes VEX prefix */
50#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */ 50#define INAT_PFX_VEX3 14 /* 3-bytes VEX prefix */
51#define INAT_PFX_EVEX 15 /* EVEX prefix */
51 52
52#define INAT_LSTPFX_MAX 3 53#define INAT_LSTPFX_MAX 3
53#define INAT_LGCPFX_MAX 11 54#define INAT_LGCPFX_MAX 11
@@ -89,6 +90,7 @@
89#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4)) 90#define INAT_VARIANT (1 << (INAT_FLAG_OFFS + 4))
90#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5)) 91#define INAT_VEXOK (1 << (INAT_FLAG_OFFS + 5))
91#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6)) 92#define INAT_VEXONLY (1 << (INAT_FLAG_OFFS + 6))
93#define INAT_EVEXONLY (1 << (INAT_FLAG_OFFS + 7))
92/* Attribute making macros for attribute tables */ 94/* Attribute making macros for attribute tables */
93#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS) 95#define INAT_MAKE_PREFIX(pfx) (pfx << INAT_PFX_OFFS)
94#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS) 96#define INAT_MAKE_ESCAPE(esc) (esc << INAT_ESC_OFFS)
@@ -141,7 +143,13 @@ static inline int inat_last_prefix_id(insn_attr_t attr)
141static inline int inat_is_vex_prefix(insn_attr_t attr) 143static inline int inat_is_vex_prefix(insn_attr_t attr)
142{ 144{
143 attr &= INAT_PFX_MASK; 145 attr &= INAT_PFX_MASK;
144 return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3; 146 return attr == INAT_PFX_VEX2 || attr == INAT_PFX_VEX3 ||
147 attr == INAT_PFX_EVEX;
148}
149
150static inline int inat_is_evex_prefix(insn_attr_t attr)
151{
152 return (attr & INAT_PFX_MASK) == INAT_PFX_EVEX;
145} 153}
146 154
147static inline int inat_is_vex3_prefix(insn_attr_t attr) 155static inline int inat_is_vex3_prefix(insn_attr_t attr)
@@ -216,6 +224,11 @@ static inline int inat_accept_vex(insn_attr_t attr)
216 224
217static inline int inat_must_vex(insn_attr_t attr) 225static inline int inat_must_vex(insn_attr_t attr)
218{ 226{
219 return attr & INAT_VEXONLY; 227 return attr & (INAT_VEXONLY | INAT_EVEXONLY);
228}
229
230static inline int inat_must_evex(insn_attr_t attr)
231{
232 return attr & INAT_EVEXONLY;
220} 233}
221#endif 234#endif
diff --git a/tools/perf/util/intel-pt-decoder/insn.c b/tools/perf/util/intel-pt-decoder/insn.c
index 9f26eae6c9f0..ca983e2bea8b 100644
--- a/tools/perf/util/intel-pt-decoder/insn.c
+++ b/tools/perf/util/intel-pt-decoder/insn.c
@@ -155,14 +155,24 @@ found:
155 /* 155 /*
156 * In 32-bits mode, if the [7:6] bits (mod bits of 156 * In 32-bits mode, if the [7:6] bits (mod bits of
157 * ModRM) on the second byte are not 11b, it is 157 * ModRM) on the second byte are not 11b, it is
158 * LDS or LES. 158 * LDS or LES or BOUND.
159 */ 159 */
160 if (X86_MODRM_MOD(b2) != 3) 160 if (X86_MODRM_MOD(b2) != 3)
161 goto vex_end; 161 goto vex_end;
162 } 162 }
163 insn->vex_prefix.bytes[0] = b; 163 insn->vex_prefix.bytes[0] = b;
164 insn->vex_prefix.bytes[1] = b2; 164 insn->vex_prefix.bytes[1] = b2;
165 if (inat_is_vex3_prefix(attr)) { 165 if (inat_is_evex_prefix(attr)) {
166 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
167 insn->vex_prefix.bytes[2] = b2;
168 b2 = peek_nbyte_next(insn_byte_t, insn, 3);
169 insn->vex_prefix.bytes[3] = b2;
170 insn->vex_prefix.nbytes = 4;
171 insn->next_byte += 4;
172 if (insn->x86_64 && X86_VEX_W(b2))
173 /* VEX.W overrides opnd_size */
174 insn->opnd_bytes = 8;
175 } else if (inat_is_vex3_prefix(attr)) {
166 b2 = peek_nbyte_next(insn_byte_t, insn, 2); 176 b2 = peek_nbyte_next(insn_byte_t, insn, 2);
167 insn->vex_prefix.bytes[2] = b2; 177 insn->vex_prefix.bytes[2] = b2;
168 insn->vex_prefix.nbytes = 3; 178 insn->vex_prefix.nbytes = 3;
@@ -221,7 +231,9 @@ void insn_get_opcode(struct insn *insn)
221 m = insn_vex_m_bits(insn); 231 m = insn_vex_m_bits(insn);
222 p = insn_vex_p_bits(insn); 232 p = insn_vex_p_bits(insn);
223 insn->attr = inat_get_avx_attribute(op, m, p); 233 insn->attr = inat_get_avx_attribute(op, m, p);
224 if (!inat_accept_vex(insn->attr) && !inat_is_group(insn->attr)) 234 if ((inat_must_evex(insn->attr) && !insn_is_evex(insn)) ||
235 (!inat_accept_vex(insn->attr) &&
236 !inat_is_group(insn->attr)))
225 insn->attr = 0; /* This instruction is bad */ 237 insn->attr = 0; /* This instruction is bad */
226 goto end; /* VEX has only 1 byte for opcode */ 238 goto end; /* VEX has only 1 byte for opcode */
227 } 239 }
diff --git a/tools/perf/util/intel-pt-decoder/insn.h b/tools/perf/util/intel-pt-decoder/insn.h
index dd12da0f4593..e23578c7b1be 100644
--- a/tools/perf/util/intel-pt-decoder/insn.h
+++ b/tools/perf/util/intel-pt-decoder/insn.h
@@ -91,6 +91,7 @@ struct insn {
91#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */ 91#define X86_VEX_B(vex) ((vex) & 0x20) /* VEX3 Byte1 */
92#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */ 92#define X86_VEX_L(vex) ((vex) & 0x04) /* VEX3 Byte2, VEX2 Byte1 */
93/* VEX bit fields */ 93/* VEX bit fields */
94#define X86_EVEX_M(vex) ((vex) & 0x03) /* EVEX Byte1 */
94#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */ 95#define X86_VEX3_M(vex) ((vex) & 0x1f) /* VEX3 Byte1 */
95#define X86_VEX2_M 1 /* VEX2.M always 1 */ 96#define X86_VEX2_M 1 /* VEX2.M always 1 */
96#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */ 97#define X86_VEX_V(vex) (((vex) & 0x78) >> 3) /* VEX3 Byte2, VEX2 Byte1 */
@@ -133,6 +134,13 @@ static inline int insn_is_avx(struct insn *insn)
133 return (insn->vex_prefix.value != 0); 134 return (insn->vex_prefix.value != 0);
134} 135}
135 136
137static inline int insn_is_evex(struct insn *insn)
138{
139 if (!insn->prefixes.got)
140 insn_get_prefixes(insn);
141 return (insn->vex_prefix.nbytes == 4);
142}
143
136/* Ensure this instruction is decoded completely */ 144/* Ensure this instruction is decoded completely */
137static inline int insn_complete(struct insn *insn) 145static inline int insn_complete(struct insn *insn)
138{ 146{
@@ -144,8 +152,10 @@ static inline insn_byte_t insn_vex_m_bits(struct insn *insn)
144{ 152{
145 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */ 153 if (insn->vex_prefix.nbytes == 2) /* 2 bytes VEX */
146 return X86_VEX2_M; 154 return X86_VEX2_M;
147 else 155 else if (insn->vex_prefix.nbytes == 3) /* 3 bytes VEX */
148 return X86_VEX3_M(insn->vex_prefix.bytes[1]); 156 return X86_VEX3_M(insn->vex_prefix.bytes[1]);
157 else /* EVEX */
158 return X86_EVEX_M(insn->vex_prefix.bytes[1]);
149} 159}
150 160
151static inline insn_byte_t insn_vex_p_bits(struct insn *insn) 161static inline insn_byte_t insn_vex_p_bits(struct insn *insn)
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
index 9409d014b46c..8ff6c6a61291 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -123,8 +123,6 @@ struct intel_pt_decoder {
123 bool have_calc_cyc_to_tsc; 123 bool have_calc_cyc_to_tsc;
124 int exec_mode; 124 int exec_mode;
125 unsigned int insn_bytes; 125 unsigned int insn_bytes;
126 uint64_t sign_bit;
127 uint64_t sign_bits;
128 uint64_t period; 126 uint64_t period;
129 enum intel_pt_period_type period_type; 127 enum intel_pt_period_type period_type;
130 uint64_t tot_insn_cnt; 128 uint64_t tot_insn_cnt;
@@ -191,9 +189,6 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
191 decoder->data = params->data; 189 decoder->data = params->data;
192 decoder->return_compression = params->return_compression; 190 decoder->return_compression = params->return_compression;
193 191
194 decoder->sign_bit = (uint64_t)1 << 47;
195 decoder->sign_bits = ~(((uint64_t)1 << 48) - 1);
196
197 decoder->period = params->period; 192 decoder->period = params->period;
198 decoder->period_type = params->period_type; 193 decoder->period_type = params->period_type;
199 194
@@ -356,27 +351,36 @@ static const char *intel_pt_err_msgs[] = {
356 351
357int intel_pt__strerror(int code, char *buf, size_t buflen) 352int intel_pt__strerror(int code, char *buf, size_t buflen)
358{ 353{
359 if (code < 1 || code > INTEL_PT_ERR_MAX) 354 if (code < 1 || code >= INTEL_PT_ERR_MAX)
360 code = INTEL_PT_ERR_UNK; 355 code = INTEL_PT_ERR_UNK;
361 strlcpy(buf, intel_pt_err_msgs[code], buflen); 356 strlcpy(buf, intel_pt_err_msgs[code], buflen);
362 return 0; 357 return 0;
363} 358}
364 359
365static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder, 360static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
366 const struct intel_pt_pkt *packet,
367 uint64_t last_ip) 361 uint64_t last_ip)
368{ 362{
369 uint64_t ip; 363 uint64_t ip;
370 364
371 switch (packet->count) { 365 switch (packet->count) {
372 case 2: 366 case 1:
373 ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) | 367 ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
374 packet->payload; 368 packet->payload;
375 break; 369 break;
376 case 4: 370 case 2:
377 ip = (last_ip & (uint64_t)0xffffffff00000000ULL) | 371 ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
378 packet->payload; 372 packet->payload;
379 break; 373 break;
374 case 3:
375 ip = packet->payload;
376 /* Sign-extend 6-byte ip */
377 if (ip & (uint64_t)0x800000000000ULL)
378 ip |= (uint64_t)0xffff000000000000ULL;
379 break;
380 case 4:
381 ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
382 packet->payload;
383 break;
380 case 6: 384 case 6:
381 ip = packet->payload; 385 ip = packet->payload;
382 break; 386 break;
@@ -384,16 +388,12 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
384 return 0; 388 return 0;
385 } 389 }
386 390
387 if (ip & decoder->sign_bit)
388 return ip | decoder->sign_bits;
389
390 return ip; 391 return ip;
391} 392}
392 393
393static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder) 394static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
394{ 395{
395 decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet, 396 decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
396 decoder->last_ip);
397} 397}
398 398
399static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder) 399static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
@@ -1657,6 +1657,12 @@ next:
1657 } 1657 }
1658} 1658}
1659 1659
1660static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
1661{
1662 return decoder->last_ip || decoder->packet.count == 0 ||
1663 decoder->packet.count == 3 || decoder->packet.count == 6;
1664}
1665
1660/* Walk PSB+ packets to get in sync. */ 1666/* Walk PSB+ packets to get in sync. */
1661static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) 1667static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1662{ 1668{
@@ -1677,8 +1683,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1677 1683
1678 case INTEL_PT_FUP: 1684 case INTEL_PT_FUP:
1679 decoder->pge = true; 1685 decoder->pge = true;
1680 if (decoder->last_ip || decoder->packet.count == 6 || 1686 if (intel_pt_have_ip(decoder)) {
1681 decoder->packet.count == 0) {
1682 uint64_t current_ip = decoder->ip; 1687 uint64_t current_ip = decoder->ip;
1683 1688
1684 intel_pt_set_ip(decoder); 1689 intel_pt_set_ip(decoder);
@@ -1767,8 +1772,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1767 case INTEL_PT_TIP_PGE: 1772 case INTEL_PT_TIP_PGE:
1768 case INTEL_PT_TIP: 1773 case INTEL_PT_TIP:
1769 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; 1774 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
1770 if (decoder->last_ip || decoder->packet.count == 6 || 1775 if (intel_pt_have_ip(decoder))
1771 decoder->packet.count == 0)
1772 intel_pt_set_ip(decoder); 1776 intel_pt_set_ip(decoder);
1773 if (decoder->ip) 1777 if (decoder->ip)
1774 return 0; 1778 return 0;
@@ -1776,9 +1780,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1776 1780
1777 case INTEL_PT_FUP: 1781 case INTEL_PT_FUP:
1778 if (decoder->overflow) { 1782 if (decoder->overflow) {
1779 if (decoder->last_ip || 1783 if (intel_pt_have_ip(decoder))
1780 decoder->packet.count == 6 ||
1781 decoder->packet.count == 0)
1782 intel_pt_set_ip(decoder); 1784 intel_pt_set_ip(decoder);
1783 if (decoder->ip) 1785 if (decoder->ip)
1784 return 0; 1786 return 0;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
index b1257c816310..4f7b32020487 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-pkt-decoder.c
@@ -292,36 +292,46 @@ static int intel_pt_get_ip(enum intel_pt_pkt_type type, unsigned int byte,
292 const unsigned char *buf, size_t len, 292 const unsigned char *buf, size_t len,
293 struct intel_pt_pkt *packet) 293 struct intel_pt_pkt *packet)
294{ 294{
295 switch (byte >> 5) { 295 int ip_len;
296
297 packet->count = byte >> 5;
298
299 switch (packet->count) {
296 case 0: 300 case 0:
297 packet->count = 0; 301 ip_len = 0;
298 break; 302 break;
299 case 1: 303 case 1:
300 if (len < 3) 304 if (len < 3)
301 return INTEL_PT_NEED_MORE_BYTES; 305 return INTEL_PT_NEED_MORE_BYTES;
302 packet->count = 2; 306 ip_len = 2;
303 packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1)); 307 packet->payload = le16_to_cpu(*(uint16_t *)(buf + 1));
304 break; 308 break;
305 case 2: 309 case 2:
306 if (len < 5) 310 if (len < 5)
307 return INTEL_PT_NEED_MORE_BYTES; 311 return INTEL_PT_NEED_MORE_BYTES;
308 packet->count = 4; 312 ip_len = 4;
309 packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1)); 313 packet->payload = le32_to_cpu(*(uint32_t *)(buf + 1));
310 break; 314 break;
311 case 3: 315 case 3:
312 case 6: 316 case 4:
313 if (len < 7) 317 if (len < 7)
314 return INTEL_PT_NEED_MORE_BYTES; 318 return INTEL_PT_NEED_MORE_BYTES;
315 packet->count = 6; 319 ip_len = 6;
316 memcpy_le64(&packet->payload, buf + 1, 6); 320 memcpy_le64(&packet->payload, buf + 1, 6);
317 break; 321 break;
322 case 6:
323 if (len < 9)
324 return INTEL_PT_NEED_MORE_BYTES;
325 ip_len = 8;
326 packet->payload = le64_to_cpu(*(uint64_t *)(buf + 1));
327 break;
318 default: 328 default:
319 return INTEL_PT_BAD_PACKET; 329 return INTEL_PT_BAD_PACKET;
320 } 330 }
321 331
322 packet->type = type; 332 packet->type = type;
323 333
324 return packet->count + 1; 334 return ip_len + 1;
325} 335}
326 336
327static int intel_pt_get_mode(const unsigned char *buf, size_t len, 337static int intel_pt_get_mode(const unsigned char *buf, size_t len,
diff --git a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
index d388de72eaca..767be7c76034 100644
--- a/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
+++ b/tools/perf/util/intel-pt-decoder/x86-opcode-map.txt
@@ -13,12 +13,17 @@
13# opcode: escape # escaped-name 13# opcode: escape # escaped-name
14# EndTable 14# EndTable
15# 15#
16# mnemonics that begin with lowercase 'v' accept a VEX or EVEX prefix
17# mnemonics that begin with lowercase 'k' accept a VEX prefix
18#
16#<group maps> 19#<group maps>
17# GrpTable: GrpXXX 20# GrpTable: GrpXXX
18# reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...] 21# reg: mnemonic [operand1[,operand2...]] [(extra1)[,(extra2)...] [| 2nd-mnemonic ...]
19# EndTable 22# EndTable
20# 23#
21# AVX Superscripts 24# AVX Superscripts
25# (ev): this opcode requires EVEX prefix.
26# (evo): this opcode is changed by EVEX prefix (EVEX opcode)
22# (v): this opcode requires VEX prefix. 27# (v): this opcode requires VEX prefix.
23# (v1): this opcode only supports 128bit VEX. 28# (v1): this opcode only supports 128bit VEX.
24# 29#
@@ -137,7 +142,7 @@ AVXcode:
137# 0x60 - 0x6f 142# 0x60 - 0x6f
13860: PUSHA/PUSHAD (i64) 14360: PUSHA/PUSHAD (i64)
13961: POPA/POPAD (i64) 14461: POPA/POPAD (i64)
14062: BOUND Gv,Ma (i64) 14562: BOUND Gv,Ma (i64) | EVEX (Prefix)
14163: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64) 14663: ARPL Ew,Gw (i64) | MOVSXD Gv,Ev (o64)
14264: SEG=FS (Prefix) 14764: SEG=FS (Prefix)
14365: SEG=GS (Prefix) 14865: SEG=GS (Prefix)
@@ -399,17 +404,17 @@ AVXcode: 1
3993f: 4043f:
400# 0x0f 0x40-0x4f 405# 0x0f 0x40-0x4f
40140: CMOVO Gv,Ev 40640: CMOVO Gv,Ev
40241: CMOVNO Gv,Ev 40741: CMOVNO Gv,Ev | kandw/q Vk,Hk,Uk | kandb/d Vk,Hk,Uk (66)
40342: CMOVB/C/NAE Gv,Ev 40842: CMOVB/C/NAE Gv,Ev | kandnw/q Vk,Hk,Uk | kandnb/d Vk,Hk,Uk (66)
40443: CMOVAE/NB/NC Gv,Ev 40943: CMOVAE/NB/NC Gv,Ev
40544: CMOVE/Z Gv,Ev 41044: CMOVE/Z Gv,Ev | knotw/q Vk,Uk | knotb/d Vk,Uk (66)
40645: CMOVNE/NZ Gv,Ev 41145: CMOVNE/NZ Gv,Ev | korw/q Vk,Hk,Uk | korb/d Vk,Hk,Uk (66)
40746: CMOVBE/NA Gv,Ev 41246: CMOVBE/NA Gv,Ev | kxnorw/q Vk,Hk,Uk | kxnorb/d Vk,Hk,Uk (66)
40847: CMOVA/NBE Gv,Ev 41347: CMOVA/NBE Gv,Ev | kxorw/q Vk,Hk,Uk | kxorb/d Vk,Hk,Uk (66)
40948: CMOVS Gv,Ev 41448: CMOVS Gv,Ev
41049: CMOVNS Gv,Ev 41549: CMOVNS Gv,Ev
4114a: CMOVP/PE Gv,Ev 4164a: CMOVP/PE Gv,Ev | kaddw/q Vk,Hk,Uk | kaddb/d Vk,Hk,Uk (66)
4124b: CMOVNP/PO Gv,Ev 4174b: CMOVNP/PO Gv,Ev | kunpckbw Vk,Hk,Uk (66) | kunpckwd/dq Vk,Hk,Uk
4134c: CMOVL/NGE Gv,Ev 4184c: CMOVL/NGE Gv,Ev
4144d: CMOVNL/GE Gv,Ev 4194d: CMOVNL/GE Gv,Ev
4154e: CMOVLE/NG Gv,Ev 4204e: CMOVLE/NG Gv,Ev
@@ -426,7 +431,7 @@ AVXcode: 1
42658: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1) 43158: vaddps Vps,Hps,Wps | vaddpd Vpd,Hpd,Wpd (66) | vaddss Vss,Hss,Wss (F3),(v1) | vaddsd Vsd,Hsd,Wsd (F2),(v1)
42759: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1) 43259: vmulps Vps,Hps,Wps | vmulpd Vpd,Hpd,Wpd (66) | vmulss Vss,Hss,Wss (F3),(v1) | vmulsd Vsd,Hsd,Wsd (F2),(v1)
4285a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1) 4335a: vcvtps2pd Vpd,Wps | vcvtpd2ps Vps,Wpd (66) | vcvtss2sd Vsd,Hx,Wss (F3),(v1) | vcvtsd2ss Vss,Hx,Wsd (F2),(v1)
4295b: vcvtdq2ps Vps,Wdq | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3) 4345b: vcvtdq2ps Vps,Wdq | vcvtqq2ps Vps,Wqq (evo) | vcvtps2dq Vdq,Wps (66) | vcvttps2dq Vdq,Wps (F3)
4305c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1) 4355c: vsubps Vps,Hps,Wps | vsubpd Vpd,Hpd,Wpd (66) | vsubss Vss,Hss,Wss (F3),(v1) | vsubsd Vsd,Hsd,Wsd (F2),(v1)
4315d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1) 4365d: vminps Vps,Hps,Wps | vminpd Vpd,Hpd,Wpd (66) | vminss Vss,Hss,Wss (F3),(v1) | vminsd Vsd,Hsd,Wsd (F2),(v1)
4325e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1) 4375e: vdivps Vps,Hps,Wps | vdivpd Vpd,Hpd,Wpd (66) | vdivss Vss,Hss,Wss (F3),(v1) | vdivsd Vsd,Hsd,Wsd (F2),(v1)
@@ -447,7 +452,7 @@ AVXcode: 1
4476c: vpunpcklqdq Vx,Hx,Wx (66),(v1) 4526c: vpunpcklqdq Vx,Hx,Wx (66),(v1)
4486d: vpunpckhqdq Vx,Hx,Wx (66),(v1) 4536d: vpunpckhqdq Vx,Hx,Wx (66),(v1)
4496e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1) 4546e: movd/q Pd,Ey | vmovd/q Vy,Ey (66),(v1)
4506f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqu Vx,Wx (F3) 4556f: movq Pq,Qq | vmovdqa Vx,Wx (66) | vmovdqa32/64 Vx,Wx (66),(evo) | vmovdqu Vx,Wx (F3) | vmovdqu32/64 Vx,Wx (F3),(evo) | vmovdqu8/16 Vx,Wx (F2),(ev)
451# 0x0f 0x70-0x7f 456# 0x0f 0x70-0x7f
45270: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1) 45770: pshufw Pq,Qq,Ib | vpshufd Vx,Wx,Ib (66),(v1) | vpshufhw Vx,Wx,Ib (F3),(v1) | vpshuflw Vx,Wx,Ib (F2),(v1)
45371: Grp12 (1A) 45871: Grp12 (1A)
@@ -458,14 +463,14 @@ AVXcode: 1
45876: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1) 46376: pcmpeqd Pq,Qq | vpcmpeqd Vx,Hx,Wx (66),(v1)
459# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX. 464# Note: Remove (v), because vzeroall and vzeroupper becomes emms without VEX.
46077: emms | vzeroupper | vzeroall 46577: emms | vzeroupper | vzeroall
46178: VMREAD Ey,Gy 46678: VMREAD Ey,Gy | vcvttps2udq/pd2udq Vx,Wpd (evo) | vcvttsd2usi Gv,Wx (F2),(ev) | vcvttss2usi Gv,Wx (F3),(ev) | vcvttps2uqq/pd2uqq Vx,Wx (66),(ev)
46279: VMWRITE Gy,Ey 46779: VMWRITE Gy,Ey | vcvtps2udq/pd2udq Vx,Wpd (evo) | vcvtsd2usi Gv,Wx (F2),(ev) | vcvtss2usi Gv,Wx (F3),(ev) | vcvtps2uqq/pd2uqq Vx,Wx (66),(ev)
4637a: 4687a: vcvtudq2pd/uqq2pd Vpd,Wx (F3),(ev) | vcvtudq2ps/uqq2ps Vpd,Wx (F2),(ev) | vcvttps2qq/pd2qq Vx,Wx (66),(ev)
4647b: 4697b: vcvtusi2sd Vpd,Hpd,Ev (F2),(ev) | vcvtusi2ss Vps,Hps,Ev (F3),(ev) | vcvtps2qq/pd2qq Vx,Wx (66),(ev)
4657c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2) 4707c: vhaddpd Vpd,Hpd,Wpd (66) | vhaddps Vps,Hps,Wps (F2)
4667d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2) 4717d: vhsubpd Vpd,Hpd,Wpd (66) | vhsubps Vps,Hps,Wps (F2)
4677e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1) 4727e: movd/q Ey,Pd | vmovd/q Ey,Vy (66),(v1) | vmovq Vq,Wq (F3),(v1)
4687f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqu Wx,Vx (F3) 4737f: movq Qq,Pq | vmovdqa Wx,Vx (66) | vmovdqa32/64 Wx,Vx (66),(evo) | vmovdqu Wx,Vx (F3) | vmovdqu32/64 Wx,Vx (F3),(evo) | vmovdqu8/16 Wx,Vx (F2),(ev)
469# 0x0f 0x80-0x8f 474# 0x0f 0x80-0x8f
470# Note: "forced64" is Intel CPU behavior (see comment about CALL insn). 475# Note: "forced64" is Intel CPU behavior (see comment about CALL insn).
47180: JO Jz (f64) 47680: JO Jz (f64)
@@ -485,16 +490,16 @@ AVXcode: 1
4858e: JLE/JNG Jz (f64) 4908e: JLE/JNG Jz (f64)
4868f: JNLE/JG Jz (f64) 4918f: JNLE/JG Jz (f64)
487# 0x0f 0x90-0x9f 492# 0x0f 0x90-0x9f
48890: SETO Eb 49390: SETO Eb | kmovw/q Vk,Wk | kmovb/d Vk,Wk (66)
48991: SETNO Eb 49491: SETNO Eb | kmovw/q Mv,Vk | kmovb/d Mv,Vk (66)
49092: SETB/C/NAE Eb 49592: SETB/C/NAE Eb | kmovw Vk,Rv | kmovb Vk,Rv (66) | kmovq/d Vk,Rv (F2)
49193: SETAE/NB/NC Eb 49693: SETAE/NB/NC Eb | kmovw Gv,Uk | kmovb Gv,Uk (66) | kmovq/d Gv,Uk (F2)
49294: SETE/Z Eb 49794: SETE/Z Eb
49395: SETNE/NZ Eb 49895: SETNE/NZ Eb
49496: SETBE/NA Eb 49996: SETBE/NA Eb
49597: SETA/NBE Eb 50097: SETA/NBE Eb
49698: SETS Eb 50198: SETS Eb | kortestw/q Vk,Uk | kortestb/d Vk,Uk (66)
49799: SETNS Eb 50299: SETNS Eb | ktestw/q Vk,Uk | ktestb/d Vk,Uk (66)
4989a: SETP/PE Eb 5039a: SETP/PE Eb
4999b: SETNP/PO Eb 5049b: SETNP/PO Eb
5009c: SETL/NGE Eb 5059c: SETL/NGE Eb
@@ -564,11 +569,11 @@ d7: pmovmskb Gd,Nq | vpmovmskb Gd,Ux (66),(v1)
564d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1) 569d8: psubusb Pq,Qq | vpsubusb Vx,Hx,Wx (66),(v1)
565d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1) 570d9: psubusw Pq,Qq | vpsubusw Vx,Hx,Wx (66),(v1)
566da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1) 571da: pminub Pq,Qq | vpminub Vx,Hx,Wx (66),(v1)
567db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) 572db: pand Pq,Qq | vpand Vx,Hx,Wx (66),(v1) | vpandd/q Vx,Hx,Wx (66),(evo)
568dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1) 573dc: paddusb Pq,Qq | vpaddusb Vx,Hx,Wx (66),(v1)
569dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1) 574dd: paddusw Pq,Qq | vpaddusw Vx,Hx,Wx (66),(v1)
570de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1) 575de: pmaxub Pq,Qq | vpmaxub Vx,Hx,Wx (66),(v1)
571df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) 576df: pandn Pq,Qq | vpandn Vx,Hx,Wx (66),(v1) | vpandnd/q Vx,Hx,Wx (66),(evo)
572# 0x0f 0xe0-0xef 577# 0x0f 0xe0-0xef
573e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1) 578e0: pavgb Pq,Qq | vpavgb Vx,Hx,Wx (66),(v1)
574e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1) 579e1: psraw Pq,Qq | vpsraw Vx,Hx,Wx (66),(v1)
@@ -576,16 +581,16 @@ e2: psrad Pq,Qq | vpsrad Vx,Hx,Wx (66),(v1)
576e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1) 581e3: pavgw Pq,Qq | vpavgw Vx,Hx,Wx (66),(v1)
577e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1) 582e4: pmulhuw Pq,Qq | vpmulhuw Vx,Hx,Wx (66),(v1)
578e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1) 583e5: pmulhw Pq,Qq | vpmulhw Vx,Hx,Wx (66),(v1)
579e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtpd2dq Vx,Wpd (F2) 584e6: vcvttpd2dq Vx,Wpd (66) | vcvtdq2pd Vx,Wdq (F3) | vcvtdq2pd/qq2pd Vx,Wdq (F3),(evo) | vcvtpd2dq Vx,Wpd (F2)
580e7: movntq Mq,Pq | vmovntdq Mx,Vx (66) 585e7: movntq Mq,Pq | vmovntdq Mx,Vx (66)
581e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1) 586e8: psubsb Pq,Qq | vpsubsb Vx,Hx,Wx (66),(v1)
582e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1) 587e9: psubsw Pq,Qq | vpsubsw Vx,Hx,Wx (66),(v1)
583ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1) 588ea: pminsw Pq,Qq | vpminsw Vx,Hx,Wx (66),(v1)
584eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) 589eb: por Pq,Qq | vpor Vx,Hx,Wx (66),(v1) | vpord/q Vx,Hx,Wx (66),(evo)
585ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1) 590ec: paddsb Pq,Qq | vpaddsb Vx,Hx,Wx (66),(v1)
586ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1) 591ed: paddsw Pq,Qq | vpaddsw Vx,Hx,Wx (66),(v1)
587ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1) 592ee: pmaxsw Pq,Qq | vpmaxsw Vx,Hx,Wx (66),(v1)
588ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) 593ef: pxor Pq,Qq | vpxor Vx,Hx,Wx (66),(v1) | vpxord/q Vx,Hx,Wx (66),(evo)
589# 0x0f 0xf0-0xff 594# 0x0f 0xf0-0xff
590f0: vlddqu Vx,Mx (F2) 595f0: vlddqu Vx,Mx (F2)
591f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1) 596f1: psllw Pq,Qq | vpsllw Vx,Hx,Wx (66),(v1)
@@ -626,81 +631,105 @@ AVXcode: 2
6260e: vtestps Vx,Wx (66),(v) 6310e: vtestps Vx,Wx (66),(v)
6270f: vtestpd Vx,Wx (66),(v) 6320f: vtestpd Vx,Wx (66),(v)
628# 0x0f 0x38 0x10-0x1f 633# 0x0f 0x38 0x10-0x1f
62910: pblendvb Vdq,Wdq (66) 63410: pblendvb Vdq,Wdq (66) | vpsrlvw Vx,Hx,Wx (66),(evo) | vpmovuswb Wx,Vx (F3),(ev)
63011: 63511: vpmovusdb Wx,Vd (F3),(ev) | vpsravw Vx,Hx,Wx (66),(ev)
63112: 63612: vpmovusqb Wx,Vq (F3),(ev) | vpsllvw Vx,Hx,Wx (66),(ev)
63213: vcvtph2ps Vx,Wx,Ib (66),(v) 63713: vcvtph2ps Vx,Wx (66),(v) | vpmovusdw Wx,Vd (F3),(ev)
63314: blendvps Vdq,Wdq (66) 63814: blendvps Vdq,Wdq (66) | vpmovusqw Wx,Vq (F3),(ev) | vprorvd/q Vx,Hx,Wx (66),(evo)
63415: blendvpd Vdq,Wdq (66) 63915: blendvpd Vdq,Wdq (66) | vpmovusqd Wx,Vq (F3),(ev) | vprolvd/q Vx,Hx,Wx (66),(evo)
63516: vpermps Vqq,Hqq,Wqq (66),(v) 64016: vpermps Vqq,Hqq,Wqq (66),(v) | vpermps/d Vqq,Hqq,Wqq (66),(evo)
63617: vptest Vx,Wx (66) 64117: vptest Vx,Wx (66)
63718: vbroadcastss Vx,Wd (66),(v) 64218: vbroadcastss Vx,Wd (66),(v)
63819: vbroadcastsd Vqq,Wq (66),(v) 64319: vbroadcastsd Vqq,Wq (66),(v) | vbroadcastf32x2 Vqq,Wq (66),(evo)
6391a: vbroadcastf128 Vqq,Mdq (66),(v) 6441a: vbroadcastf128 Vqq,Mdq (66),(v) | vbroadcastf32x4/64x2 Vqq,Wq (66),(evo)
6401b: 6451b: vbroadcastf32x8/64x4 Vqq,Mdq (66),(ev)
6411c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1) 6461c: pabsb Pq,Qq | vpabsb Vx,Wx (66),(v1)
6421d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1) 6471d: pabsw Pq,Qq | vpabsw Vx,Wx (66),(v1)
6431e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1) 6481e: pabsd Pq,Qq | vpabsd Vx,Wx (66),(v1)
6441f: 6491f: vpabsq Vx,Wx (66),(ev)
645# 0x0f 0x38 0x20-0x2f 650# 0x0f 0x38 0x20-0x2f
64620: vpmovsxbw Vx,Ux/Mq (66),(v1) 65120: vpmovsxbw Vx,Ux/Mq (66),(v1) | vpmovswb Wx,Vx (F3),(ev)
64721: vpmovsxbd Vx,Ux/Md (66),(v1) 65221: vpmovsxbd Vx,Ux/Md (66),(v1) | vpmovsdb Wx,Vd (F3),(ev)
64822: vpmovsxbq Vx,Ux/Mw (66),(v1) 65322: vpmovsxbq Vx,Ux/Mw (66),(v1) | vpmovsqb Wx,Vq (F3),(ev)
64923: vpmovsxwd Vx,Ux/Mq (66),(v1) 65423: vpmovsxwd Vx,Ux/Mq (66),(v1) | vpmovsdw Wx,Vd (F3),(ev)
65024: vpmovsxwq Vx,Ux/Md (66),(v1) 65524: vpmovsxwq Vx,Ux/Md (66),(v1) | vpmovsqw Wx,Vq (F3),(ev)
65125: vpmovsxdq Vx,Ux/Mq (66),(v1) 65625: vpmovsxdq Vx,Ux/Mq (66),(v1) | vpmovsqd Wx,Vq (F3),(ev)
65226: 65726: vptestmb/w Vk,Hx,Wx (66),(ev) | vptestnmb/w Vk,Hx,Wx (F3),(ev)
65327: 65827: vptestmd/q Vk,Hx,Wx (66),(ev) | vptestnmd/q Vk,Hx,Wx (F3),(ev)
65428: vpmuldq Vx,Hx,Wx (66),(v1) 65928: vpmuldq Vx,Hx,Wx (66),(v1) | vpmovm2b/w Vx,Uk (F3),(ev)
65529: vpcmpeqq Vx,Hx,Wx (66),(v1) 66029: vpcmpeqq Vx,Hx,Wx (66),(v1) | vpmovb2m/w2m Vk,Ux (F3),(ev)
6562a: vmovntdqa Vx,Mx (66),(v1) 6612a: vmovntdqa Vx,Mx (66),(v1) | vpbroadcastmb2q Vx,Uk (F3),(ev)
6572b: vpackusdw Vx,Hx,Wx (66),(v1) 6622b: vpackusdw Vx,Hx,Wx (66),(v1)
6582c: vmaskmovps Vx,Hx,Mx (66),(v) 6632c: vmaskmovps Vx,Hx,Mx (66),(v) | vscalefps/d Vx,Hx,Wx (66),(evo)
6592d: vmaskmovpd Vx,Hx,Mx (66),(v) 6642d: vmaskmovpd Vx,Hx,Mx (66),(v) | vscalefss/d Vx,Hx,Wx (66),(evo)
6602e: vmaskmovps Mx,Hx,Vx (66),(v) 6652e: vmaskmovps Mx,Hx,Vx (66),(v)
6612f: vmaskmovpd Mx,Hx,Vx (66),(v) 6662f: vmaskmovpd Mx,Hx,Vx (66),(v)
662# 0x0f 0x38 0x30-0x3f 667# 0x0f 0x38 0x30-0x3f
66330: vpmovzxbw Vx,Ux/Mq (66),(v1) 66830: vpmovzxbw Vx,Ux/Mq (66),(v1) | vpmovwb Wx,Vx (F3),(ev)
66431: vpmovzxbd Vx,Ux/Md (66),(v1) 66931: vpmovzxbd Vx,Ux/Md (66),(v1) | vpmovdb Wx,Vd (F3),(ev)
66532: vpmovzxbq Vx,Ux/Mw (66),(v1) 67032: vpmovzxbq Vx,Ux/Mw (66),(v1) | vpmovqb Wx,Vq (F3),(ev)
66633: vpmovzxwd Vx,Ux/Mq (66),(v1) 67133: vpmovzxwd Vx,Ux/Mq (66),(v1) | vpmovdw Wx,Vd (F3),(ev)
66734: vpmovzxwq Vx,Ux/Md (66),(v1) 67234: vpmovzxwq Vx,Ux/Md (66),(v1) | vpmovqw Wx,Vq (F3),(ev)
66835: vpmovzxdq Vx,Ux/Mq (66),(v1) 67335: vpmovzxdq Vx,Ux/Mq (66),(v1) | vpmovqd Wx,Vq (F3),(ev)
66936: vpermd Vqq,Hqq,Wqq (66),(v) 67436: vpermd Vqq,Hqq,Wqq (66),(v) | vpermd/q Vqq,Hqq,Wqq (66),(evo)
67037: vpcmpgtq Vx,Hx,Wx (66),(v1) 67537: vpcmpgtq Vx,Hx,Wx (66),(v1)
67138: vpminsb Vx,Hx,Wx (66),(v1) 67638: vpminsb Vx,Hx,Wx (66),(v1) | vpmovm2d/q Vx,Uk (F3),(ev)
67239: vpminsd Vx,Hx,Wx (66),(v1) 67739: vpminsd Vx,Hx,Wx (66),(v1) | vpminsd/q Vx,Hx,Wx (66),(evo) | vpmovd2m/q2m Vk,Ux (F3),(ev)
6733a: vpminuw Vx,Hx,Wx (66),(v1) 6783a: vpminuw Vx,Hx,Wx (66),(v1) | vpbroadcastmw2d Vx,Uk (F3),(ev)
6743b: vpminud Vx,Hx,Wx (66),(v1) 6793b: vpminud Vx,Hx,Wx (66),(v1) | vpminud/q Vx,Hx,Wx (66),(evo)
6753c: vpmaxsb Vx,Hx,Wx (66),(v1) 6803c: vpmaxsb Vx,Hx,Wx (66),(v1)
6763d: vpmaxsd Vx,Hx,Wx (66),(v1) 6813d: vpmaxsd Vx,Hx,Wx (66),(v1) | vpmaxsd/q Vx,Hx,Wx (66),(evo)
6773e: vpmaxuw Vx,Hx,Wx (66),(v1) 6823e: vpmaxuw Vx,Hx,Wx (66),(v1)
6783f: vpmaxud Vx,Hx,Wx (66),(v1) 6833f: vpmaxud Vx,Hx,Wx (66),(v1) | vpmaxud/q Vx,Hx,Wx (66),(evo)
679# 0x0f 0x38 0x40-0x8f 684# 0x0f 0x38 0x40-0x8f
68040: vpmulld Vx,Hx,Wx (66),(v1) 68540: vpmulld Vx,Hx,Wx (66),(v1) | vpmulld/q Vx,Hx,Wx (66),(evo)
68141: vphminposuw Vdq,Wdq (66),(v1) 68641: vphminposuw Vdq,Wdq (66),(v1)
68242: 68742: vgetexpps/d Vx,Wx (66),(ev)
68343: 68843: vgetexpss/d Vx,Hx,Wx (66),(ev)
68444: 68944: vplzcntd/q Vx,Wx (66),(ev)
68545: vpsrlvd/q Vx,Hx,Wx (66),(v) 69045: vpsrlvd/q Vx,Hx,Wx (66),(v)
68646: vpsravd Vx,Hx,Wx (66),(v) 69146: vpsravd Vx,Hx,Wx (66),(v) | vpsravd/q Vx,Hx,Wx (66),(evo)
68747: vpsllvd/q Vx,Hx,Wx (66),(v) 69247: vpsllvd/q Vx,Hx,Wx (66),(v)
688# Skip 0x48-0x57 693# Skip 0x48-0x4b
6944c: vrcp14ps/d Vpd,Wpd (66),(ev)
6954d: vrcp14ss/d Vsd,Hpd,Wsd (66),(ev)
6964e: vrsqrt14ps/d Vpd,Wpd (66),(ev)
6974f: vrsqrt14ss/d Vsd,Hsd,Wsd (66),(ev)
698# Skip 0x50-0x57
68958: vpbroadcastd Vx,Wx (66),(v) 69958: vpbroadcastd Vx,Wx (66),(v)
69059: vpbroadcastq Vx,Wx (66),(v) 70059: vpbroadcastq Vx,Wx (66),(v) | vbroadcasti32x2 Vx,Wx (66),(evo)
6915a: vbroadcasti128 Vqq,Mdq (66),(v) 7015a: vbroadcasti128 Vqq,Mdq (66),(v) | vbroadcasti32x4/64x2 Vx,Wx (66),(evo)
692# Skip 0x5b-0x77 7025b: vbroadcasti32x8/64x4 Vqq,Mdq (66),(ev)
703# Skip 0x5c-0x63
70464: vpblendmd/q Vx,Hx,Wx (66),(ev)
70565: vblendmps/d Vx,Hx,Wx (66),(ev)
70666: vpblendmb/w Vx,Hx,Wx (66),(ev)
707# Skip 0x67-0x74
70875: vpermi2b/w Vx,Hx,Wx (66),(ev)
70976: vpermi2d/q Vx,Hx,Wx (66),(ev)
71077: vpermi2ps/d Vx,Hx,Wx (66),(ev)
69378: vpbroadcastb Vx,Wx (66),(v) 71178: vpbroadcastb Vx,Wx (66),(v)
69479: vpbroadcastw Vx,Wx (66),(v) 71279: vpbroadcastw Vx,Wx (66),(v)
695# Skip 0x7a-0x7f 7137a: vpbroadcastb Vx,Rv (66),(ev)
7147b: vpbroadcastw Vx,Rv (66),(ev)
7157c: vpbroadcastd/q Vx,Rv (66),(ev)
7167d: vpermt2b/w Vx,Hx,Wx (66),(ev)
7177e: vpermt2d/q Vx,Hx,Wx (66),(ev)
7187f: vpermt2ps/d Vx,Hx,Wx (66),(ev)
69680: INVEPT Gy,Mdq (66) 71980: INVEPT Gy,Mdq (66)
69781: INVPID Gy,Mdq (66) 72081: INVPID Gy,Mdq (66)
69882: INVPCID Gy,Mdq (66) 72182: INVPCID Gy,Mdq (66)
72283: vpmultishiftqb Vx,Hx,Wx (66),(ev)
72388: vexpandps/d Vpd,Wpd (66),(ev)
72489: vpexpandd/q Vx,Wx (66),(ev)
7258a: vcompressps/d Wx,Vx (66),(ev)
7268b: vpcompressd/q Wx,Vx (66),(ev)
6998c: vpmaskmovd/q Vx,Hx,Mx (66),(v) 7278c: vpmaskmovd/q Vx,Hx,Mx (66),(v)
7288d: vpermb/w Vx,Hx,Wx (66),(ev)
7008e: vpmaskmovd/q Mx,Vx,Hx (66),(v) 7298e: vpmaskmovd/q Mx,Vx,Hx (66),(v)
701# 0x0f 0x38 0x90-0xbf (FMA) 730# 0x0f 0x38 0x90-0xbf (FMA)
70290: vgatherdd/q Vx,Hx,Wx (66),(v) 73190: vgatherdd/q Vx,Hx,Wx (66),(v) | vpgatherdd/q Vx,Wx (66),(evo)
70391: vgatherqd/q Vx,Hx,Wx (66),(v) 73291: vgatherqd/q Vx,Hx,Wx (66),(v) | vpgatherqd/q Vx,Wx (66),(evo)
70492: vgatherdps/d Vx,Hx,Wx (66),(v) 73392: vgatherdps/d Vx,Hx,Wx (66),(v)
70593: vgatherqps/d Vx,Hx,Wx (66),(v) 73493: vgatherqps/d Vx,Hx,Wx (66),(v)
70694: 73594:
@@ -715,6 +744,10 @@ AVXcode: 2
7159d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1) 7449d: vfnmadd132ss/d Vx,Hx,Wx (66),(v),(v1)
7169e: vfnmsub132ps/d Vx,Hx,Wx (66),(v) 7459e: vfnmsub132ps/d Vx,Hx,Wx (66),(v)
7179f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1) 7469f: vfnmsub132ss/d Vx,Hx,Wx (66),(v),(v1)
747a0: vpscatterdd/q Wx,Vx (66),(ev)
748a1: vpscatterqd/q Wx,Vx (66),(ev)
749a2: vscatterdps/d Wx,Vx (66),(ev)
750a3: vscatterqps/d Wx,Vx (66),(ev)
718a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v) 751a6: vfmaddsub213ps/d Vx,Hx,Wx (66),(v)
719a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v) 752a7: vfmsubadd213ps/d Vx,Hx,Wx (66),(v)
720a8: vfmadd213ps/d Vx,Hx,Wx (66),(v) 753a8: vfmadd213ps/d Vx,Hx,Wx (66),(v)
@@ -725,6 +758,8 @@ ac: vfnmadd213ps/d Vx,Hx,Wx (66),(v)
725ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1) 758ad: vfnmadd213ss/d Vx,Hx,Wx (66),(v),(v1)
726ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v) 759ae: vfnmsub213ps/d Vx,Hx,Wx (66),(v)
727af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1) 760af: vfnmsub213ss/d Vx,Hx,Wx (66),(v),(v1)
761b4: vpmadd52luq Vx,Hx,Wx (66),(ev)
762b5: vpmadd52huq Vx,Hx,Wx (66),(ev)
728b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v) 763b6: vfmaddsub231ps/d Vx,Hx,Wx (66),(v)
729b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v) 764b7: vfmsubadd231ps/d Vx,Hx,Wx (66),(v)
730b8: vfmadd231ps/d Vx,Hx,Wx (66),(v) 765b8: vfmadd231ps/d Vx,Hx,Wx (66),(v)
@@ -736,12 +771,15 @@ bd: vfnmadd231ss/d Vx,Hx,Wx (66),(v),(v1)
736be: vfnmsub231ps/d Vx,Hx,Wx (66),(v) 771be: vfnmsub231ps/d Vx,Hx,Wx (66),(v)
737bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1) 772bf: vfnmsub231ss/d Vx,Hx,Wx (66),(v),(v1)
738# 0x0f 0x38 0xc0-0xff 773# 0x0f 0x38 0xc0-0xff
739c8: sha1nexte Vdq,Wdq 774c4: vpconflictd/q Vx,Wx (66),(ev)
775c6: Grp18 (1A)
776c7: Grp19 (1A)
777c8: sha1nexte Vdq,Wdq | vexp2ps/d Vx,Wx (66),(ev)
740c9: sha1msg1 Vdq,Wdq 778c9: sha1msg1 Vdq,Wdq
741ca: sha1msg2 Vdq,Wdq 779ca: sha1msg2 Vdq,Wdq | vrcp28ps/d Vx,Wx (66),(ev)
742cb: sha256rnds2 Vdq,Wdq 780cb: sha256rnds2 Vdq,Wdq | vrcp28ss/d Vx,Hx,Wx (66),(ev)
743cc: sha256msg1 Vdq,Wdq 781cc: sha256msg1 Vdq,Wdq | vrsqrt28ps/d Vx,Wx (66),(ev)
744cd: sha256msg2 Vdq,Wdq 782cd: sha256msg2 Vdq,Wdq | vrsqrt28ss/d Vx,Hx,Wx (66),(ev)
745db: VAESIMC Vdq,Wdq (66),(v1) 783db: VAESIMC Vdq,Wdq (66),(v1)
746dc: VAESENC Vdq,Hdq,Wdq (66),(v1) 784dc: VAESENC Vdq,Hdq,Wdq (66),(v1)
747dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1) 785dd: VAESENCLAST Vdq,Hdq,Wdq (66),(v1)
@@ -763,15 +801,15 @@ AVXcode: 3
76300: vpermq Vqq,Wqq,Ib (66),(v) 80100: vpermq Vqq,Wqq,Ib (66),(v)
76401: vpermpd Vqq,Wqq,Ib (66),(v) 80201: vpermpd Vqq,Wqq,Ib (66),(v)
76502: vpblendd Vx,Hx,Wx,Ib (66),(v) 80302: vpblendd Vx,Hx,Wx,Ib (66),(v)
76603: 80403: valignd/q Vx,Hx,Wx,Ib (66),(ev)
76704: vpermilps Vx,Wx,Ib (66),(v) 80504: vpermilps Vx,Wx,Ib (66),(v)
76805: vpermilpd Vx,Wx,Ib (66),(v) 80605: vpermilpd Vx,Wx,Ib (66),(v)
76906: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v) 80706: vperm2f128 Vqq,Hqq,Wqq,Ib (66),(v)
77007: 80807:
77108: vroundps Vx,Wx,Ib (66) 80908: vroundps Vx,Wx,Ib (66) | vrndscaleps Vx,Wx,Ib (66),(evo)
77209: vroundpd Vx,Wx,Ib (66) 81009: vroundpd Vx,Wx,Ib (66) | vrndscalepd Vx,Wx,Ib (66),(evo)
7730a: vroundss Vss,Wss,Ib (66),(v1) 8110a: vroundss Vss,Wss,Ib (66),(v1) | vrndscaless Vx,Hx,Wx,Ib (66),(evo)
7740b: vroundsd Vsd,Wsd,Ib (66),(v1) 8120b: vroundsd Vsd,Wsd,Ib (66),(v1) | vrndscalesd Vx,Hx,Wx,Ib (66),(evo)
7750c: vblendps Vx,Hx,Wx,Ib (66) 8130c: vblendps Vx,Hx,Wx,Ib (66)
7760d: vblendpd Vx,Hx,Wx,Ib (66) 8140d: vblendpd Vx,Hx,Wx,Ib (66)
7770e: vpblendw Vx,Hx,Wx,Ib (66),(v1) 8150e: vpblendw Vx,Hx,Wx,Ib (66),(v1)
@@ -780,26 +818,51 @@ AVXcode: 3
78015: vpextrw Rd/Mw,Vdq,Ib (66),(v1) 81815: vpextrw Rd/Mw,Vdq,Ib (66),(v1)
78116: vpextrd/q Ey,Vdq,Ib (66),(v1) 81916: vpextrd/q Ey,Vdq,Ib (66),(v1)
78217: vextractps Ed,Vdq,Ib (66),(v1) 82017: vextractps Ed,Vdq,Ib (66),(v1)
78318: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) 82118: vinsertf128 Vqq,Hqq,Wqq,Ib (66),(v) | vinsertf32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo)
78419: vextractf128 Wdq,Vqq,Ib (66),(v) 82219: vextractf128 Wdq,Vqq,Ib (66),(v) | vextractf32x4/64x2 Wdq,Vqq,Ib (66),(evo)
8231a: vinsertf32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev)
8241b: vextractf32x8/64x4 Wdq,Vqq,Ib (66),(ev)
7851d: vcvtps2ph Wx,Vx,Ib (66),(v) 8251d: vcvtps2ph Wx,Vx,Ib (66),(v)
8261e: vpcmpud/q Vk,Hd,Wd,Ib (66),(ev)
8271f: vpcmpd/q Vk,Hd,Wd,Ib (66),(ev)
78620: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1) 82820: vpinsrb Vdq,Hdq,Ry/Mb,Ib (66),(v1)
78721: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1) 82921: vinsertps Vdq,Hdq,Udq/Md,Ib (66),(v1)
78822: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1) 83022: vpinsrd/q Vdq,Hdq,Ey,Ib (66),(v1)
78938: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) 83123: vshuff32x4/64x2 Vx,Hx,Wx,Ib (66),(ev)
79039: vextracti128 Wdq,Vqq,Ib (66),(v) 83225: vpternlogd/q Vx,Hx,Wx,Ib (66),(ev)
83326: vgetmantps/d Vx,Wx,Ib (66),(ev)
83427: vgetmantss/d Vx,Hx,Wx,Ib (66),(ev)
83530: kshiftrb/w Vk,Uk,Ib (66),(v)
83631: kshiftrd/q Vk,Uk,Ib (66),(v)
83732: kshiftlb/w Vk,Uk,Ib (66),(v)
83833: kshiftld/q Vk,Uk,Ib (66),(v)
83938: vinserti128 Vqq,Hqq,Wqq,Ib (66),(v) | vinserti32x4/64x2 Vqq,Hqq,Wqq,Ib (66),(evo)
84039: vextracti128 Wdq,Vqq,Ib (66),(v) | vextracti32x4/64x2 Wdq,Vqq,Ib (66),(evo)
8413a: vinserti32x8/64x4 Vqq,Hqq,Wqq,Ib (66),(ev)
8423b: vextracti32x8/64x4 Wdq,Vqq,Ib (66),(ev)
8433e: vpcmpub/w Vk,Hk,Wx,Ib (66),(ev)
8443f: vpcmpb/w Vk,Hk,Wx,Ib (66),(ev)
79140: vdpps Vx,Hx,Wx,Ib (66) 84540: vdpps Vx,Hx,Wx,Ib (66)
79241: vdppd Vdq,Hdq,Wdq,Ib (66),(v1) 84641: vdppd Vdq,Hdq,Wdq,Ib (66),(v1)
79342: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) 84742: vmpsadbw Vx,Hx,Wx,Ib (66),(v1) | vdbpsadbw Vx,Hx,Wx,Ib (66),(evo)
84843: vshufi32x4/64x2 Vx,Hx,Wx,Ib (66),(ev)
79444: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1) 84944: vpclmulqdq Vdq,Hdq,Wdq,Ib (66),(v1)
79546: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v) 85046: vperm2i128 Vqq,Hqq,Wqq,Ib (66),(v)
7964a: vblendvps Vx,Hx,Wx,Lx (66),(v) 8514a: vblendvps Vx,Hx,Wx,Lx (66),(v)
7974b: vblendvpd Vx,Hx,Wx,Lx (66),(v) 8524b: vblendvpd Vx,Hx,Wx,Lx (66),(v)
7984c: vpblendvb Vx,Hx,Wx,Lx (66),(v1) 8534c: vpblendvb Vx,Hx,Wx,Lx (66),(v1)
85450: vrangeps/d Vx,Hx,Wx,Ib (66),(ev)
85551: vrangess/d Vx,Hx,Wx,Ib (66),(ev)
85654: vfixupimmps/d Vx,Hx,Wx,Ib (66),(ev)
85755: vfixupimmss/d Vx,Hx,Wx,Ib (66),(ev)
85856: vreduceps/d Vx,Wx,Ib (66),(ev)
85957: vreducess/d Vx,Hx,Wx,Ib (66),(ev)
79960: vpcmpestrm Vdq,Wdq,Ib (66),(v1) 86060: vpcmpestrm Vdq,Wdq,Ib (66),(v1)
80061: vpcmpestri Vdq,Wdq,Ib (66),(v1) 86161: vpcmpestri Vdq,Wdq,Ib (66),(v1)
80162: vpcmpistrm Vdq,Wdq,Ib (66),(v1) 86262: vpcmpistrm Vdq,Wdq,Ib (66),(v1)
80263: vpcmpistri Vdq,Wdq,Ib (66),(v1) 86363: vpcmpistri Vdq,Wdq,Ib (66),(v1)
86466: vfpclassps/d Vk,Wx,Ib (66),(ev)
86567: vfpclassss/d Vk,Wx,Ib (66),(ev)
803cc: sha1rnds4 Vdq,Wdq,Ib 866cc: sha1rnds4 Vdq,Wdq,Ib
804df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1) 867df: VAESKEYGEN Vdq,Wdq,Ib (66),(v1)
805f0: RORX Gy,Ey,Ib (F2),(v) 868f0: RORX Gy,Ey,Ib (F2),(v)
@@ -927,8 +990,10 @@ GrpTable: Grp12
927EndTable 990EndTable
928 991
929GrpTable: Grp13 992GrpTable: Grp13
9930: vprord/q Hx,Wx,Ib (66),(ev)
9941: vprold/q Hx,Wx,Ib (66),(ev)
9302: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1) 9952: psrld Nq,Ib (11B) | vpsrld Hx,Ux,Ib (66),(11B),(v1)
9314: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) 9964: psrad Nq,Ib (11B) | vpsrad Hx,Ux,Ib (66),(11B),(v1) | vpsrad/q Hx,Ux,Ib (66),(evo)
9326: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1) 9976: pslld Nq,Ib (11B) | vpslld Hx,Ux,Ib (66),(11B),(v1)
933EndTable 998EndTable
934 999
@@ -947,7 +1012,7 @@ GrpTable: Grp15
9474: XSAVE 10124: XSAVE
9485: XRSTOR | lfence (11B) 10135: XRSTOR | lfence (11B)
9496: XSAVEOPT | clwb (66) | mfence (11B) 10146: XSAVEOPT | clwb (66) | mfence (11B)
9507: clflush | clflushopt (66) | sfence (11B) | pcommit (66),(11B) 10157: clflush | clflushopt (66) | sfence (11B)
951EndTable 1016EndTable
952 1017
953GrpTable: Grp16 1018GrpTable: Grp16
@@ -963,6 +1028,20 @@ GrpTable: Grp17
9633: BLSI By,Ey (v) 10283: BLSI By,Ey (v)
964EndTable 1029EndTable
965 1030
1031GrpTable: Grp18
10321: vgatherpf0dps/d Wx (66),(ev)
10332: vgatherpf1dps/d Wx (66),(ev)
10345: vscatterpf0dps/d Wx (66),(ev)
10356: vscatterpf1dps/d Wx (66),(ev)
1036EndTable
1037
1038GrpTable: Grp19
10391: vgatherpf0qps/d Wx (66),(ev)
10402: vgatherpf1qps/d Wx (66),(ev)
10415: vscatterpf0qps/d Wx (66),(ev)
10426: vscatterpf1qps/d Wx (66),(ev)
1043EndTable
1044
966# AMD's Prefetch Group 1045# AMD's Prefetch Group
967GrpTable: GrpP 1046GrpTable: GrpP
9680: PREFETCH 10470: PREFETCH
diff --git a/tools/perf/util/intel-pt.c b/tools/perf/util/intel-pt.c
index 617578440989..551ff6f640be 100644
--- a/tools/perf/util/intel-pt.c
+++ b/tools/perf/util/intel-pt.c
@@ -39,6 +39,7 @@
39#include "auxtrace.h" 39#include "auxtrace.h"
40#include "tsc.h" 40#include "tsc.h"
41#include "intel-pt.h" 41#include "intel-pt.h"
42#include "config.h"
42 43
43#include "intel-pt-decoder/intel-pt-log.h" 44#include "intel-pt-decoder/intel-pt-log.h"
44#include "intel-pt-decoder/intel-pt-decoder.h" 45#include "intel-pt-decoder/intel-pt-decoder.h"
@@ -100,6 +101,8 @@ struct intel_pt {
100 u64 cyc_bit; 101 u64 cyc_bit;
101 u64 noretcomp_bit; 102 u64 noretcomp_bit;
102 unsigned max_non_turbo_ratio; 103 unsigned max_non_turbo_ratio;
104
105 unsigned long num_events;
103}; 106};
104 107
105enum switch_state { 108enum switch_state {
@@ -554,7 +557,7 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt)
554{ 557{
555 struct perf_evsel *evsel; 558 struct perf_evsel *evsel;
556 559
557 evlist__for_each(pt->session->evlist, evsel) { 560 evlist__for_each_entry(pt->session->evlist, evsel) {
558 if (intel_pt_get_config(pt, &evsel->attr, NULL) && 561 if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
559 !evsel->attr.exclude_kernel) 562 !evsel->attr.exclude_kernel)
560 return false; 563 return false;
@@ -570,7 +573,7 @@ static bool intel_pt_return_compression(struct intel_pt *pt)
570 if (!pt->noretcomp_bit) 573 if (!pt->noretcomp_bit)
571 return true; 574 return true;
572 575
573 evlist__for_each(pt->session->evlist, evsel) { 576 evlist__for_each_entry(pt->session->evlist, evsel) {
574 if (intel_pt_get_config(pt, &evsel->attr, &config) && 577 if (intel_pt_get_config(pt, &evsel->attr, &config) &&
575 (config & pt->noretcomp_bit)) 578 (config & pt->noretcomp_bit))
576 return false; 579 return false;
@@ -590,7 +593,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
590 for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++) 593 for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++)
591 config >>= 1; 594 config >>= 1;
592 595
593 evlist__for_each(pt->session->evlist, evsel) { 596 evlist__for_each_entry(pt->session->evlist, evsel) {
594 if (intel_pt_get_config(pt, &evsel->attr, &config)) 597 if (intel_pt_get_config(pt, &evsel->attr, &config))
595 return (config & pt->mtc_freq_bits) >> shift; 598 return (config & pt->mtc_freq_bits) >> shift;
596 } 599 }
@@ -606,7 +609,7 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt)
606 if (!pt->tsc_bit || !pt->cap_user_time_zero) 609 if (!pt->tsc_bit || !pt->cap_user_time_zero)
607 return true; 610 return true;
608 611
609 evlist__for_each(pt->session->evlist, evsel) { 612 evlist__for_each_entry(pt->session->evlist, evsel) {
610 if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME)) 613 if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME))
611 return true; 614 return true;
612 if (intel_pt_get_config(pt, &evsel->attr, &config)) { 615 if (intel_pt_get_config(pt, &evsel->attr, &config)) {
@@ -623,7 +626,7 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt)
623{ 626{
624 struct perf_evsel *evsel; 627 struct perf_evsel *evsel;
625 628
626 evlist__for_each(pt->session->evlist, evsel) { 629 evlist__for_each_entry(pt->session->evlist, evsel) {
627 if (intel_pt_get_config(pt, &evsel->attr, NULL) && 630 if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
628 !evsel->attr.exclude_kernel) 631 !evsel->attr.exclude_kernel)
629 return true; 632 return true;
@@ -640,7 +643,7 @@ static bool intel_pt_have_tsc(struct intel_pt *pt)
640 if (!pt->tsc_bit) 643 if (!pt->tsc_bit)
641 return false; 644 return false;
642 645
643 evlist__for_each(pt->session->evlist, evsel) { 646 evlist__for_each_entry(pt->session->evlist, evsel) {
644 if (intel_pt_get_config(pt, &evsel->attr, &config)) { 647 if (intel_pt_get_config(pt, &evsel->attr, &config)) {
645 if (config & pt->tsc_bit) 648 if (config & pt->tsc_bit)
646 have_tsc = true; 649 have_tsc = true;
@@ -972,6 +975,10 @@ static int intel_pt_synth_branch_sample(struct intel_pt_queue *ptq)
972 if (pt->branches_filter && !(pt->branches_filter & ptq->flags)) 975 if (pt->branches_filter && !(pt->branches_filter & ptq->flags))
973 return 0; 976 return 0;
974 977
978 if (pt->synth_opts.initial_skip &&
979 pt->num_events++ < pt->synth_opts.initial_skip)
980 return 0;
981
975 event->sample.header.type = PERF_RECORD_SAMPLE; 982 event->sample.header.type = PERF_RECORD_SAMPLE;
976 event->sample.header.misc = PERF_RECORD_MISC_USER; 983 event->sample.header.misc = PERF_RECORD_MISC_USER;
977 event->sample.header.size = sizeof(struct perf_event_header); 984 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1029,6 +1036,10 @@ static int intel_pt_synth_instruction_sample(struct intel_pt_queue *ptq)
1029 union perf_event *event = ptq->event_buf; 1036 union perf_event *event = ptq->event_buf;
1030 struct perf_sample sample = { .ip = 0, }; 1037 struct perf_sample sample = { .ip = 0, };
1031 1038
1039 if (pt->synth_opts.initial_skip &&
1040 pt->num_events++ < pt->synth_opts.initial_skip)
1041 return 0;
1042
1032 event->sample.header.type = PERF_RECORD_SAMPLE; 1043 event->sample.header.type = PERF_RECORD_SAMPLE;
1033 event->sample.header.misc = PERF_RECORD_MISC_USER; 1044 event->sample.header.misc = PERF_RECORD_MISC_USER;
1034 event->sample.header.size = sizeof(struct perf_event_header); 1045 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1087,6 +1098,10 @@ static int intel_pt_synth_transaction_sample(struct intel_pt_queue *ptq)
1087 union perf_event *event = ptq->event_buf; 1098 union perf_event *event = ptq->event_buf;
1088 struct perf_sample sample = { .ip = 0, }; 1099 struct perf_sample sample = { .ip = 0, };
1089 1100
1101 if (pt->synth_opts.initial_skip &&
1102 pt->num_events++ < pt->synth_opts.initial_skip)
1103 return 0;
1104
1090 event->sample.header.type = PERF_RECORD_SAMPLE; 1105 event->sample.header.type = PERF_RECORD_SAMPLE;
1091 event->sample.header.misc = PERF_RECORD_MISC_USER; 1106 event->sample.header.misc = PERF_RECORD_MISC_USER;
1092 event->sample.header.size = sizeof(struct perf_event_header); 1107 event->sample.header.size = sizeof(struct perf_event_header);
@@ -1199,14 +1214,18 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1199 ptq->have_sample = false; 1214 ptq->have_sample = false;
1200 1215
1201 if (pt->sample_instructions && 1216 if (pt->sample_instructions &&
1202 (state->type & INTEL_PT_INSTRUCTION)) { 1217 (state->type & INTEL_PT_INSTRUCTION) &&
1218 (!pt->synth_opts.initial_skip ||
1219 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1203 err = intel_pt_synth_instruction_sample(ptq); 1220 err = intel_pt_synth_instruction_sample(ptq);
1204 if (err) 1221 if (err)
1205 return err; 1222 return err;
1206 } 1223 }
1207 1224
1208 if (pt->sample_transactions && 1225 if (pt->sample_transactions &&
1209 (state->type & INTEL_PT_TRANSACTION)) { 1226 (state->type & INTEL_PT_TRANSACTION) &&
1227 (!pt->synth_opts.initial_skip ||
1228 pt->num_events++ >= pt->synth_opts.initial_skip)) {
1210 err = intel_pt_synth_transaction_sample(ptq); 1229 err = intel_pt_synth_transaction_sample(ptq);
1211 if (err) 1230 if (err)
1212 return err; 1231 return err;
@@ -1215,7 +1234,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1215 if (!(state->type & INTEL_PT_BRANCH)) 1234 if (!(state->type & INTEL_PT_BRANCH))
1216 return 0; 1235 return 0;
1217 1236
1218 if (pt->synth_opts.callchain) 1237 if (pt->synth_opts.callchain || pt->synth_opts.thread_stack)
1219 thread_stack__event(ptq->thread, ptq->flags, state->from_ip, 1238 thread_stack__event(ptq->thread, ptq->flags, state->from_ip,
1220 state->to_ip, ptq->insn_len, 1239 state->to_ip, ptq->insn_len,
1221 state->trace_nr); 1240 state->trace_nr);
@@ -1832,7 +1851,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1832 u64 id; 1851 u64 id;
1833 int err; 1852 int err;
1834 1853
1835 evlist__for_each(evlist, evsel) { 1854 evlist__for_each_entry(evlist, evsel) {
1836 if (evsel->attr.type == pt->pmu_type && evsel->ids) { 1855 if (evsel->attr.type == pt->pmu_type && evsel->ids) {
1837 found = true; 1856 found = true;
1838 break; 1857 break;
@@ -1912,7 +1931,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1912 pt->sample_transactions = true; 1931 pt->sample_transactions = true;
1913 pt->transactions_id = id; 1932 pt->transactions_id = id;
1914 id += 1; 1933 id += 1;
1915 evlist__for_each(evlist, evsel) { 1934 evlist__for_each_entry(evlist, evsel) {
1916 if (evsel->id && evsel->id[0] == pt->transactions_id) { 1935 if (evsel->id && evsel->id[0] == pt->transactions_id) {
1917 if (evsel->name) 1936 if (evsel->name)
1918 zfree(&evsel->name); 1937 zfree(&evsel->name);
@@ -1950,7 +1969,7 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
1950{ 1969{
1951 struct perf_evsel *evsel; 1970 struct perf_evsel *evsel;
1952 1971
1953 evlist__for_each_reverse(evlist, evsel) { 1972 evlist__for_each_entry_reverse(evlist, evsel) {
1954 const char *name = perf_evsel__name(evsel); 1973 const char *name = perf_evsel__name(evsel);
1955 1974
1956 if (!strcmp(name, "sched:sched_switch")) 1975 if (!strcmp(name, "sched:sched_switch"))
@@ -1964,7 +1983,7 @@ static bool intel_pt_find_switch(struct perf_evlist *evlist)
1964{ 1983{
1965 struct perf_evsel *evsel; 1984 struct perf_evsel *evsel;
1966 1985
1967 evlist__for_each(evlist, evsel) { 1986 evlist__for_each_entry(evlist, evsel) {
1968 if (evsel->attr.context_switch) 1987 if (evsel->attr.context_switch)
1969 return true; 1988 return true;
1970 } 1989 }
@@ -2118,6 +2137,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2118 pt->synth_opts.branches = false; 2137 pt->synth_opts.branches = false;
2119 pt->synth_opts.callchain = true; 2138 pt->synth_opts.callchain = true;
2120 } 2139 }
2140 if (session->itrace_synth_opts)
2141 pt->synth_opts.thread_stack =
2142 session->itrace_synth_opts->thread_stack;
2121 } 2143 }
2122 2144
2123 if (pt->synth_opts.log) 2145 if (pt->synth_opts.log)
diff --git a/tools/perf/util/intlist.h b/tools/perf/util/intlist.h
index aa6877d36858..020b9ca1b47e 100644
--- a/tools/perf/util/intlist.h
+++ b/tools/perf/util/intlist.h
@@ -57,21 +57,21 @@ static inline struct int_node *intlist__next(struct int_node *in)
57} 57}
58 58
59/** 59/**
60 * intlist_for_each - iterate over a intlist 60 * intlist__for_each_entry - iterate over a intlist
61 * @pos: the &struct int_node to use as a loop cursor. 61 * @pos: the &struct int_node to use as a loop cursor.
62 * @ilist: the &struct intlist for loop. 62 * @ilist: the &struct intlist for loop.
63 */ 63 */
64#define intlist__for_each(pos, ilist) \ 64#define intlist__for_each_entry(pos, ilist) \
65 for (pos = intlist__first(ilist); pos; pos = intlist__next(pos)) 65 for (pos = intlist__first(ilist); pos; pos = intlist__next(pos))
66 66
67/** 67/**
68 * intlist_for_each_safe - iterate over a intlist safe against removal of 68 * intlist__for_each_entry_safe - iterate over a intlist safe against removal of
69 * int_node 69 * int_node
70 * @pos: the &struct int_node to use as a loop cursor. 70 * @pos: the &struct int_node to use as a loop cursor.
71 * @n: another &struct int_node to use as temporary storage. 71 * @n: another &struct int_node to use as temporary storage.
72 * @ilist: the &struct intlist for loop. 72 * @ilist: the &struct intlist for loop.
73 */ 73 */
74#define intlist__for_each_safe(pos, n, ilist) \ 74#define intlist__for_each_entry_safe(pos, n, ilist) \
75 for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\ 75 for (pos = intlist__first(ilist), n = intlist__next(pos); pos;\
76 pos = n, n = intlist__next(n)) 76 pos = n, n = intlist__next(n))
77#endif /* __PERF_INTLIST_H */ 77#endif /* __PERF_INTLIST_H */
diff --git a/tools/perf/util/jitdump.c b/tools/perf/util/jitdump.c
index ad0c0bb1fbc7..95f0884aae02 100644
--- a/tools/perf/util/jitdump.c
+++ b/tools/perf/util/jitdump.c
@@ -1,3 +1,4 @@
1#include <sys/sysmacros.h>
1#include <sys/types.h> 2#include <sys/types.h>
2#include <stdio.h> 3#include <stdio.h>
3#include <stdlib.h> 4#include <stdlib.h>
@@ -17,6 +18,7 @@
17#include "strlist.h" 18#include "strlist.h"
18#include <elf.h> 19#include <elf.h>
19 20
21#include "tsc.h"
20#include "session.h" 22#include "session.h"
21#include "jit.h" 23#include "jit.h"
22#include "jitdump.h" 24#include "jitdump.h"
@@ -33,6 +35,7 @@ struct jit_buf_desc {
33 size_t bufsize; 35 size_t bufsize;
34 FILE *in; 36 FILE *in;
35 bool needs_bswap; /* handles cross-endianess */ 37 bool needs_bswap; /* handles cross-endianess */
38 bool use_arch_timestamp;
36 void *debug_data; 39 void *debug_data;
37 size_t nr_debug_entries; 40 size_t nr_debug_entries;
38 uint32_t code_load_count; 41 uint32_t code_load_count;
@@ -106,7 +109,7 @@ jit_validate_events(struct perf_session *session)
106 /* 109 /*
107 * check that all events use CLOCK_MONOTONIC 110 * check that all events use CLOCK_MONOTONIC
108 */ 111 */
109 evlist__for_each(session->evlist, evsel) { 112 evlist__for_each_entry(session->evlist, evsel) {
110 if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) 113 if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC)
111 return -1; 114 return -1;
112 } 115 }
@@ -158,13 +161,16 @@ jit_open(struct jit_buf_desc *jd, const char *name)
158 header.flags = bswap_64(header.flags); 161 header.flags = bswap_64(header.flags);
159 } 162 }
160 163
164 jd->use_arch_timestamp = header.flags & JITDUMP_FLAGS_ARCH_TIMESTAMP;
165
161 if (verbose > 2) 166 if (verbose > 2)
162 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\n", 167 pr_debug("version=%u\nhdr.size=%u\nts=0x%llx\npid=%d\nelf_mach=%d\nuse_arch_timestamp=%d\n",
163 header.version, 168 header.version,
164 header.total_size, 169 header.total_size,
165 (unsigned long long)header.timestamp, 170 (unsigned long long)header.timestamp,
166 header.pid, 171 header.pid,
167 header.elf_mach); 172 header.elf_mach,
173 jd->use_arch_timestamp);
168 174
169 if (header.flags & JITDUMP_FLAGS_RESERVED) { 175 if (header.flags & JITDUMP_FLAGS_RESERVED) {
170 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n", 176 pr_err("jitdump file contains invalid or unsupported flags 0x%llx\n",
@@ -172,10 +178,15 @@ jit_open(struct jit_buf_desc *jd, const char *name)
172 goto error; 178 goto error;
173 } 179 }
174 180
181 if (jd->use_arch_timestamp && !jd->session->time_conv.time_mult) {
182 pr_err("jitdump file uses arch timestamps but there is no timestamp conversion\n");
183 goto error;
184 }
185
175 /* 186 /*
176 * validate event is using the correct clockid 187 * validate event is using the correct clockid
177 */ 188 */
178 if (jit_validate_events(jd->session)) { 189 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"); 190 pr_err("error, jitted code must be sampled with perf record -k 1\n");
180 goto error; 191 goto error;
181 } 192 }
@@ -329,6 +340,23 @@ jit_inject_event(struct jit_buf_desc *jd, union perf_event *event)
329 return 0; 340 return 0;
330} 341}
331 342
343static uint64_t convert_timestamp(struct jit_buf_desc *jd, uint64_t timestamp)
344{
345 struct perf_tsc_conversion tc;
346
347 if (!jd->use_arch_timestamp)
348 return timestamp;
349
350 tc.time_shift = jd->session->time_conv.time_shift;
351 tc.time_mult = jd->session->time_conv.time_mult;
352 tc.time_zero = jd->session->time_conv.time_zero;
353
354 if (!tc.time_mult)
355 return 0;
356
357 return tsc_to_perf_time(timestamp, &tc);
358}
359
332static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) 360static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
333{ 361{
334 struct perf_sample sample; 362 struct perf_sample sample;
@@ -385,7 +413,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
385 return -1; 413 return -1;
386 } 414 }
387 if (stat(filename, &st)) 415 if (stat(filename, &st))
388 memset(&st, 0, sizeof(stat)); 416 memset(&st, 0, sizeof(st));
389 417
390 event->mmap2.header.type = PERF_RECORD_MMAP2; 418 event->mmap2.header.type = PERF_RECORD_MMAP2;
391 event->mmap2.header.misc = PERF_RECORD_MISC_USER; 419 event->mmap2.header.misc = PERF_RECORD_MISC_USER;
@@ -410,7 +438,7 @@ static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr)
410 id->tid = tid; 438 id->tid = tid;
411 } 439 }
412 if (jd->sample_type & PERF_SAMPLE_TIME) 440 if (jd->sample_type & PERF_SAMPLE_TIME)
413 id->time = jr->load.p.timestamp; 441 id->time = convert_timestamp(jd, jr->load.p.timestamp);
414 442
415 /* 443 /*
416 * create pseudo sample to induce dso hit increment 444 * create pseudo sample to induce dso hit increment
@@ -473,7 +501,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
473 size++; /* for \0 */ 501 size++; /* for \0 */
474 502
475 if (stat(filename, &st)) 503 if (stat(filename, &st))
476 memset(&st, 0, sizeof(stat)); 504 memset(&st, 0, sizeof(st));
477 505
478 size = PERF_ALIGN(size, sizeof(u64)); 506 size = PERF_ALIGN(size, sizeof(u64));
479 507
@@ -499,7 +527,7 @@ static int jit_repipe_code_move(struct jit_buf_desc *jd, union jr_entry *jr)
499 id->tid = tid; 527 id->tid = tid;
500 } 528 }
501 if (jd->sample_type & PERF_SAMPLE_TIME) 529 if (jd->sample_type & PERF_SAMPLE_TIME)
502 id->time = jr->load.p.timestamp; 530 id->time = convert_timestamp(jd, jr->load.p.timestamp);
503 531
504 /* 532 /*
505 * create pseudo sample to induce dso hit increment 533 * create pseudo sample to induce dso hit increment
diff --git a/tools/perf/util/jitdump.h b/tools/perf/util/jitdump.h
index b66c1f503d9e..bcacd20d0c1c 100644
--- a/tools/perf/util/jitdump.h
+++ b/tools/perf/util/jitdump.h
@@ -23,9 +23,12 @@
23#define JITHEADER_VERSION 1 23#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
diff --git a/tools/perf/util/levenshtein.c b/tools/perf/util/levenshtein.c
index e521d1516df6..f616e4f65b67 100644
--- a/tools/perf/util/levenshtein.c
+++ b/tools/perf/util/levenshtein.c
@@ -1,5 +1,7 @@
1#include "cache.h"
2#include "levenshtein.h" 1#include "levenshtein.h"
2#include <errno.h>
3#include <stdlib.h>
4#include <string.h>
3 5
4/* 6/*
5 * This function implements the Damerau-Levenshtein algorithm to 7 * This function implements the Damerau-Levenshtein algorithm to
diff --git a/tools/perf/util/libunwind/arm64.c b/tools/perf/util/libunwind/arm64.c
new file mode 100644
index 000000000000..6559bc586643
--- /dev/null
+++ b/tools/perf/util/libunwind/arm64.c
@@ -0,0 +1,40 @@
1/*
2 * This file setups defines to compile arch specific binary from the
3 * generic one.
4 *
5 * The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch
6 * name and the defination of this function is included directly from
7 * 'arch/arm64/util/unwind-libunwind.c', to make sure that this function
8 * is defined no matter what arch the host is.
9 *
10 * Finally, the arch specific unwind methods are exported which will
11 * be assigned to each arm64 thread.
12 */
13
14#define REMOTE_UNWIND_LIBUNWIND
15
16/* Define arch specific functions & regs for libunwind, should be
17 * defined before including "unwind.h"
18 */
19#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arm64_reg_id(regnum)
20#define LIBUNWIND__ARCH_REG_IP PERF_REG_ARM64_PC
21#define LIBUNWIND__ARCH_REG_SP PERF_REG_ARM64_SP
22
23#include "unwind.h"
24#include "debug.h"
25#include "libunwind-aarch64.h"
26#include <../../../../arch/arm64/include/uapi/asm/perf_regs.h>
27#include "../../arch/arm64/util/unwind-libunwind.c"
28
29/* NO_LIBUNWIND_DEBUG_FRAME is a feature flag for local libunwind,
30 * assign NO_LIBUNWIND_DEBUG_FRAME_AARCH64 to it for compiling arm64
31 * unwind methods.
32 */
33#undef NO_LIBUNWIND_DEBUG_FRAME
34#ifdef NO_LIBUNWIND_DEBUG_FRAME_AARCH64
35#define NO_LIBUNWIND_DEBUG_FRAME
36#endif
37#include "util/unwind-libunwind-local.c"
38
39struct unwind_libunwind_ops *
40arm64_unwind_libunwind_ops = &_unwind_libunwind_ops;
diff --git a/tools/perf/util/libunwind/x86_32.c b/tools/perf/util/libunwind/x86_32.c
new file mode 100644
index 000000000000..957ffff72428
--- /dev/null
+++ b/tools/perf/util/libunwind/x86_32.c
@@ -0,0 +1,43 @@
1/*
2 * This file setups defines to compile arch specific binary from the
3 * generic one.
4 *
5 * The function 'LIBUNWIND__ARCH_REG_ID' name is set according to arch
6 * name and the defination of this function is included directly from
7 * 'arch/x86/util/unwind-libunwind.c', to make sure that this function
8 * is defined no matter what arch the host is.
9 *
10 * Finally, the arch specific unwind methods are exported which will
11 * be assigned to each x86 thread.
12 */
13
14#define REMOTE_UNWIND_LIBUNWIND
15
16/* Define arch specific functions & regs for libunwind, should be
17 * defined before including "unwind.h"
18 */
19#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__x86_reg_id(regnum)
20#define LIBUNWIND__ARCH_REG_IP PERF_REG_X86_IP
21#define LIBUNWIND__ARCH_REG_SP PERF_REG_X86_SP
22
23#include "unwind.h"
24#include "debug.h"
25#include "libunwind-x86.h"
26#include <../../../../arch/x86/include/uapi/asm/perf_regs.h>
27
28/* HAVE_ARCH_X86_64_SUPPORT is used in'arch/x86/util/unwind-libunwind.c'
29 * for x86_32, we undef it to compile code for x86_32 only.
30 */
31#undef HAVE_ARCH_X86_64_SUPPORT
32#include "../../arch/x86/util/unwind-libunwind.c"
33
34/* Explicitly define NO_LIBUNWIND_DEBUG_FRAME, because non-ARM has no
35 * dwarf_find_debug_frame() function.
36 */
37#ifndef NO_LIBUNWIND_DEBUG_FRAME
38#define NO_LIBUNWIND_DEBUG_FRAME
39#endif
40#include "util/unwind-libunwind-local.c"
41
42struct unwind_libunwind_ops *
43x86_32_unwind_libunwind_ops = &_unwind_libunwind_ops;
diff --git a/tools/perf/util/llvm-utils.c b/tools/perf/util/llvm-utils.c
index 33071d6159bc..bf7216b8731d 100644
--- a/tools/perf/util/llvm-utils.c
+++ b/tools/perf/util/llvm-utils.c
@@ -3,11 +3,14 @@
3 * Copyright (C) 2015, Huawei Inc. 3 * Copyright (C) 2015, Huawei Inc.
4 */ 4 */
5 5
6#include <errno.h>
6#include <limits.h> 7#include <limits.h>
7#include <stdio.h> 8#include <stdio.h>
8#include <stdlib.h> 9#include <stdlib.h>
9#include "debug.h" 10#include "debug.h"
10#include "llvm-utils.h" 11#include "llvm-utils.h"
12#include "config.h"
13#include "util.h"
11 14
12#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \ 15#define CLANG_BPF_CMD_DEFAULT_TEMPLATE \
13 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\ 16 "$CLANG_EXEC -D__KERNEL__ -D__NR_CPUS__=$NR_CPUS "\
@@ -42,6 +45,8 @@ int perf_llvm_config(const char *var, const char *value)
42 llvm_param.kbuild_dir = strdup(value); 45 llvm_param.kbuild_dir = strdup(value);
43 else if (!strcmp(var, "kbuild-opts")) 46 else if (!strcmp(var, "kbuild-opts"))
44 llvm_param.kbuild_opts = strdup(value); 47 llvm_param.kbuild_opts = strdup(value);
48 else if (!strcmp(var, "dump-obj"))
49 llvm_param.dump_obj = !!perf_config_bool(var, value);
45 else 50 else
46 return -1; 51 return -1;
47 llvm_param.user_set_param = true; 52 llvm_param.user_set_param = true;
@@ -103,7 +108,7 @@ read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz)
103 file = popen(cmd, "r"); 108 file = popen(cmd, "r");
104 if (!file) { 109 if (!file) {
105 pr_err("ERROR: unable to popen cmd: %s\n", 110 pr_err("ERROR: unable to popen cmd: %s\n",
106 strerror_r(errno, serr, sizeof(serr))); 111 str_error_r(errno, serr, sizeof(serr)));
107 return -EINVAL; 112 return -EINVAL;
108 } 113 }
109 114
@@ -137,7 +142,7 @@ read_from_pipe(const char *cmd, void **p_buf, size_t *p_read_sz)
137 142
138 if (ferror(file)) { 143 if (ferror(file)) {
139 pr_err("ERROR: error occurred when reading from pipe: %s\n", 144 pr_err("ERROR: error occurred when reading from pipe: %s\n",
140 strerror_r(errno, serr, sizeof(serr))); 145 str_error_r(errno, serr, sizeof(serr)));
141 err = -EIO; 146 err = -EIO;
142 goto errout; 147 goto errout;
143 } 148 }
@@ -326,6 +331,42 @@ get_kbuild_opts(char **kbuild_dir, char **kbuild_include_opts)
326 pr_debug("include option is set to %s\n", *kbuild_include_opts); 331 pr_debug("include option is set to %s\n", *kbuild_include_opts);
327} 332}
328 333
334static void
335dump_obj(const char *path, void *obj_buf, size_t size)
336{
337 char *obj_path = strdup(path);
338 FILE *fp;
339 char *p;
340
341 if (!obj_path) {
342 pr_warning("WARNING: No enough memory, skip object dumping\n");
343 return;
344 }
345
346 p = strrchr(obj_path, '.');
347 if (!p || (strcmp(p, ".c") != 0)) {
348 pr_warning("WARNING: invalid llvm source path: '%s', skip object dumping\n",
349 obj_path);
350 goto out;
351 }
352
353 p[1] = 'o';
354 fp = fopen(obj_path, "wb");
355 if (!fp) {
356 pr_warning("WARNING: failed to open '%s': %s, skip object dumping\n",
357 obj_path, strerror(errno));
358 goto out;
359 }
360
361 pr_info("LLVM: dumping %s\n", obj_path);
362 if (fwrite(obj_buf, size, 1, fp) != 1)
363 pr_warning("WARNING: failed to write to file '%s': %s, skip object dumping\n",
364 obj_path, strerror(errno));
365 fclose(fp);
366out:
367 free(obj_path);
368}
369
329int llvm__compile_bpf(const char *path, void **p_obj_buf, 370int llvm__compile_bpf(const char *path, void **p_obj_buf,
330 size_t *p_obj_buf_sz) 371 size_t *p_obj_buf_sz)
331{ 372{
@@ -343,7 +384,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
343 if (path[0] != '-' && realpath(path, abspath) == NULL) { 384 if (path[0] != '-' && realpath(path, abspath) == NULL) {
344 err = errno; 385 err = errno;
345 pr_err("ERROR: problems with path %s: %s\n", 386 pr_err("ERROR: problems with path %s: %s\n",
346 path, strerror_r(err, serr, sizeof(serr))); 387 path, str_error_r(err, serr, sizeof(serr)));
347 return -err; 388 return -err;
348 } 389 }
349 390
@@ -371,7 +412,7 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
371 if (nr_cpus_avail <= 0) { 412 if (nr_cpus_avail <= 0) {
372 pr_err( 413 pr_err(
373"WARNING:\tunable to get available CPUs in this system: %s\n" 414"WARNING:\tunable to get available CPUs in this system: %s\n"
374" \tUse 128 instead.\n", strerror_r(errno, serr, sizeof(serr))); 415" \tUse 128 instead.\n", str_error_r(errno, serr, sizeof(serr)));
375 nr_cpus_avail = 128; 416 nr_cpus_avail = 128;
376 } 417 }
377 snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d", 418 snprintf(nr_cpus_avail_str, sizeof(nr_cpus_avail_str), "%d",
@@ -411,6 +452,10 @@ int llvm__compile_bpf(const char *path, void **p_obj_buf,
411 452
412 free(kbuild_dir); 453 free(kbuild_dir);
413 free(kbuild_include_opts); 454 free(kbuild_include_opts);
455
456 if (llvm_param.dump_obj)
457 dump_obj(path, obj_buf, obj_buf_sz);
458
414 if (!p_obj_buf) 459 if (!p_obj_buf)
415 free(obj_buf); 460 free(obj_buf);
416 else 461 else
diff --git a/tools/perf/util/llvm-utils.h b/tools/perf/util/llvm-utils.h
index 23b9a743fe72..9f501cef06a1 100644
--- a/tools/perf/util/llvm-utils.h
+++ b/tools/perf/util/llvm-utils.h
@@ -30,6 +30,11 @@ struct llvm_param {
30 */ 30 */
31 const char *kbuild_opts; 31 const char *kbuild_opts;
32 /* 32 /*
33 * Default is false. If set to true, write compiling result
34 * to object file.
35 */
36 bool dump_obj;
37 /*
33 * Default is false. If one of the above fields is set by user 38 * Default is false. If one of the above fields is set by user
34 * explicitly then user_set_llvm is set to true. This is used 39 * explicitly then user_set_llvm is set to true. This is used
35 * for perf test. If user doesn't set anything in .perfconfig 40 * for perf test. If user doesn't set anything in .perfconfig
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 80b9b6a87990..cb6388dbdd98 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -32,6 +32,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
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
@@ -42,6 +43,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
42 43
43 machine->symbol_filter = NULL; 44 machine->symbol_filter = NULL;
44 machine->id_hdr_size = 0; 45 machine->id_hdr_size = 0;
46 machine->kptr_restrict_warned = false;
45 machine->comm_exec = false; 47 machine->comm_exec = false;
46 machine->kernel_start = 0; 48 machine->kernel_start = 0;
47 49
@@ -136,8 +138,10 @@ void machine__exit(struct machine *machine)
136 138
137void machine__delete(struct machine *machine) 139void machine__delete(struct machine *machine)
138{ 140{
139 machine__exit(machine); 141 if (machine) {
140 free(machine); 142 machine__exit(machine);
143 free(machine);
144 }
141} 145}
142 146
143void machines__init(struct machines *machines) 147void machines__init(struct machines *machines)
@@ -361,7 +365,7 @@ out_err:
361} 365}
362 366
363/* 367/*
364 * Caller must eventually drop thread->refcnt returned with a successfull 368 * Caller must eventually drop thread->refcnt returned with a successful
365 * lookup/new thread inserted. 369 * lookup/new thread inserted.
366 */ 370 */
367static struct thread *____machine__findnew_thread(struct machine *machine, 371static struct thread *____machine__findnew_thread(struct machine *machine,
@@ -430,6 +434,7 @@ static struct thread *____machine__findnew_thread(struct machine *machine,
430 */ 434 */
431 thread__get(th); 435 thread__get(th);
432 machine->last_match = th; 436 machine->last_match = th;
437 ++machine->nr_threads;
433 } 438 }
434 439
435 return th; 440 return th;
@@ -681,11 +686,13 @@ size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp)
681 686
682size_t machine__fprintf(struct machine *machine, FILE *fp) 687size_t machine__fprintf(struct machine *machine, FILE *fp)
683{ 688{
684 size_t ret = 0; 689 size_t ret;
685 struct rb_node *nd; 690 struct rb_node *nd;
686 691
687 pthread_rwlock_rdlock(&machine->threads_lock); 692 pthread_rwlock_rdlock(&machine->threads_lock);
688 693
694 ret = fprintf(fp, "Threads: %u\n", machine->nr_threads);
695
689 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) { 696 for (nd = rb_first(&machine->threads); nd; nd = rb_next(nd)) {
690 struct thread *pos = rb_entry(nd, struct thread, rb_node); 697 struct thread *pos = rb_entry(nd, struct thread, rb_node);
691 698
@@ -705,7 +712,7 @@ static struct dso *machine__get_kernel(struct machine *machine)
705 if (machine__is_host(machine)) { 712 if (machine__is_host(machine)) {
706 vmlinux_name = symbol_conf.vmlinux_name; 713 vmlinux_name = symbol_conf.vmlinux_name;
707 if (!vmlinux_name) 714 if (!vmlinux_name)
708 vmlinux_name = "[kernel.kallsyms]"; 715 vmlinux_name = DSO__NAME_KALLSYMS;
709 716
710 kernel = machine__findnew_kernel(machine, vmlinux_name, 717 kernel = machine__findnew_kernel(machine, vmlinux_name,
711 "[kernel]", DSO_TYPE_KERNEL); 718 "[kernel]", DSO_TYPE_KERNEL);
@@ -908,11 +915,11 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
908 return machine__create_kernel_maps(machine); 915 return machine__create_kernel_maps(machine);
909} 916}
910 917
911int machine__load_kallsyms(struct machine *machine, const char *filename, 918int __machine__load_kallsyms(struct machine *machine, const char *filename,
912 enum map_type type, symbol_filter_t filter) 919 enum map_type type, bool no_kcore, symbol_filter_t filter)
913{ 920{
914 struct map *map = machine__kernel_map(machine); 921 struct map *map = machine__kernel_map(machine);
915 int ret = dso__load_kallsyms(map->dso, filename, map, filter); 922 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter);
916 923
917 if (ret > 0) { 924 if (ret > 0) {
918 dso__set_loaded(map->dso, type); 925 dso__set_loaded(map->dso, type);
@@ -927,6 +934,12 @@ int machine__load_kallsyms(struct machine *machine, const char *filename,
927 return ret; 934 return ret;
928} 935}
929 936
937int machine__load_kallsyms(struct machine *machine, const char *filename,
938 enum map_type type, symbol_filter_t filter)
939{
940 return __machine__load_kallsyms(machine, filename, type, false, filter);
941}
942
930int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 943int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
931 symbol_filter_t filter) 944 symbol_filter_t filter)
932{ 945{
@@ -1080,12 +1093,20 @@ static int machine__set_modules_path(struct machine *machine)
1080 1093
1081 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); 1094 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
1082} 1095}
1096int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
1097 const char *name __maybe_unused)
1098{
1099 return 0;
1100}
1083 1101
1084static int machine__create_module(void *arg, const char *name, u64 start) 1102static int machine__create_module(void *arg, const char *name, u64 start)
1085{ 1103{
1086 struct machine *machine = arg; 1104 struct machine *machine = arg;
1087 struct map *map; 1105 struct map *map;
1088 1106
1107 if (arch__fix_module_text_start(&start, name) < 0)
1108 return -1;
1109
1089 map = machine__findnew_module_map(machine, start, name); 1110 map = machine__findnew_module_map(machine, start, name);
1090 if (map == NULL) 1111 if (map == NULL)
1091 return -1; 1112 return -1;
@@ -1125,10 +1146,10 @@ int machine__create_kernel_maps(struct machine *machine)
1125{ 1146{
1126 struct dso *kernel = machine__get_kernel(machine); 1147 struct dso *kernel = machine__get_kernel(machine);
1127 const char *name; 1148 const char *name;
1128 u64 addr = machine__get_running_kernel_start(machine, &name); 1149 u64 addr;
1129 int ret; 1150 int ret;
1130 1151
1131 if (!addr || kernel == NULL) 1152 if (kernel == NULL)
1132 return -1; 1153 return -1;
1133 1154
1134 ret = __machine__create_kernel_maps(machine, kernel); 1155 ret = __machine__create_kernel_maps(machine, kernel);
@@ -1150,8 +1171,9 @@ int machine__create_kernel_maps(struct machine *machine)
1150 */ 1171 */
1151 map_groups__fixup_end(&machine->kmaps); 1172 map_groups__fixup_end(&machine->kmaps);
1152 1173
1153 if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, 1174 addr = machine__get_running_kernel_start(machine, &name);
1154 addr)) { 1175 if (!addr) {
1176 } else if (maps__set_kallsyms_ref_reloc_sym(machine->vmlinux_maps, name, addr)) {
1155 machine__destroy_kernel_maps(machine); 1177 machine__destroy_kernel_maps(machine);
1156 return -1; 1178 return -1;
1157 } 1179 }
@@ -1341,11 +1363,16 @@ int machine__process_mmap2_event(struct machine *machine,
1341 if (map == NULL) 1363 if (map == NULL)
1342 goto out_problem_map; 1364 goto out_problem_map;
1343 1365
1344 thread__insert_map(thread, map); 1366 ret = thread__insert_map(thread, map);
1367 if (ret)
1368 goto out_problem_insert;
1369
1345 thread__put(thread); 1370 thread__put(thread);
1346 map__put(map); 1371 map__put(map);
1347 return 0; 1372 return 0;
1348 1373
1374out_problem_insert:
1375 map__put(map);
1349out_problem_map: 1376out_problem_map:
1350 thread__put(thread); 1377 thread__put(thread);
1351out_problem: 1378out_problem:
@@ -1391,11 +1418,16 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1391 if (map == NULL) 1418 if (map == NULL)
1392 goto out_problem_map; 1419 goto out_problem_map;
1393 1420
1394 thread__insert_map(thread, map); 1421 ret = thread__insert_map(thread, map);
1422 if (ret)
1423 goto out_problem_insert;
1424
1395 thread__put(thread); 1425 thread__put(thread);
1396 map__put(map); 1426 map__put(map);
1397 return 0; 1427 return 0;
1398 1428
1429out_problem_insert:
1430 map__put(map);
1399out_problem_map: 1431out_problem_map:
1400 thread__put(thread); 1432 thread__put(thread);
1401out_problem: 1433out_problem:
@@ -1413,6 +1445,7 @@ static void __machine__remove_thread(struct machine *machine, struct thread *th,
1413 pthread_rwlock_wrlock(&machine->threads_lock); 1445 pthread_rwlock_wrlock(&machine->threads_lock);
1414 rb_erase_init(&th->rb_node, &machine->threads); 1446 rb_erase_init(&th->rb_node, &machine->threads);
1415 RB_CLEAR_NODE(&th->rb_node); 1447 RB_CLEAR_NODE(&th->rb_node);
1448 --machine->nr_threads;
1416 /* 1449 /*
1417 * Move it first to the dead_threads list, then drop the reference, 1450 * Move it first to the dead_threads list, then drop the reference,
1418 * if this is the last reference, then the thread__delete destructor 1451 * if this is the last reference, then the thread__delete destructor
@@ -1599,6 +1632,7 @@ struct mem_info *sample__resolve_mem(struct perf_sample *sample,
1599} 1632}
1600 1633
1601static int add_callchain_ip(struct thread *thread, 1634static int add_callchain_ip(struct thread *thread,
1635 struct callchain_cursor *cursor,
1602 struct symbol **parent, 1636 struct symbol **parent,
1603 struct addr_location *root_al, 1637 struct addr_location *root_al,
1604 u8 *cpumode, 1638 u8 *cpumode,
@@ -1630,7 +1664,7 @@ static int add_callchain_ip(struct thread *thread,
1630 * It seems the callchain is corrupted. 1664 * It seems the callchain is corrupted.
1631 * Discard all. 1665 * Discard all.
1632 */ 1666 */
1633 callchain_cursor_reset(&callchain_cursor); 1667 callchain_cursor_reset(cursor);
1634 return 1; 1668 return 1;
1635 } 1669 }
1636 return 0; 1670 return 0;
@@ -1640,7 +1674,7 @@ static int add_callchain_ip(struct thread *thread,
1640 } 1674 }
1641 1675
1642 if (al.sym != NULL) { 1676 if (al.sym != NULL) {
1643 if (sort__has_parent && !*parent && 1677 if (perf_hpp_list.parent && !*parent &&
1644 symbol__match_regex(al.sym, &parent_regex)) 1678 symbol__match_regex(al.sym, &parent_regex))
1645 *parent = al.sym; 1679 *parent = al.sym;
1646 else if (have_ignore_callees && root_al && 1680 else if (have_ignore_callees && root_al &&
@@ -1648,13 +1682,13 @@ static int add_callchain_ip(struct thread *thread,
1648 /* Treat this symbol as the root, 1682 /* Treat this symbol as the root,
1649 forgetting its callees. */ 1683 forgetting its callees. */
1650 *root_al = al; 1684 *root_al = al;
1651 callchain_cursor_reset(&callchain_cursor); 1685 callchain_cursor_reset(cursor);
1652 } 1686 }
1653 } 1687 }
1654 1688
1655 if (symbol_conf.hide_unresolved && al.sym == NULL) 1689 if (symbol_conf.hide_unresolved && al.sym == NULL)
1656 return 0; 1690 return 0;
1657 return callchain_cursor_append(&callchain_cursor, al.addr, al.map, al.sym); 1691 return callchain_cursor_append(cursor, al.addr, al.map, al.sym);
1658} 1692}
1659 1693
1660struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 1694struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
@@ -1724,6 +1758,7 @@ static int remove_loops(struct branch_entry *l, int nr)
1724 * negative error code on other errors. 1758 * negative error code on other errors.
1725 */ 1759 */
1726static int resolve_lbr_callchain_sample(struct thread *thread, 1760static int resolve_lbr_callchain_sample(struct thread *thread,
1761 struct callchain_cursor *cursor,
1727 struct perf_sample *sample, 1762 struct perf_sample *sample,
1728 struct symbol **parent, 1763 struct symbol **parent,
1729 struct addr_location *root_al, 1764 struct addr_location *root_al,
@@ -1756,11 +1791,6 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1756 */ 1791 */
1757 int mix_chain_nr = i + 1 + lbr_nr + 1; 1792 int mix_chain_nr = i + 1 + lbr_nr + 1;
1758 1793
1759 if (mix_chain_nr > PERF_MAX_STACK_DEPTH + PERF_MAX_BRANCH_DEPTH) {
1760 pr_warning("corrupted callchain. skipping...\n");
1761 return 0;
1762 }
1763
1764 for (j = 0; j < mix_chain_nr; j++) { 1794 for (j = 0; j < mix_chain_nr; j++) {
1765 if (callchain_param.order == ORDER_CALLEE) { 1795 if (callchain_param.order == ORDER_CALLEE) {
1766 if (j < i + 1) 1796 if (j < i + 1)
@@ -1778,7 +1808,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1778 ip = lbr_stack->entries[0].to; 1808 ip = lbr_stack->entries[0].to;
1779 } 1809 }
1780 1810
1781 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); 1811 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1782 if (err) 1812 if (err)
1783 return (err < 0) ? err : 0; 1813 return (err < 0) ? err : 0;
1784 } 1814 }
@@ -1789,6 +1819,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1789} 1819}
1790 1820
1791static int thread__resolve_callchain_sample(struct thread *thread, 1821static int thread__resolve_callchain_sample(struct thread *thread,
1822 struct callchain_cursor *cursor,
1792 struct perf_evsel *evsel, 1823 struct perf_evsel *evsel,
1793 struct perf_sample *sample, 1824 struct perf_sample *sample,
1794 struct symbol **parent, 1825 struct symbol **parent,
@@ -1797,16 +1828,14 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1797{ 1828{
1798 struct branch_stack *branch = sample->branch_stack; 1829 struct branch_stack *branch = sample->branch_stack;
1799 struct ip_callchain *chain = sample->callchain; 1830 struct ip_callchain *chain = sample->callchain;
1800 int chain_nr = min(max_stack, (int)chain->nr); 1831 int chain_nr = chain->nr;
1801 u8 cpumode = PERF_RECORD_MISC_USER; 1832 u8 cpumode = PERF_RECORD_MISC_USER;
1802 int i, j, err; 1833 int i, j, err, nr_entries;
1803 int skip_idx = -1; 1834 int skip_idx = -1;
1804 int first_call = 0; 1835 int first_call = 0;
1805 1836
1806 callchain_cursor_reset(&callchain_cursor); 1837 if (perf_evsel__has_branch_callstack(evsel)) {
1807 1838 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); 1839 root_al, max_stack);
1811 if (err) 1840 if (err)
1812 return (err < 0) ? err : 0; 1841 return (err < 0) ? err : 0;
@@ -1816,8 +1845,7 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1816 * Based on DWARF debug information, some architectures skip 1845 * Based on DWARF debug information, some architectures skip
1817 * a callchain entry saved by the kernel. 1846 * a callchain entry saved by the kernel.
1818 */ 1847 */
1819 if (chain->nr < PERF_MAX_STACK_DEPTH) 1848 skip_idx = arch_skip_callchain_idx(thread, chain);
1820 skip_idx = arch_skip_callchain_idx(thread, chain);
1821 1849
1822 /* 1850 /*
1823 * Add branches to call stack for easier browsing. This gives 1851 * Add branches to call stack for easier browsing. This gives
@@ -1863,10 +1891,10 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1863 nr = remove_loops(be, nr); 1891 nr = remove_loops(be, nr);
1864 1892
1865 for (i = 0; i < nr; i++) { 1893 for (i = 0; i < nr; i++) {
1866 err = add_callchain_ip(thread, parent, root_al, 1894 err = add_callchain_ip(thread, cursor, parent, root_al,
1867 NULL, be[i].to); 1895 NULL, be[i].to);
1868 if (!err) 1896 if (!err)
1869 err = add_callchain_ip(thread, parent, root_al, 1897 err = add_callchain_ip(thread, cursor, parent, root_al,
1870 NULL, be[i].from); 1898 NULL, be[i].from);
1871 if (err == -EINVAL) 1899 if (err == -EINVAL)
1872 break; 1900 break;
@@ -1877,12 +1905,8 @@ static int thread__resolve_callchain_sample(struct thread *thread,
1877 } 1905 }
1878 1906
1879check_calls: 1907check_calls:
1880 if (chain->nr > PERF_MAX_STACK_DEPTH && (int)chain->nr > max_stack) { 1908 for (i = first_call, nr_entries = 0;
1881 pr_warning("corrupted callchain. skipping...\n"); 1909 i < chain_nr && nr_entries < max_stack; i++) {
1882 return 0;
1883 }
1884
1885 for (i = first_call; i < chain_nr; i++) {
1886 u64 ip; 1910 u64 ip;
1887 1911
1888 if (callchain_param.order == ORDER_CALLEE) 1912 if (callchain_param.order == ORDER_CALLEE)
@@ -1896,7 +1920,10 @@ check_calls:
1896#endif 1920#endif
1897 ip = chain->ips[j]; 1921 ip = chain->ips[j];
1898 1922
1899 err = add_callchain_ip(thread, parent, root_al, &cpumode, ip); 1923 if (ip < PERF_CONTEXT_MAX)
1924 ++nr_entries;
1925
1926 err = add_callchain_ip(thread, cursor, parent, root_al, &cpumode, ip);
1900 1927
1901 if (err) 1928 if (err)
1902 return (err < 0) ? err : 0; 1929 return (err < 0) ? err : 0;
@@ -1915,19 +1942,12 @@ static int unwind_entry(struct unwind_entry *entry, void *arg)
1915 entry->map, entry->sym); 1942 entry->map, entry->sym);
1916} 1943}
1917 1944
1918int thread__resolve_callchain(struct thread *thread, 1945static int thread__resolve_callchain_unwind(struct thread *thread,
1919 struct perf_evsel *evsel, 1946 struct callchain_cursor *cursor,
1920 struct perf_sample *sample, 1947 struct perf_evsel *evsel,
1921 struct symbol **parent, 1948 struct perf_sample *sample,
1922 struct addr_location *root_al, 1949 int max_stack)
1923 int max_stack)
1924{ 1950{
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? */ 1951 /* Can we do dwarf post unwind? */
1932 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) && 1952 if (!((evsel->attr.sample_type & PERF_SAMPLE_REGS_USER) &&
1933 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER))) 1953 (evsel->attr.sample_type & PERF_SAMPLE_STACK_USER)))
@@ -1938,9 +1958,45 @@ int thread__resolve_callchain(struct thread *thread,
1938 (!sample->user_stack.size)) 1958 (!sample->user_stack.size))
1939 return 0; 1959 return 0;
1940 1960
1941 return unwind__get_entries(unwind_entry, &callchain_cursor, 1961 return unwind__get_entries(unwind_entry, cursor,
1942 thread, sample, max_stack); 1962 thread, sample, max_stack);
1963}
1943 1964
1965int thread__resolve_callchain(struct thread *thread,
1966 struct callchain_cursor *cursor,
1967 struct perf_evsel *evsel,
1968 struct perf_sample *sample,
1969 struct symbol **parent,
1970 struct addr_location *root_al,
1971 int max_stack)
1972{
1973 int ret = 0;
1974
1975 callchain_cursor_reset(&callchain_cursor);
1976
1977 if (callchain_param.order == ORDER_CALLEE) {
1978 ret = thread__resolve_callchain_sample(thread, cursor,
1979 evsel, sample,
1980 parent, root_al,
1981 max_stack);
1982 if (ret)
1983 return ret;
1984 ret = thread__resolve_callchain_unwind(thread, cursor,
1985 evsel, sample,
1986 max_stack);
1987 } else {
1988 ret = thread__resolve_callchain_unwind(thread, cursor,
1989 evsel, sample,
1990 max_stack);
1991 if (ret)
1992 return ret;
1993 ret = thread__resolve_callchain_sample(thread, cursor,
1994 evsel, sample,
1995 parent, root_al,
1996 max_stack);
1997 }
1998
1999 return ret;
1944} 2000}
1945 2001
1946int machine__for_each_thread(struct machine *machine, 2002int machine__for_each_thread(struct machine *machine,
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 8499db281158..20739f746bc4 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -28,9 +28,11 @@ struct machine {
28 pid_t pid; 28 pid_t pid;
29 u16 id_hdr_size; 29 u16 id_hdr_size;
30 bool comm_exec; 30 bool comm_exec;
31 bool kptr_restrict_warned;
31 char *root_dir; 32 char *root_dir;
32 struct rb_root threads; 33 struct rb_root threads;
33 pthread_rwlock_t threads_lock; 34 pthread_rwlock_t threads_lock;
35 unsigned int nr_threads;
34 struct list_head dead_threads; 36 struct list_head dead_threads;
35 struct thread *last_match; 37 struct thread *last_match;
36 struct vdso_info *vdso_info; 38 struct vdso_info *vdso_info;
@@ -141,7 +143,11 @@ struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
141 struct addr_location *al); 143 struct addr_location *al);
142struct mem_info *sample__resolve_mem(struct perf_sample *sample, 144struct mem_info *sample__resolve_mem(struct perf_sample *sample,
143 struct addr_location *al); 145 struct addr_location *al);
146
147struct callchain_cursor;
148
144int thread__resolve_callchain(struct thread *thread, 149int thread__resolve_callchain(struct thread *thread,
150 struct callchain_cursor *cursor,
145 struct perf_evsel *evsel, 151 struct perf_evsel *evsel,
146 struct perf_sample *sample, 152 struct perf_sample *sample,
147 struct symbol **parent, 153 struct symbol **parent,
@@ -210,7 +216,10 @@ struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
210 216
211struct map *machine__findnew_module_map(struct machine *machine, u64 start, 217struct map *machine__findnew_module_map(struct machine *machine, u64 start,
212 const char *filename); 218 const char *filename);
219int arch__fix_module_text_start(u64 *start, const char *name);
213 220
221int __machine__load_kallsyms(struct machine *machine, const char *filename,
222 enum map_type type, bool no_kcore, symbol_filter_t filter);
214int machine__load_kallsyms(struct machine *machine, const char *filename, 223int machine__load_kallsyms(struct machine *machine, const char *filename,
215 enum map_type type, symbol_filter_t filter); 224 enum map_type type, symbol_filter_t filter);
216int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 225int machine__load_vmlinux_path(struct machine *machine, enum map_type type,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 171b6d10a04b..728129ac653a 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -15,6 +15,7 @@
15#include "debug.h" 15#include "debug.h"
16#include "machine.h" 16#include "machine.h"
17#include <linux/string.h> 17#include <linux/string.h>
18#include "unwind.h"
18 19
19static void __maps__insert(struct maps *maps, struct map *map); 20static void __maps__insert(struct maps *maps, struct map *map);
20 21
@@ -289,7 +290,7 @@ int map__load(struct map *map, symbol_filter_t filter)
289 nr = dso__load(map->dso, map, filter); 290 nr = dso__load(map->dso, map, filter);
290 if (nr < 0) { 291 if (nr < 0) {
291 if (map->dso->has_build_id) { 292 if (map->dso->has_build_id) {
292 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 293 char sbuild_id[SBUILD_ID_SIZE];
293 294
294 build_id__sprintf(map->dso->build_id, 295 build_id__sprintf(map->dso->build_id,
295 sizeof(map->dso->build_id), 296 sizeof(map->dso->build_id),
@@ -311,6 +312,9 @@ int map__load(struct map *map, symbol_filter_t filter)
311 pr_warning("%.*s was updated (is prelink enabled?). " 312 pr_warning("%.*s was updated (is prelink enabled?). "
312 "Restart the long running apps that use it!\n", 313 "Restart the long running apps that use it!\n",
313 (int)real_len, name); 314 (int)real_len, name);
315 } else if (filter) {
316 pr_warning("no symbols passed the given filter.\n");
317 return -2; /* Empty but maybe by the filter */
314 } else { 318 } else {
315 pr_warning("no symbols found in %s, maybe install " 319 pr_warning("no symbols found in %s, maybe install "
316 "a debug package?\n", name); 320 "a debug package?\n", name);
@@ -431,6 +435,13 @@ u64 map__rip_2objdump(struct map *map, u64 rip)
431 if (map->dso->rel) 435 if (map->dso->rel)
432 return rip - map->pgoff; 436 return rip - map->pgoff;
433 437
438 /*
439 * kernel modules also have DSO_TYPE_USER in dso->kernel,
440 * but all kernel modules are ET_REL, so won't get here.
441 */
442 if (map->dso->kernel == DSO_TYPE_USER)
443 return rip + map->dso->text_offset;
444
434 return map->unmap_ip(map, rip) - map->reloc; 445 return map->unmap_ip(map, rip) - map->reloc;
435} 446}
436 447
@@ -454,6 +465,13 @@ u64 map__objdump_2mem(struct map *map, u64 ip)
454 if (map->dso->rel) 465 if (map->dso->rel)
455 return map->unmap_ip(map, ip + map->pgoff); 466 return map->unmap_ip(map, ip + map->pgoff);
456 467
468 /*
469 * kernel modules also have DSO_TYPE_USER in dso->kernel,
470 * but all kernel modules are ET_REL, so won't get here.
471 */
472 if (map->dso->kernel == DSO_TYPE_USER)
473 return map->unmap_ip(map, ip - map->dso->text_offset);
474
457 return ip + map->reloc; 475 return ip + map->reloc;
458} 476}
459 477
@@ -730,9 +748,10 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
730/* 748/*
731 * XXX This should not really _copy_ te maps, but refcount them. 749 * XXX This should not really _copy_ te maps, but refcount them.
732 */ 750 */
733int map_groups__clone(struct map_groups *mg, 751int map_groups__clone(struct thread *thread,
734 struct map_groups *parent, enum map_type type) 752 struct map_groups *parent, enum map_type type)
735{ 753{
754 struct map_groups *mg = thread->mg;
736 int err = -ENOMEM; 755 int err = -ENOMEM;
737 struct map *map; 756 struct map *map;
738 struct maps *maps = &parent->maps[type]; 757 struct maps *maps = &parent->maps[type];
@@ -743,6 +762,11 @@ int map_groups__clone(struct map_groups *mg,
743 struct map *new = map__clone(map); 762 struct map *new = map__clone(map);
744 if (new == NULL) 763 if (new == NULL)
745 goto out_unlock; 764 goto out_unlock;
765
766 err = unwind__prepare_access(thread, new, NULL);
767 if (err)
768 goto out_unlock;
769
746 map_groups__insert(mg, new); 770 map_groups__insert(mg, new);
747 map__put(new); 771 map__put(new);
748 } 772 }
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 7309d64ce39e..d83396ceecba 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -194,7 +194,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
194 struct map **mapp, symbol_filter_t filter); 194 struct map **mapp, symbol_filter_t filter);
195void map_groups__init(struct map_groups *mg, struct machine *machine); 195void map_groups__init(struct map_groups *mg, struct machine *machine);
196void map_groups__exit(struct map_groups *mg); 196void map_groups__exit(struct map_groups *mg);
197int map_groups__clone(struct map_groups *mg, 197int map_groups__clone(struct thread *thread,
198 struct map_groups *parent, enum map_type type); 198 struct map_groups *parent, enum map_type type);
199size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); 199size_t map_groups__fprintf(struct map_groups *mg, FILE *fp);
200 200
diff --git a/tools/perf/util/mem-events.c b/tools/perf/util/mem-events.c
index 75465f89a413..bbc368e7d1e4 100644
--- a/tools/perf/util/mem-events.c
+++ b/tools/perf/util/mem-events.c
@@ -10,18 +10,33 @@
10#include "debug.h" 10#include "debug.h"
11#include "symbol.h" 11#include "symbol.h"
12 12
13unsigned int perf_mem_events__loads_ldlat = 30;
14
13#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s } 15#define E(t, n, s) { .tag = t, .name = n, .sysfs_name = s }
14 16
15struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = { 17struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
16 E("ldlat-loads", "cpu/mem-loads,ldlat=30/P", "mem-loads"), 18 E("ldlat-loads", "cpu/mem-loads,ldlat=%u/P", "mem-loads"),
17 E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"), 19 E("ldlat-stores", "cpu/mem-stores/P", "mem-stores"),
18}; 20};
19#undef E 21#undef E
20 22
21#undef E 23#undef E
22 24
25static char mem_loads_name[100];
26static bool mem_loads_name__init;
27
23char *perf_mem_events__name(int i) 28char *perf_mem_events__name(int i)
24{ 29{
30 if (i == PERF_MEM_EVENTS__LOAD) {
31 if (!mem_loads_name__init) {
32 mem_loads_name__init = true;
33 scnprintf(mem_loads_name, sizeof(mem_loads_name),
34 perf_mem_events[i].name,
35 perf_mem_events__loads_ldlat);
36 }
37 return mem_loads_name;
38 }
39
25 return (char *)perf_mem_events[i].name; 40 return (char *)perf_mem_events[i].name;
26} 41}
27 42
diff --git a/tools/perf/util/mem-events.h b/tools/perf/util/mem-events.h
index 5d6d93066a6e..7f69bf9d789d 100644
--- a/tools/perf/util/mem-events.h
+++ b/tools/perf/util/mem-events.h
@@ -18,6 +18,7 @@ enum {
18}; 18};
19 19
20extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX]; 20extern struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX];
21extern unsigned int perf_mem_events__loads_ldlat;
21 22
22int perf_mem_events__parse(const char *str); 23int perf_mem_events__parse(const char *str);
23int perf_mem_events__init(void); 24int perf_mem_events__init(void);
diff --git a/tools/perf/util/ordered-events.c b/tools/perf/util/ordered-events.c
index b1b9e2385f4b..fe84df1875aa 100644
--- a/tools/perf/util/ordered-events.c
+++ b/tools/perf/util/ordered-events.c
@@ -308,3 +308,12 @@ void ordered_events__free(struct ordered_events *oe)
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}
diff --git a/tools/perf/util/ordered-events.h b/tools/perf/util/ordered-events.h
index f403991e3bfd..e11468a9a6e4 100644
--- a/tools/perf/util/ordered-events.h
+++ b/tools/perf/util/ordered-events.h
@@ -49,6 +49,7 @@ void ordered_events__delete(struct ordered_events *oe, struct ordered_event *eve
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 inline 54static 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)
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index bcbc983d4b12..6c913c3914fb 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -20,6 +20,7 @@
20#include "pmu.h" 20#include "pmu.h"
21#include "thread_map.h" 21#include "thread_map.h"
22#include "cpumap.h" 22#include "cpumap.h"
23#include "probe-file.h"
23#include "asm/bug.h" 24#include "asm/bug.h"
24 25
25#define MAX_NAME_LEN 100 26#define MAX_NAME_LEN 100
@@ -436,7 +437,7 @@ int parse_events_add_cache(struct list_head *list, int *idx,
436} 437}
437 438
438static void tracepoint_error(struct parse_events_error *e, int err, 439static void tracepoint_error(struct parse_events_error *e, int err,
439 char *sys, char *name) 440 const char *sys, const char *name)
440{ 441{
441 char help[BUFSIZ]; 442 char help[BUFSIZ];
442 443
@@ -466,7 +467,7 @@ static void tracepoint_error(struct parse_events_error *e, int err,
466} 467}
467 468
468static int add_tracepoint(struct list_head *list, int *idx, 469static int add_tracepoint(struct list_head *list, int *idx,
469 char *sys_name, char *evt_name, 470 const char *sys_name, const char *evt_name,
470 struct parse_events_error *err, 471 struct parse_events_error *err,
471 struct list_head *head_config) 472 struct list_head *head_config)
472{ 473{
@@ -491,7 +492,7 @@ static int add_tracepoint(struct list_head *list, int *idx,
491} 492}
492 493
493static int add_tracepoint_multi_event(struct list_head *list, int *idx, 494static int add_tracepoint_multi_event(struct list_head *list, int *idx,
494 char *sys_name, char *evt_name, 495 const char *sys_name, const char *evt_name,
495 struct parse_events_error *err, 496 struct parse_events_error *err,
496 struct list_head *head_config) 497 struct list_head *head_config)
497{ 498{
@@ -533,7 +534,7 @@ static int add_tracepoint_multi_event(struct list_head *list, int *idx,
533} 534}
534 535
535static int add_tracepoint_event(struct list_head *list, int *idx, 536static int add_tracepoint_event(struct list_head *list, int *idx,
536 char *sys_name, char *evt_name, 537 const char *sys_name, const char *evt_name,
537 struct parse_events_error *err, 538 struct parse_events_error *err,
538 struct list_head *head_config) 539 struct list_head *head_config)
539{ 540{
@@ -545,7 +546,7 @@ static int add_tracepoint_event(struct list_head *list, int *idx,
545} 546}
546 547
547static int add_tracepoint_multi_sys(struct list_head *list, int *idx, 548static int add_tracepoint_multi_sys(struct list_head *list, int *idx,
548 char *sys_name, char *evt_name, 549 const char *sys_name, const char *evt_name,
549 struct parse_events_error *err, 550 struct parse_events_error *err,
550 struct list_head *head_config) 551 struct list_head *head_config)
551{ 552{
@@ -584,7 +585,7 @@ struct __add_bpf_event_param {
584 struct list_head *head_config; 585 struct list_head *head_config;
585}; 586};
586 587
587static int add_bpf_event(struct probe_trace_event *tev, int fd, 588static int add_bpf_event(const char *group, const char *event, int fd,
588 void *_param) 589 void *_param)
589{ 590{
590 LIST_HEAD(new_evsels); 591 LIST_HEAD(new_evsels);
@@ -595,27 +596,27 @@ static int add_bpf_event(struct probe_trace_event *tev, int fd,
595 int err; 596 int err;
596 597
597 pr_debug("add bpf event %s:%s and attach bpf program %d\n", 598 pr_debug("add bpf event %s:%s and attach bpf program %d\n",
598 tev->group, tev->event, fd); 599 group, event, fd);
599 600
600 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, tev->group, 601 err = parse_events_add_tracepoint(&new_evsels, &evlist->idx, group,
601 tev->event, evlist->error, 602 event, evlist->error,
602 param->head_config); 603 param->head_config);
603 if (err) { 604 if (err) {
604 struct perf_evsel *evsel, *tmp; 605 struct perf_evsel *evsel, *tmp;
605 606
606 pr_debug("Failed to add BPF event %s:%s\n", 607 pr_debug("Failed to add BPF event %s:%s\n",
607 tev->group, tev->event); 608 group, event);
608 list_for_each_entry_safe(evsel, tmp, &new_evsels, node) { 609 list_for_each_entry_safe(evsel, tmp, &new_evsels, node) {
609 list_del(&evsel->node); 610 list_del(&evsel->node);
610 perf_evsel__delete(evsel); 611 perf_evsel__delete(evsel);
611 } 612 }
612 return err; 613 return err;
613 } 614 }
614 pr_debug("adding %s:%s\n", tev->group, tev->event); 615 pr_debug("adding %s:%s\n", group, event);
615 616
616 list_for_each_entry(pos, &new_evsels, node) { 617 list_for_each_entry(pos, &new_evsels, node) {
617 pr_debug("adding %s:%s to %p\n", 618 pr_debug("adding %s:%s to %p\n",
618 tev->group, tev->event, pos); 619 group, event, pos);
619 pos->bpf_fd = fd; 620 pos->bpf_fd = fd;
620 } 621 }
621 list_splice(&new_evsels, list); 622 list_splice(&new_evsels, list);
@@ -661,7 +662,7 @@ int parse_events_load_bpf_obj(struct parse_events_evlist *data,
661 goto errout; 662 goto errout;
662 } 663 }
663 664
664 err = bpf__foreach_tev(obj, add_bpf_event, &param); 665 err = bpf__foreach_event(obj, add_bpf_event, &param);
665 if (err) { 666 if (err) {
666 snprintf(errbuf, sizeof(errbuf), 667 snprintf(errbuf, sizeof(errbuf),
667 "Attach events in BPF object failed"); 668 "Attach events in BPF object failed");
@@ -900,6 +901,9 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
900 [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size", 901 [PARSE_EVENTS__TERM_TYPE_STACKSIZE] = "stack-size",
901 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit", 902 [PARSE_EVENTS__TERM_TYPE_NOINHERIT] = "no-inherit",
902 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit", 903 [PARSE_EVENTS__TERM_TYPE_INHERIT] = "inherit",
904 [PARSE_EVENTS__TERM_TYPE_MAX_STACK] = "max-stack",
905 [PARSE_EVENTS__TERM_TYPE_OVERWRITE] = "overwrite",
906 [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE] = "no-overwrite",
903}; 907};
904 908
905static bool config_term_shrinked; 909static bool config_term_shrinked;
@@ -992,9 +996,18 @@ do { \
992 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 996 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
993 CHECK_TYPE_VAL(NUM); 997 CHECK_TYPE_VAL(NUM);
994 break; 998 break;
999 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1000 CHECK_TYPE_VAL(NUM);
1001 break;
1002 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1003 CHECK_TYPE_VAL(NUM);
1004 break;
995 case PARSE_EVENTS__TERM_TYPE_NAME: 1005 case PARSE_EVENTS__TERM_TYPE_NAME:
996 CHECK_TYPE_VAL(STR); 1006 CHECK_TYPE_VAL(STR);
997 break; 1007 break;
1008 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1009 CHECK_TYPE_VAL(NUM);
1010 break;
998 default: 1011 default:
999 err->str = strdup("unknown term"); 1012 err->str = strdup("unknown term");
1000 err->idx = term->err_term; 1013 err->idx = term->err_term;
@@ -1040,6 +1053,9 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
1040 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1053 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
1041 case PARSE_EVENTS__TERM_TYPE_INHERIT: 1054 case PARSE_EVENTS__TERM_TYPE_INHERIT:
1042 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1055 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1056 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1057 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1058 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1043 return config_term_common(attr, term, err); 1059 return config_term_common(attr, term, err);
1044 default: 1060 default:
1045 if (err) { 1061 if (err) {
@@ -1109,6 +1125,15 @@ do { \
1109 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1125 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1110 ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); 1126 ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
1111 break; 1127 break;
1128 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1129 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num);
1130 break;
1131 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1132 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
1133 break;
1134 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1135 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1);
1136 break;
1112 default: 1137 default:
1113 break; 1138 break;
1114 } 1139 }
@@ -1118,7 +1143,7 @@ do { \
1118} 1143}
1119 1144
1120int parse_events_add_tracepoint(struct list_head *list, int *idx, 1145int parse_events_add_tracepoint(struct list_head *list, int *idx,
1121 char *sys, char *event, 1146 const char *sys, const char *event,
1122 struct parse_events_error *err, 1147 struct parse_events_error *err,
1123 struct list_head *head_config) 1148 struct list_head *head_config)
1124{ 1149{
@@ -1388,7 +1413,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
1388 if (!add && get_event_modifier(&mod, str, NULL)) 1413 if (!add && get_event_modifier(&mod, str, NULL))
1389 return -EINVAL; 1414 return -EINVAL;
1390 1415
1391 __evlist__for_each(list, evsel) { 1416 __evlist__for_each_entry(list, evsel) {
1392 if (add && get_event_modifier(&mod, str, evsel)) 1417 if (add && get_event_modifier(&mod, str, evsel))
1393 return -EINVAL; 1418 return -EINVAL;
1394 1419
@@ -1414,7 +1439,7 @@ int parse_events_name(struct list_head *list, char *name)
1414{ 1439{
1415 struct perf_evsel *evsel; 1440 struct perf_evsel *evsel;
1416 1441
1417 __evlist__for_each(list, evsel) { 1442 __evlist__for_each_entry(list, evsel) {
1418 if (!evsel->name) 1443 if (!evsel->name)
1419 evsel->name = strdup(name); 1444 evsel->name = strdup(name);
1420 } 1445 }
@@ -1649,7 +1674,7 @@ static void parse_events_print_error(struct parse_events_error *err,
1649 1674
1650 buf = _buf; 1675 buf = _buf;
1651 1676
1652 /* We're cutting from the beggining. */ 1677 /* We're cutting from the beginning. */
1653 if (err->idx > max_err_idx) 1678 if (err->idx > max_err_idx)
1654 cut = err->idx - max_err_idx; 1679 cut = err->idx - max_err_idx;
1655 1680
@@ -1976,6 +2001,85 @@ static bool is_event_supported(u8 type, unsigned config)
1976 return ret; 2001 return ret;
1977} 2002}
1978 2003
2004void print_sdt_events(const char *subsys_glob, const char *event_glob,
2005 bool name_only)
2006{
2007 struct probe_cache *pcache;
2008 struct probe_cache_entry *ent;
2009 struct strlist *bidlist, *sdtlist;
2010 struct strlist_config cfg = {.dont_dupstr = true};
2011 struct str_node *nd, *nd2;
2012 char *buf, *path, *ptr = NULL;
2013 bool show_detail = false;
2014 int ret;
2015
2016 sdtlist = strlist__new(NULL, &cfg);
2017 if (!sdtlist) {
2018 pr_debug("Failed to allocate new strlist for SDT\n");
2019 return;
2020 }
2021 bidlist = build_id_cache__list_all(true);
2022 if (!bidlist) {
2023 pr_debug("Failed to get buildids: %d\n", errno);
2024 return;
2025 }
2026 strlist__for_each_entry(nd, bidlist) {
2027 pcache = probe_cache__new(nd->s);
2028 if (!pcache)
2029 continue;
2030 list_for_each_entry(ent, &pcache->entries, node) {
2031 if (!ent->sdt)
2032 continue;
2033 if (subsys_glob &&
2034 !strglobmatch(ent->pev.group, subsys_glob))
2035 continue;
2036 if (event_glob &&
2037 !strglobmatch(ent->pev.event, event_glob))
2038 continue;
2039 ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
2040 ent->pev.event, nd->s);
2041 if (ret > 0)
2042 strlist__add(sdtlist, buf);
2043 }
2044 probe_cache__delete(pcache);
2045 }
2046 strlist__delete(bidlist);
2047
2048 strlist__for_each_entry(nd, sdtlist) {
2049 buf = strchr(nd->s, '@');
2050 if (buf)
2051 *(buf++) = '\0';
2052 if (name_only) {
2053 printf("%s ", nd->s);
2054 continue;
2055 }
2056 nd2 = strlist__next(nd);
2057 if (nd2) {
2058 ptr = strchr(nd2->s, '@');
2059 if (ptr)
2060 *ptr = '\0';
2061 if (strcmp(nd->s, nd2->s) == 0)
2062 show_detail = true;
2063 }
2064 if (show_detail) {
2065 path = build_id_cache__origname(buf);
2066 ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
2067 if (ret > 0) {
2068 printf(" %-50s [%s]\n", buf, "SDT event");
2069 free(buf);
2070 }
2071 } else
2072 printf(" %-50s [%s]\n", nd->s, "SDT event");
2073 if (nd2) {
2074 if (strcmp(nd->s, nd2->s) != 0)
2075 show_detail = false;
2076 if (ptr)
2077 *ptr = '@';
2078 }
2079 }
2080 strlist__delete(sdtlist);
2081}
2082
1979int print_hwcache_events(const char *event_glob, bool name_only) 2083int print_hwcache_events(const char *event_glob, bool name_only)
1980{ 2084{
1981 unsigned int type, op, i, evt_i = 0, evt_num = 0; 2085 unsigned int type, op, i, evt_i = 0, evt_num = 0;
@@ -2158,6 +2262,8 @@ void print_events(const char *event_glob, bool name_only)
2158 } 2262 }
2159 2263
2160 print_tracepoint_events(NULL, NULL, name_only); 2264 print_tracepoint_events(NULL, NULL, name_only);
2265
2266 print_sdt_events(NULL, NULL, name_only);
2161} 2267}
2162 2268
2163int parse_events__is_hardcoded_term(struct parse_events_term *term) 2269int parse_events__is_hardcoded_term(struct parse_events_term *term)
@@ -2322,9 +2428,9 @@ static void config_terms_list(char *buf, size_t buf_sz)
2322char *parse_events_formats_error_string(char *additional_terms) 2428char *parse_events_formats_error_string(char *additional_terms)
2323{ 2429{
2324 char *str; 2430 char *str;
2325 /* "branch_type" is the longest name */ 2431 /* "no-overwrite" is the longest name */
2326 char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * 2432 char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
2327 (sizeof("branch_type") - 1)]; 2433 (sizeof("no-overwrite") - 1)];
2328 2434
2329 config_terms_list(static_terms, sizeof(static_terms)); 2435 config_terms_list(static_terms, sizeof(static_terms));
2330 /* valid terms */ 2436 /* valid terms */
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index d740c3ca9a1d..d1edbf8cc66a 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -68,6 +68,9 @@ enum {
68 PARSE_EVENTS__TERM_TYPE_STACKSIZE, 68 PARSE_EVENTS__TERM_TYPE_STACKSIZE,
69 PARSE_EVENTS__TERM_TYPE_NOINHERIT, 69 PARSE_EVENTS__TERM_TYPE_NOINHERIT,
70 PARSE_EVENTS__TERM_TYPE_INHERIT, 70 PARSE_EVENTS__TERM_TYPE_INHERIT,
71 PARSE_EVENTS__TERM_TYPE_MAX_STACK,
72 PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
73 PARSE_EVENTS__TERM_TYPE_OVERWRITE,
71 __PARSE_EVENTS__TERM_TYPE_NR, 74 __PARSE_EVENTS__TERM_TYPE_NR,
72}; 75};
73 76
@@ -133,7 +136,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add);
133int parse_events__modifier_group(struct list_head *list, char *event_mod); 136int parse_events__modifier_group(struct list_head *list, char *event_mod);
134int parse_events_name(struct list_head *list, char *name); 137int parse_events_name(struct list_head *list, char *name);
135int parse_events_add_tracepoint(struct list_head *list, int *idx, 138int parse_events_add_tracepoint(struct list_head *list, int *idx,
136 char *sys, char *event, 139 const char *sys, const char *event,
137 struct parse_events_error *error, 140 struct parse_events_error *error,
138 struct list_head *head_config); 141 struct list_head *head_config);
139int parse_events_load_bpf(struct parse_events_evlist *data, 142int parse_events_load_bpf(struct parse_events_evlist *data,
@@ -182,6 +185,8 @@ void print_symbol_events(const char *event_glob, unsigned type,
182void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 185void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
183 bool name_only); 186 bool name_only);
184int print_hwcache_events(const char *event_glob, bool name_only); 187int print_hwcache_events(const char *event_glob, bool name_only);
188void print_sdt_events(const char *subsys_glob, const char *event_glob,
189 bool name_only);
185int is_valid_tracepoint(const char *event_string); 190int is_valid_tracepoint(const char *event_string);
186 191
187int valid_event_mount(const char *eventfs); 192int valid_event_mount(const char *eventfs);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 1477fbc78993..7a2519435da0 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -199,8 +199,11 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
199time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 199time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
200call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } 200call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
201stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } 201stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
202max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
202inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } 203inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
203no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 204no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
205overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
206no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
204, { return ','; } 207, { return ','; }
205"/" { BEGIN(INITIAL); return '/'; } 208"/" { BEGIN(INITIAL); return '/'; }
206{name_minus} { return str(yyscanner, PE_NAME); } 209{name_minus} { return str(yyscanner, PE_NAME); }
@@ -259,6 +262,7 @@ cycles-ct { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
259cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); } 262cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
260mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); } 263mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
261mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); } 264mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
265topdown-[a-z-]+ { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
262 266
263L1-dcache|l1-d|l1d|L1-data | 267L1-dcache|l1-d|l1d|L1-data |
264L1-icache|l1-i|l1i|L1-instruction | 268L1-icache|l1-i|l1i|L1-instruction |
diff --git a/tools/perf/util/path.c b/tools/perf/util/path.c
index 3bf6bf82ff2d..7c7630be5a89 100644
--- a/tools/perf/util/path.c
+++ b/tools/perf/util/path.c
@@ -11,17 +11,13 @@
11 * which is what it's designed for. 11 * which is what it's designed for.
12 */ 12 */
13#include "cache.h" 13#include "cache.h"
14#include "util.h"
15#include <limits.h>
14 16
15static char bad_path[] = "/bad-path/"; 17static char bad_path[] = "/bad-path/";
16/* 18/*
17 * Two hacks: 19 * One hack:
18 */ 20 */
19
20static const char *get_perf_dir(void)
21{
22 return ".";
23}
24
25static char *get_pathname(void) 21static char *get_pathname(void)
26{ 22{
27 static char pathname_array[4][PATH_MAX]; 23 static char pathname_array[4][PATH_MAX];
@@ -54,60 +50,3 @@ char *mkpath(const char *fmt, ...)
54 return bad_path; 50 return bad_path;
55 return cleanup_path(pathname); 51 return cleanup_path(pathname);
56} 52}
57
58char *perf_path(const char *fmt, ...)
59{
60 const char *perf_dir = get_perf_dir();
61 char *pathname = get_pathname();
62 va_list args;
63 unsigned len;
64
65 len = strlen(perf_dir);
66 if (len > PATH_MAX-100)
67 return bad_path;
68 memcpy(pathname, perf_dir, len);
69 if (len && perf_dir[len-1] != '/')
70 pathname[len++] = '/';
71 va_start(args, fmt);
72 len += vsnprintf(pathname + len, PATH_MAX - len, fmt, args);
73 va_end(args);
74 if (len >= PATH_MAX)
75 return bad_path;
76 return cleanup_path(pathname);
77}
78
79/* strip arbitrary amount of directory separators at end of path */
80static inline int chomp_trailing_dir_sep(const char *path, int len)
81{
82 while (len && is_dir_sep(path[len - 1]))
83 len--;
84 return len;
85}
86
87/*
88 * If path ends with suffix (complete path components), returns the
89 * part before suffix (sans trailing directory separators).
90 * Otherwise returns NULL.
91 */
92char *strip_path_suffix(const char *path, const char *suffix)
93{
94 int path_len = strlen(path), suffix_len = strlen(suffix);
95
96 while (suffix_len) {
97 if (!path_len)
98 return NULL;
99
100 if (is_dir_sep(path[path_len - 1])) {
101 if (!is_dir_sep(suffix[suffix_len - 1]))
102 return NULL;
103 path_len = chomp_trailing_dir_sep(path, path_len);
104 suffix_len = chomp_trailing_dir_sep(suffix, suffix_len);
105 }
106 else if (path[--path_len] != suffix[--suffix_len])
107 return NULL;
108 }
109
110 if (path_len && !is_dir_sep(path[path_len - 1]))
111 return NULL;
112 return strndup(path, chomp_trailing_dir_sep(path, path_len));
113}
diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c
index 6b8eb13e14e4..c4023f22f287 100644
--- a/tools/perf/util/perf_regs.c
+++ b/tools/perf/util/perf_regs.c
@@ -12,18 +12,18 @@ int perf_reg_value(u64 *valp, struct regs_dump *regs, int id)
12 int i, idx = 0; 12 int i, idx = 0;
13 u64 mask = regs->mask; 13 u64 mask = regs->mask;
14 14
15 if (regs->cache_mask & (1 << id)) 15 if (regs->cache_mask & (1ULL << id))
16 goto out; 16 goto out;
17 17
18 if (!(mask & (1 << id))) 18 if (!(mask & (1ULL << id)))
19 return -EINVAL; 19 return -EINVAL;
20 20
21 for (i = 0; i < id; i++) { 21 for (i = 0; i < id; i++) {
22 if (mask & (1 << i)) 22 if (mask & (1ULL << i))
23 idx++; 23 idx++;
24 } 24 }
25 25
26 regs->cache_mask |= (1 << id); 26 regs->cache_mask |= (1ULL << id);
27 regs->cache_regs[id] = regs->regs[idx]; 27 regs->cache_regs[id] = regs->regs[idx];
28 28
29out: 29out:
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index adef23b1352e..ddb0261b2577 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -602,14 +602,13 @@ static void pmu_format_value(unsigned long *format, __u64 value, __u64 *v,
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,
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;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 8319fbb08636..28733962cd80 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -67,7 +67,6 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
67 return ret; 67 return ret;
68} 68}
69 69
70static char *synthesize_perf_probe_point(struct perf_probe_point *pp);
71static struct machine *host_machine; 70static struct machine *host_machine;
72 71
73/* Initialize symbol maps and path of vmlinux/modules */ 72/* Initialize symbol maps and path of vmlinux/modules */
@@ -103,10 +102,8 @@ out:
103 102
104void exit_probe_symbol_maps(void) 103void exit_probe_symbol_maps(void)
105{ 104{
106 if (host_machine) { 105 machine__delete(host_machine);
107 machine__delete(host_machine); 106 host_machine = NULL;
108 host_machine = NULL;
109 }
110 symbol__exit(); 107 symbol__exit();
111} 108}
112 109
@@ -173,15 +170,17 @@ static struct map *kernel_get_module_map(const char *module)
173 module = "kernel"; 170 module = "kernel";
174 171
175 for (pos = maps__first(maps); pos; pos = map__next(pos)) { 172 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
173 /* short_name is "[module]" */
176 if (strncmp(pos->dso->short_name + 1, module, 174 if (strncmp(pos->dso->short_name + 1, module,
177 pos->dso->short_name_len - 2) == 0) { 175 pos->dso->short_name_len - 2) == 0 &&
176 module[pos->dso->short_name_len - 2] == '\0') {
178 return pos; 177 return pos;
179 } 178 }
180 } 179 }
181 return NULL; 180 return NULL;
182} 181}
183 182
184static struct map *get_target_map(const char *target, bool user) 183struct map *get_target_map(const char *target, bool user)
185{ 184{
186 /* Init maps of given executable or kernel */ 185 /* Init maps of given executable or kernel */
187 if (user) 186 if (user)
@@ -265,6 +264,65 @@ static bool kprobe_warn_out_range(const char *symbol, unsigned long address)
265 return true; 264 return true;
266} 265}
267 266
267/*
268 * NOTE:
269 * '.gnu.linkonce.this_module' section of kernel module elf directly
270 * maps to 'struct module' from linux/module.h. This section contains
271 * actual module name which will be used by kernel after loading it.
272 * But, we cannot use 'struct module' here since linux/module.h is not
273 * exposed to user-space. Offset of 'name' has remained same from long
274 * time, so hardcoding it here.
275 */
276#ifdef __LP64__
277#define MOD_NAME_OFFSET 24
278#else
279#define MOD_NAME_OFFSET 12
280#endif
281
282/*
283 * @module can be module name of module file path. In case of path,
284 * inspect elf and find out what is actual module name.
285 * Caller has to free mod_name after using it.
286 */
287static char *find_module_name(const char *module)
288{
289 int fd;
290 Elf *elf;
291 GElf_Ehdr ehdr;
292 GElf_Shdr shdr;
293 Elf_Data *data;
294 Elf_Scn *sec;
295 char *mod_name = NULL;
296
297 fd = open(module, O_RDONLY);
298 if (fd < 0)
299 return NULL;
300
301 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
302 if (elf == NULL)
303 goto elf_err;
304
305 if (gelf_getehdr(elf, &ehdr) == NULL)
306 goto ret_err;
307
308 sec = elf_section_by_name(elf, &ehdr, &shdr,
309 ".gnu.linkonce.this_module", NULL);
310 if (!sec)
311 goto ret_err;
312
313 data = elf_getdata(sec, NULL);
314 if (!data || !data->d_buf)
315 goto ret_err;
316
317 mod_name = strdup((char *)data->d_buf + MOD_NAME_OFFSET);
318
319ret_err:
320 elf_end(elf);
321elf_err:
322 close(fd);
323 return mod_name;
324}
325
268#ifdef HAVE_DWARF_SUPPORT 326#ifdef HAVE_DWARF_SUPPORT
269 327
270static int kernel_get_module_dso(const char *module, struct dso **pdso) 328static int kernel_get_module_dso(const char *module, struct dso **pdso)
@@ -329,7 +387,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
329 if (uprobes) 387 if (uprobes)
330 address = sym->start; 388 address = sym->start;
331 else 389 else
332 address = map->unmap_ip(map, sym->start); 390 address = map->unmap_ip(map, sym->start) - map->reloc;
333 break; 391 break;
334 } 392 }
335 if (!address) { 393 if (!address) {
@@ -412,7 +470,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
412 err = kernel_get_module_dso(module, &dso); 470 err = kernel_get_module_dso(module, &dso);
413 if (err < 0) { 471 if (err < 0) {
414 if (!dso || dso->load_errno == 0) { 472 if (!dso || dso->load_errno == 0) {
415 if (!strerror_r(-err, reason, STRERR_BUFSIZE)) 473 if (!str_error_r(-err, reason, STRERR_BUFSIZE))
416 strcpy(reason, "(unknown)"); 474 strcpy(reason, "(unknown)");
417 } else 475 } else
418 dso__strerror_load(dso, reason, STRERR_BUFSIZE); 476 dso__strerror_load(dso, reason, STRERR_BUFSIZE);
@@ -486,8 +544,10 @@ static int get_text_start_address(const char *exec, unsigned long *address)
486 return -errno; 544 return -errno;
487 545
488 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 546 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
489 if (elf == NULL) 547 if (elf == NULL) {
490 return -EINVAL; 548 ret = -EINVAL;
549 goto out_close;
550 }
491 551
492 if (gelf_getehdr(elf, &ehdr) == NULL) 552 if (gelf_getehdr(elf, &ehdr) == NULL)
493 goto out; 553 goto out;
@@ -499,6 +559,9 @@ static int get_text_start_address(const char *exec, unsigned long *address)
499 ret = 0; 559 ret = 0;
500out: 560out:
501 elf_end(elf); 561 elf_end(elf);
562out_close:
563 close(fd);
564
502 return ret; 565 return ret;
503} 566}
504 567
@@ -583,51 +646,34 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
583 int ntevs, const char *module) 646 int ntevs, const char *module)
584{ 647{
585 int i, ret = 0; 648 int i, ret = 0;
586 char *tmp; 649 char *mod_name = NULL;
587 650
588 if (!module) 651 if (!module)
589 return 0; 652 return 0;
590 653
591 tmp = strrchr(module, '/'); 654 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 655
603 for (i = 0; i < ntevs; i++) { 656 for (i = 0; i < ntevs; i++) {
604 tevs[i].point.module = strdup(module); 657 tevs[i].point.module =
658 strdup(mod_name ? mod_name : module);
605 if (!tevs[i].point.module) { 659 if (!tevs[i].point.module) {
606 ret = -ENOMEM; 660 ret = -ENOMEM;
607 break; 661 break;
608 } 662 }
609 } 663 }
610 664
611 free(tmp); 665 free(mod_name);
612 return ret; 666 return ret;
613} 667}
614 668
615/* Post processing the probe events */ 669static int
616static int post_process_probe_trace_events(struct probe_trace_event *tevs, 670post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
617 int ntevs, const char *module, 671 int ntevs)
618 bool uprobe)
619{ 672{
620 struct ref_reloc_sym *reloc_sym; 673 struct ref_reloc_sym *reloc_sym;
621 char *tmp; 674 char *tmp;
622 int i, skipped = 0; 675 int i, skipped = 0;
623 676
624 if (uprobe)
625 return add_exec_to_probe_trace_events(tevs, ntevs, module);
626
627 /* Note that currently ref_reloc_sym based probe is not for drivers */
628 if (module)
629 return add_module_to_probe_trace_events(tevs, ntevs, module);
630
631 reloc_sym = kernel_get_ref_reloc_sym(); 677 reloc_sym = kernel_get_ref_reloc_sym();
632 if (!reloc_sym) { 678 if (!reloc_sym) {
633 pr_warning("Relocated base symbol is not found!\n"); 679 pr_warning("Relocated base symbol is not found!\n");
@@ -659,6 +705,34 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
659 return skipped; 705 return skipped;
660} 706}
661 707
708void __weak
709arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unused,
710 int ntevs __maybe_unused)
711{
712}
713
714/* Post processing the probe events */
715static int post_process_probe_trace_events(struct perf_probe_event *pev,
716 struct probe_trace_event *tevs,
717 int ntevs, const char *module,
718 bool uprobe)
719{
720 int ret;
721
722 if (uprobe)
723 ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
724 else if (module)
725 /* Currently ref_reloc_sym based probe is not for drivers */
726 ret = add_module_to_probe_trace_events(tevs, ntevs, module);
727 else
728 ret = post_process_kernel_probe_trace_events(tevs, ntevs);
729
730 if (ret >= 0)
731 arch__post_process_probe_trace_events(pev, ntevs);
732
733 return ret;
734}
735
662/* Try to find perf_probe_event with debuginfo */ 736/* Try to find perf_probe_event with debuginfo */
663static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 737static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
664 struct probe_trace_event **tevs) 738 struct probe_trace_event **tevs)
@@ -697,7 +771,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
697 771
698 if (ntevs > 0) { /* Succeeded to find trace events */ 772 if (ntevs > 0) { /* Succeeded to find trace events */
699 pr_debug("Found %d probe_trace_events.\n", ntevs); 773 pr_debug("Found %d probe_trace_events.\n", ntevs);
700 ret = post_process_probe_trace_events(*tevs, ntevs, 774 ret = post_process_probe_trace_events(pev, *tevs, ntevs,
701 pev->target, pev->uprobes); 775 pev->target, pev->uprobes);
702 if (ret < 0 || ret == ntevs) { 776 if (ret < 0 || ret == ntevs) {
703 clear_probe_trace_events(*tevs, ntevs); 777 clear_probe_trace_events(*tevs, ntevs);
@@ -754,7 +828,7 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
754error: 828error:
755 if (ferror(fp)) { 829 if (ferror(fp)) {
756 pr_warning("File read error: %s\n", 830 pr_warning("File read error: %s\n",
757 strerror_r(errno, sbuf, sizeof(sbuf))); 831 str_error_r(errno, sbuf, sizeof(sbuf)));
758 return -1; 832 return -1;
759 } 833 }
760 return 0; 834 return 0;
@@ -834,7 +908,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
834 fp = fopen(lr->path, "r"); 908 fp = fopen(lr->path, "r");
835 if (fp == NULL) { 909 if (fp == NULL) {
836 pr_warning("Failed to open %s: %s\n", lr->path, 910 pr_warning("Failed to open %s: %s\n", lr->path,
837 strerror_r(errno, sbuf, sizeof(sbuf))); 911 str_error_r(errno, sbuf, sizeof(sbuf)));
838 return -errno; 912 return -errno;
839 } 913 }
840 /* Skip to starting line number */ 914 /* Skip to starting line number */
@@ -844,7 +918,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
844 goto end; 918 goto end;
845 } 919 }
846 920
847 intlist__for_each(ln, lr->line_list) { 921 intlist__for_each_entry(ln, lr->line_list) {
848 for (; ln->i > l; l++) { 922 for (; ln->i > l; l++) {
849 ret = show_one_line(fp, l - lr->offset); 923 ret = show_one_line(fp, l - lr->offset);
850 if (ret < 0) 924 if (ret < 0)
@@ -928,7 +1002,7 @@ static int show_available_vars_at(struct debuginfo *dinfo,
928 zfree(&vl->point.symbol); 1002 zfree(&vl->point.symbol);
929 nvars = 0; 1003 nvars = 0;
930 if (vl->vars) { 1004 if (vl->vars) {
931 strlist__for_each(node, vl->vars) { 1005 strlist__for_each_entry(node, vl->vars) {
932 var = strchr(node->s, '\t') + 1; 1006 var = strchr(node->s, '\t') + 1;
933 if (strfilter__compare(_filter, var)) { 1007 if (strfilter__compare(_filter, var)) {
934 fprintf(stdout, "\t\t%s\n", node->s); 1008 fprintf(stdout, "\t\t%s\n", node->s);
@@ -1145,6 +1219,34 @@ err:
1145 return err; 1219 return err;
1146} 1220}
1147 1221
1222static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
1223{
1224 char *ptr;
1225
1226 ptr = strchr(*arg, ':');
1227 if (ptr) {
1228 *ptr = '\0';
1229 if (!pev->sdt && !is_c_func_name(*arg))
1230 goto ng_name;
1231 pev->group = strdup(*arg);
1232 if (!pev->group)
1233 return -ENOMEM;
1234 *arg = ptr + 1;
1235 } else
1236 pev->group = NULL;
1237 if (!pev->sdt && !is_c_func_name(*arg)) {
1238ng_name:
1239 semantic_error("%s is bad for event name -it must "
1240 "follow C symbol-naming rule.\n", *arg);
1241 return -EINVAL;
1242 }
1243 pev->event = strdup(*arg);
1244 if (pev->event == NULL)
1245 return -ENOMEM;
1246
1247 return 0;
1248}
1249
1148/* Parse probepoint definition. */ 1250/* Parse probepoint definition. */
1149static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 1251static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1150{ 1252{
@@ -1152,33 +1254,64 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1152 char *ptr, *tmp; 1254 char *ptr, *tmp;
1153 char c, nc = 0; 1255 char c, nc = 0;
1154 bool file_spec = false; 1256 bool file_spec = false;
1257 int ret;
1258
1155 /* 1259 /*
1156 * <Syntax> 1260 * <Syntax>
1157 * perf probe [EVENT=]SRC[:LN|;PTN] 1261 * perf probe [GRP:][EVENT=]SRC[:LN|;PTN]
1158 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 1262 * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
1159 * 1263 * perf probe %[GRP:]SDT_EVENT
1160 * TODO:Group name support
1161 */ 1264 */
1162 if (!arg) 1265 if (!arg)
1163 return -EINVAL; 1266 return -EINVAL;
1164 1267
1268 /*
1269 * If the probe point starts with '%',
1270 * or starts with "sdt_" and has a ':' but no '=',
1271 * then it should be a SDT/cached probe point.
1272 */
1273 if (arg[0] == '%' ||
1274 (!strncmp(arg, "sdt_", 4) &&
1275 !!strchr(arg, ':') && !strchr(arg, '='))) {
1276 pev->sdt = true;
1277 if (arg[0] == '%')
1278 arg++;
1279 }
1280
1165 ptr = strpbrk(arg, ";=@+%"); 1281 ptr = strpbrk(arg, ";=@+%");
1282 if (pev->sdt) {
1283 if (ptr) {
1284 if (*ptr != '@') {
1285 semantic_error("%s must be an SDT name.\n",
1286 arg);
1287 return -EINVAL;
1288 }
1289 /* This must be a target file name or build id */
1290 tmp = build_id_cache__complement(ptr + 1);
1291 if (tmp) {
1292 pev->target = build_id_cache__origname(tmp);
1293 free(tmp);
1294 } else
1295 pev->target = strdup(ptr + 1);
1296 if (!pev->target)
1297 return -ENOMEM;
1298 *ptr = '\0';
1299 }
1300 ret = parse_perf_probe_event_name(&arg, pev);
1301 if (ret == 0) {
1302 if (asprintf(&pev->point.function, "%%%s", pev->event) < 0)
1303 ret = -errno;
1304 }
1305 return ret;
1306 }
1307
1166 if (ptr && *ptr == '=') { /* Event name */ 1308 if (ptr && *ptr == '=') { /* Event name */
1167 *ptr = '\0'; 1309 *ptr = '\0';
1168 tmp = ptr + 1; 1310 tmp = ptr + 1;
1169 if (strchr(arg, ':')) { 1311 ret = parse_perf_probe_event_name(&arg, pev);
1170 semantic_error("Group name is not supported yet.\n"); 1312 if (ret < 0)
1171 return -ENOTSUP; 1313 return ret;
1172 } 1314
1173 if (!is_c_func_name(arg)) {
1174 semantic_error("%s is bad for event name -it must "
1175 "follow C symbol-naming rule.\n", arg);
1176 return -EINVAL;
1177 }
1178 pev->event = strdup(arg);
1179 if (pev->event == NULL)
1180 return -ENOMEM;
1181 pev->group = NULL;
1182 arg = tmp; 1315 arg = tmp;
1183 } 1316 }
1184 1317
@@ -1490,7 +1623,9 @@ bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
1490 return true; 1623 return true;
1491 1624
1492 for (i = 0; i < pev->nargs; i++) 1625 for (i = 0; i < pev->nargs; i++)
1493 if (is_c_varname(pev->args[i].var)) 1626 if (is_c_varname(pev->args[i].var) ||
1627 !strcmp(pev->args[i].var, "$params") ||
1628 !strcmp(pev->args[i].var, "$vars"))
1494 return true; 1629 return true;
1495 1630
1496 return false; 1631 return false;
@@ -1548,6 +1683,11 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
1548 p = strchr(argv[1], ':'); 1683 p = strchr(argv[1], ':');
1549 if (p) { 1684 if (p) {
1550 tp->module = strndup(argv[1], p - argv[1]); 1685 tp->module = strndup(argv[1], p - argv[1]);
1686 if (!tp->module) {
1687 ret = -ENOMEM;
1688 goto out;
1689 }
1690 tev->uprobes = (tp->module[0] == '/');
1551 p++; 1691 p++;
1552 } else 1692 } else
1553 p = argv[1]; 1693 p = argv[1];
@@ -1618,69 +1758,65 @@ out:
1618} 1758}
1619 1759
1620/* Compose only probe arg */ 1760/* Compose only probe arg */
1621int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len) 1761char *synthesize_perf_probe_arg(struct perf_probe_arg *pa)
1622{ 1762{
1623 struct perf_probe_arg_field *field = pa->field; 1763 struct perf_probe_arg_field *field = pa->field;
1624 int ret; 1764 struct strbuf buf;
1625 char *tmp = buf; 1765 char *ret = NULL;
1766 int err;
1767
1768 if (strbuf_init(&buf, 64) < 0)
1769 return NULL;
1626 1770
1627 if (pa->name && pa->var) 1771 if (pa->name && pa->var)
1628 ret = e_snprintf(tmp, len, "%s=%s", pa->name, pa->var); 1772 err = strbuf_addf(&buf, "%s=%s", pa->name, pa->var);
1629 else 1773 else
1630 ret = e_snprintf(tmp, len, "%s", pa->name ? pa->name : pa->var); 1774 err = strbuf_addstr(&buf, pa->name ?: pa->var);
1631 if (ret <= 0) 1775 if (err)
1632 goto error; 1776 goto out;
1633 tmp += ret;
1634 len -= ret;
1635 1777
1636 while (field) { 1778 while (field) {
1637 if (field->name[0] == '[') 1779 if (field->name[0] == '[')
1638 ret = e_snprintf(tmp, len, "%s", field->name); 1780 err = strbuf_addstr(&buf, field->name);
1639 else 1781 else
1640 ret = e_snprintf(tmp, len, "%s%s", 1782 err = strbuf_addf(&buf, "%s%s", field->ref ? "->" : ".",
1641 field->ref ? "->" : ".", field->name); 1783 field->name);
1642 if (ret <= 0)
1643 goto error;
1644 tmp += ret;
1645 len -= ret;
1646 field = field->next; 1784 field = field->next;
1785 if (err)
1786 goto out;
1647 } 1787 }
1648 1788
1649 if (pa->type) { 1789 if (pa->type)
1650 ret = e_snprintf(tmp, len, ":%s", pa->type); 1790 if (strbuf_addf(&buf, ":%s", pa->type) < 0)
1651 if (ret <= 0) 1791 goto out;
1652 goto error;
1653 tmp += ret;
1654 len -= ret;
1655 }
1656 1792
1657 return tmp - buf; 1793 ret = strbuf_detach(&buf, NULL);
1658error: 1794out:
1659 pr_debug("Failed to synthesize perf probe argument: %d\n", ret); 1795 strbuf_release(&buf);
1660 return ret; 1796 return ret;
1661} 1797}
1662 1798
1663/* Compose only probe point (not argument) */ 1799/* Compose only probe point (not argument) */
1664static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 1800char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1665{ 1801{
1666 char *buf, *tmp; 1802 struct strbuf buf;
1667 char offs[32] = "", line[32] = "", file[32] = ""; 1803 char *tmp, *ret = NULL;
1668 int ret, len; 1804 int len, err = 0;
1669 1805
1670 buf = zalloc(MAX_CMDLEN); 1806 if (strbuf_init(&buf, 64) < 0)
1671 if (buf == NULL) { 1807 return NULL;
1672 ret = -ENOMEM; 1808
1673 goto error; 1809 if (pp->function) {
1674 } 1810 if (strbuf_addstr(&buf, pp->function) < 0)
1675 if (pp->offset) { 1811 goto out;
1676 ret = e_snprintf(offs, 32, "+%lu", pp->offset); 1812 if (pp->offset)
1677 if (ret <= 0) 1813 err = strbuf_addf(&buf, "+%lu", pp->offset);
1678 goto error; 1814 else if (pp->line)
1679 } 1815 err = strbuf_addf(&buf, ":%d", pp->line);
1680 if (pp->line) { 1816 else if (pp->retprobe)
1681 ret = e_snprintf(line, 32, ":%d", pp->line); 1817 err = strbuf_addstr(&buf, "%return");
1682 if (ret <= 0) 1818 if (err)
1683 goto error; 1819 goto out;
1684 } 1820 }
1685 if (pp->file) { 1821 if (pp->file) {
1686 tmp = pp->file; 1822 tmp = pp->file;
@@ -1689,92 +1825,75 @@ static char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1689 tmp = strchr(pp->file + len - 30, '/'); 1825 tmp = strchr(pp->file + len - 30, '/');
1690 tmp = tmp ? tmp + 1 : pp->file + len - 30; 1826 tmp = tmp ? tmp + 1 : pp->file + len - 30;
1691 } 1827 }
1692 ret = e_snprintf(file, 32, "@%s", tmp); 1828 err = strbuf_addf(&buf, "@%s", tmp);
1693 if (ret <= 0) 1829 if (!err && !pp->function && pp->line)
1694 goto error; 1830 err = strbuf_addf(&buf, ":%d", pp->line);
1695 } 1831 }
1696 1832 if (!err)
1697 if (pp->function) 1833 ret = strbuf_detach(&buf, NULL);
1698 ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s%s", pp->function, 1834out:
1699 offs, pp->retprobe ? "%return" : "", line, 1835 strbuf_release(&buf);
1700 file); 1836 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} 1837}
1712 1838
1713#if 0
1714char *synthesize_perf_probe_command(struct perf_probe_event *pev) 1839char *synthesize_perf_probe_command(struct perf_probe_event *pev)
1715{ 1840{
1716 char *buf; 1841 struct strbuf buf;
1717 int i, len, ret; 1842 char *tmp, *ret = NULL;
1843 int i;
1718 1844
1719 buf = synthesize_perf_probe_point(&pev->point); 1845 if (strbuf_init(&buf, 64))
1720 if (!buf)
1721 return NULL; 1846 return NULL;
1847 if (pev->event)
1848 if (strbuf_addf(&buf, "%s:%s=", pev->group ?: PERFPROBE_GROUP,
1849 pev->event) < 0)
1850 goto out;
1851
1852 tmp = synthesize_perf_probe_point(&pev->point);
1853 if (!tmp || strbuf_addstr(&buf, tmp) < 0)
1854 goto out;
1855 free(tmp);
1722 1856
1723 len = strlen(buf);
1724 for (i = 0; i < pev->nargs; i++) { 1857 for (i = 0; i < pev->nargs; i++) {
1725 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 1858 tmp = synthesize_perf_probe_arg(pev->args + i);
1726 pev->args[i].name); 1859 if (!tmp || strbuf_addf(&buf, " %s", tmp) < 0)
1727 if (ret <= 0) { 1860 goto out;
1728 free(buf); 1861 free(tmp);
1729 return NULL;
1730 }
1731 len += ret;
1732 } 1862 }
1733 1863
1734 return buf; 1864 ret = strbuf_detach(&buf, NULL);
1865out:
1866 strbuf_release(&buf);
1867 return ret;
1735} 1868}
1736#endif
1737 1869
1738static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 1870static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1739 char **buf, size_t *buflen, 1871 struct strbuf *buf, int depth)
1740 int depth)
1741{ 1872{
1742 int ret; 1873 int err;
1743 if (ref->next) { 1874 if (ref->next) {
1744 depth = __synthesize_probe_trace_arg_ref(ref->next, buf, 1875 depth = __synthesize_probe_trace_arg_ref(ref->next, buf,
1745 buflen, depth + 1); 1876 depth + 1);
1746 if (depth < 0) 1877 if (depth < 0)
1747 goto out; 1878 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 } 1879 }
1757out: 1880 err = strbuf_addf(buf, "%+ld(", ref->offset);
1758 return depth; 1881 return (err < 0) ? err : depth;
1759
1760} 1882}
1761 1883
1762static int synthesize_probe_trace_arg(struct probe_trace_arg *arg, 1884static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1763 char *buf, size_t buflen) 1885 struct strbuf *buf)
1764{ 1886{
1765 struct probe_trace_arg_ref *ref = arg->ref; 1887 struct probe_trace_arg_ref *ref = arg->ref;
1766 int ret, depth = 0; 1888 int depth = 0, err;
1767 char *tmp = buf;
1768 1889
1769 /* Argument name or separator */ 1890 /* Argument name or separator */
1770 if (arg->name) 1891 if (arg->name)
1771 ret = e_snprintf(buf, buflen, " %s=", arg->name); 1892 err = strbuf_addf(buf, " %s=", arg->name);
1772 else 1893 else
1773 ret = e_snprintf(buf, buflen, " "); 1894 err = strbuf_addch(buf, ' ');
1774 if (ret < 0) 1895 if (err)
1775 return ret; 1896 return err;
1776 buf += ret;
1777 buflen -= ret;
1778 1897
1779 /* Special case: @XXX */ 1898 /* Special case: @XXX */
1780 if (arg->value[0] == '@' && arg->ref) 1899 if (arg->value[0] == '@' && arg->ref)
@@ -1782,59 +1901,44 @@ static int synthesize_probe_trace_arg(struct probe_trace_arg *arg,
1782 1901
1783 /* Dereferencing arguments */ 1902 /* Dereferencing arguments */
1784 if (ref) { 1903 if (ref) {
1785 depth = __synthesize_probe_trace_arg_ref(ref, &buf, 1904 depth = __synthesize_probe_trace_arg_ref(ref, buf, 1);
1786 &buflen, 1);
1787 if (depth < 0) 1905 if (depth < 0)
1788 return depth; 1906 return depth;
1789 } 1907 }
1790 1908
1791 /* Print argument value */ 1909 /* Print argument value */
1792 if (arg->value[0] == '@' && arg->ref) 1910 if (arg->value[0] == '@' && arg->ref)
1793 ret = e_snprintf(buf, buflen, "%s%+ld", arg->value, 1911 err = strbuf_addf(buf, "%s%+ld", arg->value, arg->ref->offset);
1794 arg->ref->offset);
1795 else 1912 else
1796 ret = e_snprintf(buf, buflen, "%s", arg->value); 1913 err = strbuf_addstr(buf, arg->value);
1797 if (ret < 0)
1798 return ret;
1799 buf += ret;
1800 buflen -= ret;
1801 1914
1802 /* Closing */ 1915 /* Closing */
1803 while (depth--) { 1916 while (!err && depth--)
1804 ret = e_snprintf(buf, buflen, ")"); 1917 err = strbuf_addch(buf, ')');
1805 if (ret < 0) 1918
1806 return ret;
1807 buf += ret;
1808 buflen -= ret;
1809 }
1810 /* Print argument type */ 1919 /* Print argument type */
1811 if (arg->type) { 1920 if (!err && arg->type)
1812 ret = e_snprintf(buf, buflen, ":%s", arg->type); 1921 err = strbuf_addf(buf, ":%s", arg->type);
1813 if (ret <= 0)
1814 return ret;
1815 buf += ret;
1816 }
1817 1922
1818 return buf - tmp; 1923 return err;
1819} 1924}
1820 1925
1821char *synthesize_probe_trace_command(struct probe_trace_event *tev) 1926char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1822{ 1927{
1823 struct probe_trace_point *tp = &tev->point; 1928 struct probe_trace_point *tp = &tev->point;
1824 char *buf; 1929 struct strbuf buf;
1825 int i, len, ret; 1930 char *ret = NULL;
1931 int i, err;
1826 1932
1827 buf = zalloc(MAX_CMDLEN); 1933 /* Uprobes must have tp->module */
1828 if (buf == NULL) 1934 if (tev->uprobes && !tp->module)
1829 return NULL; 1935 return NULL;
1830 1936
1831 len = e_snprintf(buf, MAX_CMDLEN, "%c:%s/%s ", tp->retprobe ? 'r' : 'p', 1937 if (strbuf_init(&buf, 32) < 0)
1832 tev->group, tev->event); 1938 return NULL;
1833 if (len <= 0)
1834 goto error;
1835 1939
1836 /* Uprobes must have tp->module */ 1940 if (strbuf_addf(&buf, "%c:%s/%s ", tp->retprobe ? 'r' : 'p',
1837 if (tev->uprobes && !tp->module) 1941 tev->group, tev->event) < 0)
1838 goto error; 1942 goto error;
1839 /* 1943 /*
1840 * If tp->address == 0, then this point must be a 1944 * If tp->address == 0, then this point must be a
@@ -1849,34 +1953,25 @@ char *synthesize_probe_trace_command(struct probe_trace_event *tev)
1849 1953
1850 /* Use the tp->address for uprobes */ 1954 /* Use the tp->address for uprobes */
1851 if (tev->uprobes) 1955 if (tev->uprobes)
1852 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s:0x%lx", 1956 err = strbuf_addf(&buf, "%s:0x%lx", tp->module, tp->address);
1853 tp->module, tp->address);
1854 else if (!strncmp(tp->symbol, "0x", 2)) 1957 else if (!strncmp(tp->symbol, "0x", 2))
1855 /* Absolute address. See try_to_find_absolute_address() */ 1958 /* Absolute address. See try_to_find_absolute_address() */
1856 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s0x%lx", 1959 err = strbuf_addf(&buf, "%s%s0x%lx", tp->module ?: "",
1857 tp->module ?: "", tp->module ? ":" : "", 1960 tp->module ? ":" : "", tp->address);
1858 tp->address);
1859 else 1961 else
1860 ret = e_snprintf(buf + len, MAX_CMDLEN - len, "%s%s%s+%lu", 1962 err = strbuf_addf(&buf, "%s%s%s+%lu", tp->module ?: "",
1861 tp->module ?: "", tp->module ? ":" : "", 1963 tp->module ? ":" : "", tp->symbol, tp->offset);
1862 tp->symbol, tp->offset); 1964 if (err)
1863
1864 if (ret <= 0)
1865 goto error; 1965 goto error;
1866 len += ret;
1867 1966
1868 for (i = 0; i < tev->nargs; i++) { 1967 for (i = 0; i < tev->nargs; i++)
1869 ret = synthesize_probe_trace_arg(&tev->args[i], buf + len, 1968 if (synthesize_probe_trace_arg(&tev->args[i], &buf) < 0)
1870 MAX_CMDLEN - len);
1871 if (ret <= 0)
1872 goto error; 1969 goto error;
1873 len += ret;
1874 }
1875 1970
1876 return buf; 1971 ret = strbuf_detach(&buf, NULL);
1877error: 1972error:
1878 free(buf); 1973 strbuf_release(&buf);
1879 return NULL; 1974 return ret;
1880} 1975}
1881 1976
1882static int find_perf_probe_point_from_map(struct probe_trace_point *tp, 1977static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
@@ -1958,7 +2053,7 @@ static int convert_to_perf_probe_point(struct probe_trace_point *tp,
1958static int convert_to_perf_probe_event(struct probe_trace_event *tev, 2053static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1959 struct perf_probe_event *pev, bool is_kprobe) 2054 struct perf_probe_event *pev, bool is_kprobe)
1960{ 2055{
1961 char buf[64] = ""; 2056 struct strbuf buf = STRBUF_INIT;
1962 int i, ret; 2057 int i, ret;
1963 2058
1964 /* Convert event/group name */ 2059 /* Convert event/group name */
@@ -1981,14 +2076,15 @@ static int convert_to_perf_probe_event(struct probe_trace_event *tev,
1981 if (tev->args[i].name) 2076 if (tev->args[i].name)
1982 pev->args[i].name = strdup(tev->args[i].name); 2077 pev->args[i].name = strdup(tev->args[i].name);
1983 else { 2078 else {
1984 ret = synthesize_probe_trace_arg(&tev->args[i], 2079 if ((ret = strbuf_init(&buf, 32)) < 0)
1985 buf, 64); 2080 goto error;
1986 pev->args[i].name = strdup(buf); 2081 ret = synthesize_probe_trace_arg(&tev->args[i], &buf);
2082 pev->args[i].name = strbuf_detach(&buf, NULL);
1987 } 2083 }
1988 if (pev->args[i].name == NULL && ret >= 0) 2084 if (pev->args[i].name == NULL && ret >= 0)
1989 ret = -ENOMEM; 2085 ret = -ENOMEM;
1990 } 2086 }
1991 2087error:
1992 if (ret < 0) 2088 if (ret < 0)
1993 clear_perf_probe_event(pev); 2089 clear_perf_probe_event(pev);
1994 2090
@@ -2021,6 +2117,79 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
2021 memset(pev, 0, sizeof(*pev)); 2117 memset(pev, 0, sizeof(*pev));
2022} 2118}
2023 2119
2120#define strdup_or_goto(str, label) \
2121({ char *__p = NULL; if (str && !(__p = strdup(str))) goto label; __p; })
2122
2123static int perf_probe_point__copy(struct perf_probe_point *dst,
2124 struct perf_probe_point *src)
2125{
2126 dst->file = strdup_or_goto(src->file, out_err);
2127 dst->function = strdup_or_goto(src->function, out_err);
2128 dst->lazy_line = strdup_or_goto(src->lazy_line, out_err);
2129 dst->line = src->line;
2130 dst->retprobe = src->retprobe;
2131 dst->offset = src->offset;
2132 return 0;
2133
2134out_err:
2135 clear_perf_probe_point(dst);
2136 return -ENOMEM;
2137}
2138
2139static int perf_probe_arg__copy(struct perf_probe_arg *dst,
2140 struct perf_probe_arg *src)
2141{
2142 struct perf_probe_arg_field *field, **ppfield;
2143
2144 dst->name = strdup_or_goto(src->name, out_err);
2145 dst->var = strdup_or_goto(src->var, out_err);
2146 dst->type = strdup_or_goto(src->type, out_err);
2147
2148 field = src->field;
2149 ppfield = &(dst->field);
2150 while (field) {
2151 *ppfield = zalloc(sizeof(*field));
2152 if (!*ppfield)
2153 goto out_err;
2154 (*ppfield)->name = strdup_or_goto(field->name, out_err);
2155 (*ppfield)->index = field->index;
2156 (*ppfield)->ref = field->ref;
2157 field = field->next;
2158 ppfield = &((*ppfield)->next);
2159 }
2160 return 0;
2161out_err:
2162 return -ENOMEM;
2163}
2164
2165int perf_probe_event__copy(struct perf_probe_event *dst,
2166 struct perf_probe_event *src)
2167{
2168 int i;
2169
2170 dst->event = strdup_or_goto(src->event, out_err);
2171 dst->group = strdup_or_goto(src->group, out_err);
2172 dst->target = strdup_or_goto(src->target, out_err);
2173 dst->uprobes = src->uprobes;
2174
2175 if (perf_probe_point__copy(&dst->point, &src->point) < 0)
2176 goto out_err;
2177
2178 dst->args = zalloc(sizeof(struct perf_probe_arg) * src->nargs);
2179 if (!dst->args)
2180 goto out_err;
2181 dst->nargs = src->nargs;
2182
2183 for (i = 0; i < src->nargs; i++)
2184 if (perf_probe_arg__copy(&dst->args[i], &src->args[i]) < 0)
2185 goto out_err;
2186 return 0;
2187
2188out_err:
2189 clear_perf_probe_event(dst);
2190 return -ENOMEM;
2191}
2192
2024void clear_probe_trace_event(struct probe_trace_event *tev) 2193void clear_probe_trace_event(struct probe_trace_event *tev)
2025{ 2194{
2026 struct probe_trace_arg_ref *ref, *next; 2195 struct probe_trace_arg_ref *ref, *next;
@@ -2162,35 +2331,38 @@ static int perf_probe_event__sprintf(const char *group, const char *event,
2162 struct strbuf *result) 2331 struct strbuf *result)
2163{ 2332{
2164 int i, ret; 2333 int i, ret;
2165 char buf[128]; 2334 char *buf;
2166 char *place;
2167 2335
2168 /* Synthesize only event probe point */ 2336 if (asprintf(&buf, "%s:%s", group, event) < 0)
2169 place = synthesize_perf_probe_point(&pev->point); 2337 return -errno;
2170 if (!place) 2338 ret = strbuf_addf(result, " %-20s (on ", buf);
2171 return -EINVAL; 2339 free(buf);
2340 if (ret)
2341 return ret;
2172 2342
2173 ret = e_snprintf(buf, 128, "%s:%s", group, event); 2343 /* Synthesize only event probe point */
2174 if (ret < 0) 2344 buf = synthesize_perf_probe_point(&pev->point);
2175 goto out; 2345 if (!buf)
2346 return -ENOMEM;
2347 ret = strbuf_addstr(result, buf);
2348 free(buf);
2176 2349
2177 strbuf_addf(result, " %-20s (on %s", buf, place); 2350 if (!ret && module)
2178 if (module) 2351 ret = strbuf_addf(result, " in %s", module);
2179 strbuf_addf(result, " in %s", module);
2180 2352
2181 if (pev->nargs > 0) { 2353 if (!ret && pev->nargs > 0) {
2182 strbuf_add(result, " with", 5); 2354 ret = strbuf_add(result, " with", 5);
2183 for (i = 0; i < pev->nargs; i++) { 2355 for (i = 0; !ret && i < pev->nargs; i++) {
2184 ret = synthesize_perf_probe_arg(&pev->args[i], 2356 buf = synthesize_perf_probe_arg(&pev->args[i]);
2185 buf, 128); 2357 if (!buf)
2186 if (ret < 0) 2358 return -ENOMEM;
2187 goto out; 2359 ret = strbuf_addf(result, " %s", buf);
2188 strbuf_addf(result, " %s", buf); 2360 free(buf);
2189 } 2361 }
2190 } 2362 }
2191 strbuf_addch(result, ')'); 2363 if (!ret)
2192out: 2364 ret = strbuf_addch(result, ')');
2193 free(place); 2365
2194 return ret; 2366 return ret;
2195} 2367}
2196 2368
@@ -2245,7 +2417,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe,
2245 if (!rawlist) 2417 if (!rawlist)
2246 return -ENOMEM; 2418 return -ENOMEM;
2247 2419
2248 strlist__for_each(ent, rawlist) { 2420 strlist__for_each_entry(ent, rawlist) {
2249 ret = parse_probe_trace_command(ent->s, &tev); 2421 ret = parse_probe_trace_command(ent->s, &tev);
2250 if (ret >= 0) { 2422 if (ret >= 0) {
2251 if (!filter_probe_trace_event(&tev, filter)) 2423 if (!filter_probe_trace_event(&tev, filter))
@@ -2278,6 +2450,9 @@ int show_perf_probe_events(struct strfilter *filter)
2278 2450
2279 setup_pager(); 2451 setup_pager();
2280 2452
2453 if (probe_conf.cache)
2454 return probe_cache__show_all_caches(filter);
2455
2281 ret = init_probe_symbol_maps(false); 2456 ret = init_probe_symbol_maps(false);
2282 if (ret < 0) 2457 if (ret < 0)
2283 return ret; 2458 return ret;
@@ -2386,17 +2561,24 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
2386 char buf[64]; 2561 char buf[64];
2387 int ret; 2562 int ret;
2388 2563
2389 if (pev->event) 2564 /* If probe_event or trace_event already have the name, reuse it */
2565 if (pev->event && !pev->sdt)
2390 event = pev->event; 2566 event = pev->event;
2391 else 2567 else if (tev->event)
2568 event = tev->event;
2569 else {
2570 /* Or generate new one from probe point */
2392 if (pev->point.function && 2571 if (pev->point.function &&
2393 (strncmp(pev->point.function, "0x", 2) != 0) && 2572 (strncmp(pev->point.function, "0x", 2) != 0) &&
2394 !strisglob(pev->point.function)) 2573 !strisglob(pev->point.function))
2395 event = pev->point.function; 2574 event = pev->point.function;
2396 else 2575 else
2397 event = tev->point.realname; 2576 event = tev->point.realname;
2398 if (pev->group) 2577 }
2578 if (pev->group && !pev->sdt)
2399 group = pev->group; 2579 group = pev->group;
2580 else if (tev->group)
2581 group = tev->group;
2400 else 2582 else
2401 group = PERFPROBE_GROUP; 2583 group = PERFPROBE_GROUP;
2402 2584
@@ -2418,40 +2600,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
2418 return 0; 2600 return 0;
2419} 2601}
2420 2602
2421static int __add_probe_trace_events(struct perf_probe_event *pev, 2603static int __open_probe_file_and_namelist(bool uprobe,
2422 struct probe_trace_event *tevs, 2604 struct strlist **namelist)
2423 int ntevs, bool allow_suffix)
2424{ 2605{
2425 int i, fd, ret; 2606 int fd;
2426 struct probe_trace_event *tev = NULL;
2427 struct strlist *namelist;
2428 2607
2429 fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); 2608 fd = probe_file__open(PF_FL_RW | (uprobe ? PF_FL_UPROBE : 0));
2430 if (fd < 0) 2609 if (fd < 0)
2431 return fd; 2610 return fd;
2432 2611
2433 /* Get current event names */ 2612 /* Get current event names */
2434 namelist = probe_file__get_namelist(fd); 2613 *namelist = probe_file__get_namelist(fd);
2435 if (!namelist) { 2614 if (!(*namelist)) {
2436 pr_debug("Failed to get current event list.\n"); 2615 pr_debug("Failed to get current event list.\n");
2437 ret = -ENOMEM; 2616 close(fd);
2438 goto close_out; 2617 return -ENOMEM;
2439 } 2618 }
2619 return fd;
2620}
2621
2622static int __add_probe_trace_events(struct perf_probe_event *pev,
2623 struct probe_trace_event *tevs,
2624 int ntevs, bool allow_suffix)
2625{
2626 int i, fd[2] = {-1, -1}, up, ret;
2627 struct probe_trace_event *tev = NULL;
2628 struct probe_cache *cache = NULL;
2629 struct strlist *namelist[2] = {NULL, NULL};
2630
2631 up = pev->uprobes ? 1 : 0;
2632 fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
2633 if (fd[up] < 0)
2634 return fd[up];
2440 2635
2441 ret = 0; 2636 ret = 0;
2442 for (i = 0; i < ntevs; i++) { 2637 for (i = 0; i < ntevs; i++) {
2443 tev = &tevs[i]; 2638 tev = &tevs[i];
2639 up = tev->uprobes ? 1 : 0;
2640 if (fd[up] == -1) { /* Open the kprobe/uprobe_events */
2641 fd[up] = __open_probe_file_and_namelist(up,
2642 &namelist[up]);
2643 if (fd[up] < 0)
2644 goto close_out;
2645 }
2444 /* Skip if the symbol is out of .text or blacklisted */ 2646 /* Skip if the symbol is out of .text or blacklisted */
2445 if (!tev->point.symbol) 2647 if (!tev->point.symbol && !pev->uprobes)
2446 continue; 2648 continue;
2447 2649
2448 /* Set new name for tev (and update namelist) */ 2650 /* Set new name for tev (and update namelist) */
2449 ret = probe_trace_event__set_name(tev, pev, namelist, 2651 ret = probe_trace_event__set_name(tev, pev, namelist[up],
2450 allow_suffix); 2652 allow_suffix);
2451 if (ret < 0) 2653 if (ret < 0)
2452 break; 2654 break;
2453 2655
2454 ret = probe_file__add_event(fd, tev); 2656 ret = probe_file__add_event(fd[up], tev);
2455 if (ret < 0) 2657 if (ret < 0)
2456 break; 2658 break;
2457 2659
@@ -2465,10 +2667,21 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2465 } 2667 }
2466 if (ret == -EINVAL && pev->uprobes) 2668 if (ret == -EINVAL && pev->uprobes)
2467 warn_uprobe_event_compat(tev); 2669 warn_uprobe_event_compat(tev);
2670 if (ret == 0 && probe_conf.cache) {
2671 cache = probe_cache__new(pev->target);
2672 if (!cache ||
2673 probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 ||
2674 probe_cache__commit(cache) < 0)
2675 pr_warning("Failed to add event to probe cache\n");
2676 probe_cache__delete(cache);
2677 }
2468 2678
2469 strlist__delete(namelist);
2470close_out: 2679close_out:
2471 close(fd); 2680 for (up = 0; up < 2; up++) {
2681 strlist__delete(namelist[up]);
2682 if (fd[up] >= 0)
2683 close(fd[up]);
2684 }
2472 return ret; 2685 return ret;
2473} 2686}
2474 2687
@@ -2493,12 +2706,10 @@ static int find_probe_functions(struct map *map, char *name,
2493 return found; 2706 return found;
2494} 2707}
2495 2708
2496#define strdup_or_goto(str, label) \
2497 ({ char *__p = strdup(str); if (!__p) goto label; __p; })
2498
2499void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused, 2709void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
2500 struct probe_trace_event *tev __maybe_unused, 2710 struct probe_trace_event *tev __maybe_unused,
2501 struct map *map __maybe_unused) { } 2711 struct map *map __maybe_unused,
2712 struct symbol *sym __maybe_unused) { }
2502 2713
2503/* 2714/*
2504 * Find probe function addresses from map. 2715 * Find probe function addresses from map.
@@ -2516,6 +2727,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2516 struct probe_trace_point *tp; 2727 struct probe_trace_point *tp;
2517 int num_matched_functions; 2728 int num_matched_functions;
2518 int ret, i, j, skipped = 0; 2729 int ret, i, j, skipped = 0;
2730 char *mod_name;
2519 2731
2520 map = get_target_map(pev->target, pev->uprobes); 2732 map = get_target_map(pev->target, pev->uprobes);
2521 if (!map) { 2733 if (!map) {
@@ -2600,9 +2812,19 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2600 tp->realname = strdup_or_goto(sym->name, nomem_out); 2812 tp->realname = strdup_or_goto(sym->name, nomem_out);
2601 2813
2602 tp->retprobe = pp->retprobe; 2814 tp->retprobe = pp->retprobe;
2603 if (pev->target) 2815 if (pev->target) {
2604 tev->point.module = strdup_or_goto(pev->target, 2816 if (pev->uprobes) {
2605 nomem_out); 2817 tev->point.module = strdup_or_goto(pev->target,
2818 nomem_out);
2819 } else {
2820 mod_name = find_module_name(pev->target);
2821 tev->point.module =
2822 strdup(mod_name ? mod_name : pev->target);
2823 free(mod_name);
2824 if (!tev->point.module)
2825 goto nomem_out;
2826 }
2827 }
2606 tev->uprobes = pev->uprobes; 2828 tev->uprobes = pev->uprobes;
2607 tev->nargs = pev->nargs; 2829 tev->nargs = pev->nargs;
2608 if (tev->nargs) { 2830 if (tev->nargs) {
@@ -2624,7 +2846,7 @@ static int find_probe_trace_events_from_map(struct perf_probe_event *pev,
2624 strdup_or_goto(pev->args[i].type, 2846 strdup_or_goto(pev->args[i].type,
2625 nomem_out); 2847 nomem_out);
2626 } 2848 }
2627 arch__fix_tev_from_maps(pev, tev, map); 2849 arch__fix_tev_from_maps(pev, tev, map, sym);
2628 } 2850 }
2629 if (ret == skipped) { 2851 if (ret == skipped) {
2630 ret = -ENOENT; 2852 ret = -ENOENT;
@@ -2736,16 +2958,211 @@ errout:
2736 return err; 2958 return err;
2737} 2959}
2738 2960
2739bool __weak arch__prefers_symtab(void) { return false; } 2961/* Concatinate two arrays */
2962static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b)
2963{
2964 void *ret;
2965
2966 ret = malloc(sz_a + sz_b);
2967 if (ret) {
2968 memcpy(ret, a, sz_a);
2969 memcpy(ret + sz_a, b, sz_b);
2970 }
2971 return ret;
2972}
2973
2974static int
2975concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
2976 struct probe_trace_event **tevs2, int ntevs2)
2977{
2978 struct probe_trace_event *new_tevs;
2979 int ret = 0;
2980
2981 if (ntevs == 0) {
2982 *tevs = *tevs2;
2983 *ntevs = ntevs2;
2984 *tevs2 = NULL;
2985 return 0;
2986 }
2987
2988 if (*ntevs + ntevs2 > probe_conf.max_probes)
2989 ret = -E2BIG;
2990 else {
2991 /* Concatinate the array of probe_trace_event */
2992 new_tevs = memcat(*tevs, (*ntevs) * sizeof(**tevs),
2993 *tevs2, ntevs2 * sizeof(**tevs2));
2994 if (!new_tevs)
2995 ret = -ENOMEM;
2996 else {
2997 free(*tevs);
2998 *tevs = new_tevs;
2999 *ntevs += ntevs2;
3000 }
3001 }
3002 if (ret < 0)
3003 clear_probe_trace_events(*tevs2, ntevs2);
3004 zfree(tevs2);
3005
3006 return ret;
3007}
3008
3009/*
3010 * Try to find probe_trace_event from given probe caches. Return the number
3011 * of cached events found, if an error occurs return the error.
3012 */
3013static int find_cached_events(struct perf_probe_event *pev,
3014 struct probe_trace_event **tevs,
3015 const char *target)
3016{
3017 struct probe_cache *cache;
3018 struct probe_cache_entry *entry;
3019 struct probe_trace_event *tmp_tevs = NULL;
3020 int ntevs = 0;
3021 int ret = 0;
3022
3023 cache = probe_cache__new(target);
3024 /* Return 0 ("not found") if the target has no probe cache. */
3025 if (!cache)
3026 return 0;
3027
3028 for_each_probe_cache_entry(entry, cache) {
3029 /* Skip the cache entry which has no name */
3030 if (!entry->pev.event || !entry->pev.group)
3031 continue;
3032 if ((!pev->group || strglobmatch(entry->pev.group, pev->group)) &&
3033 strglobmatch(entry->pev.event, pev->event)) {
3034 ret = probe_cache_entry__get_event(entry, &tmp_tevs);
3035 if (ret > 0)
3036 ret = concat_probe_trace_events(tevs, &ntevs,
3037 &tmp_tevs, ret);
3038 if (ret < 0)
3039 break;
3040 }
3041 }
3042 probe_cache__delete(cache);
3043 if (ret < 0) {
3044 clear_probe_trace_events(*tevs, ntevs);
3045 zfree(tevs);
3046 } else {
3047 ret = ntevs;
3048 if (ntevs > 0 && target && target[0] == '/')
3049 pev->uprobes = true;
3050 }
3051
3052 return ret;
3053}
3054
3055/* Try to find probe_trace_event from all probe caches */
3056static int find_cached_events_all(struct perf_probe_event *pev,
3057 struct probe_trace_event **tevs)
3058{
3059 struct probe_trace_event *tmp_tevs = NULL;
3060 struct strlist *bidlist;
3061 struct str_node *nd;
3062 char *pathname;
3063 int ntevs = 0;
3064 int ret;
3065
3066 /* Get the buildid list of all valid caches */
3067 bidlist = build_id_cache__list_all(true);
3068 if (!bidlist) {
3069 ret = -errno;
3070 pr_debug("Failed to get buildids: %d\n", ret);
3071 return ret;
3072 }
3073
3074 ret = 0;
3075 strlist__for_each_entry(nd, bidlist) {
3076 pathname = build_id_cache__origname(nd->s);
3077 ret = find_cached_events(pev, &tmp_tevs, pathname);
3078 /* In the case of cnt == 0, we just skip it */
3079 if (ret > 0)
3080 ret = concat_probe_trace_events(tevs, &ntevs,
3081 &tmp_tevs, ret);
3082 free(pathname);
3083 if (ret < 0)
3084 break;
3085 }
3086 strlist__delete(bidlist);
3087
3088 if (ret < 0) {
3089 clear_probe_trace_events(*tevs, ntevs);
3090 zfree(tevs);
3091 } else
3092 ret = ntevs;
3093
3094 return ret;
3095}
3096
3097static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
3098 struct probe_trace_event **tevs)
3099{
3100 struct probe_cache *cache;
3101 struct probe_cache_entry *entry;
3102 struct probe_trace_event *tev;
3103 struct str_node *node;
3104 int ret, i;
3105
3106 if (pev->sdt) {
3107 /* For SDT/cached events, we use special search functions */
3108 if (!pev->target)
3109 return find_cached_events_all(pev, tevs);
3110 else
3111 return find_cached_events(pev, tevs, pev->target);
3112 }
3113 cache = probe_cache__new(pev->target);
3114 if (!cache)
3115 return 0;
3116
3117 entry = probe_cache__find(cache, pev);
3118 if (!entry) {
3119 /* SDT must be in the cache */
3120 ret = pev->sdt ? -ENOENT : 0;
3121 goto out;
3122 }
3123
3124 ret = strlist__nr_entries(entry->tevlist);
3125 if (ret > probe_conf.max_probes) {
3126 pr_debug("Too many entries matched in the cache of %s\n",
3127 pev->target ? : "kernel");
3128 ret = -E2BIG;
3129 goto out;
3130 }
3131
3132 *tevs = zalloc(ret * sizeof(*tev));
3133 if (!*tevs) {
3134 ret = -ENOMEM;
3135 goto out;
3136 }
3137
3138 i = 0;
3139 strlist__for_each_entry(node, entry->tevlist) {
3140 tev = &(*tevs)[i++];
3141 ret = parse_probe_trace_command(node->s, tev);
3142 if (ret < 0)
3143 goto out;
3144 /* Set the uprobes attribute as same as original */
3145 tev->uprobes = pev->uprobes;
3146 }
3147 ret = i;
3148
3149out:
3150 probe_cache__delete(cache);
3151 return ret;
3152}
2740 3153
2741static int convert_to_probe_trace_events(struct perf_probe_event *pev, 3154static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2742 struct probe_trace_event **tevs) 3155 struct probe_trace_event **tevs)
2743{ 3156{
2744 int ret; 3157 int ret;
2745 3158
2746 if (pev->uprobes && !pev->group) { 3159 if (!pev->group && !pev->sdt) {
2747 /* Replace group name if not given */ 3160 /* Set group name if not given */
2748 ret = convert_exec_to_group(pev->target, &pev->group); 3161 if (!pev->uprobes) {
3162 pev->group = strdup(PERFPROBE_GROUP);
3163 ret = pev->group ? 0 : -ENOMEM;
3164 } else
3165 ret = convert_exec_to_group(pev->target, &pev->group);
2749 if (ret != 0) { 3166 if (ret != 0) {
2750 pr_warning("Failed to make a group name.\n"); 3167 pr_warning("Failed to make a group name.\n");
2751 return ret; 3168 return ret;
@@ -2756,11 +3173,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2756 if (ret > 0) 3173 if (ret > 0)
2757 return ret; 3174 return ret;
2758 3175
2759 if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { 3176 /* At first, we need to lookup cache entry */
2760 ret = find_probe_trace_events_from_map(pev, tevs); 3177 ret = find_probe_trace_events_from_cache(pev, tevs);
2761 if (ret > 0) 3178 if (ret > 0 || pev->sdt) /* SDT can be found only in the cache */
2762 return ret; /* Found in symbol table */ 3179 return ret == 0 ? -ENOENT : ret; /* Found in probe cache */
2763 }
2764 3180
2765 /* Convert perf_probe_event with debuginfo */ 3181 /* Convert perf_probe_event with debuginfo */
2766 ret = try_to_find_probe_trace_events(pev, tevs); 3182 ret = try_to_find_probe_trace_events(pev, tevs);
@@ -2910,8 +3326,16 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
2910 3326
2911 /* Load symbols with given filter */ 3327 /* Load symbols with given filter */
2912 available_func_filter = _filter; 3328 available_func_filter = _filter;
2913 if (map__load(map, filter_available_functions)) { 3329 ret = map__load(map, filter_available_functions);
2914 pr_err("Failed to load symbols in %s\n", (target) ? : "kernel"); 3330 if (ret) {
3331 if (ret == -2) {
3332 char *str = strfilter__string(_filter);
3333 pr_err("Failed to find symbols matched to \"%s\"\n",
3334 str);
3335 free(str);
3336 } else
3337 pr_err("Failed to load symbols in %s\n",
3338 (target) ? : "kernel");
2915 goto end; 3339 goto end;
2916 } 3340 }
2917 if (!dso__sorted_by_name(map->dso, map->type)) 3341 if (!dso__sorted_by_name(map->dso, map->type))
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e54e7b011577..f4f45db77c1c 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -12,6 +12,7 @@ struct probe_conf {
12 bool show_location_range; 12 bool show_location_range;
13 bool force_add; 13 bool force_add;
14 bool no_inlines; 14 bool no_inlines;
15 bool cache;
15 int max_probes; 16 int max_probes;
16}; 17};
17extern struct probe_conf probe_conf; 18extern struct probe_conf probe_conf;
@@ -84,6 +85,7 @@ struct perf_probe_event {
84 char *group; /* Group name */ 85 char *group; /* Group name */
85 struct perf_probe_point point; /* Probe point */ 86 struct perf_probe_point point; /* Probe point */
86 int nargs; /* Number of arguments */ 87 int nargs; /* Number of arguments */
88 bool sdt; /* SDT/cached event flag */
87 bool uprobes; /* Uprobe event flag */ 89 bool uprobes; /* Uprobe event flag */
88 char *target; /* Target binary */ 90 char *target; /* Target binary */
89 struct perf_probe_arg *args; /* Arguments */ 91 struct perf_probe_arg *args; /* Arguments */
@@ -120,7 +122,11 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev);
120/* Events to command string */ 122/* Events to command string */
121char *synthesize_perf_probe_command(struct perf_probe_event *pev); 123char *synthesize_perf_probe_command(struct perf_probe_event *pev);
122char *synthesize_probe_trace_command(struct probe_trace_event *tev); 124char *synthesize_probe_trace_command(struct probe_trace_event *tev);
123int synthesize_perf_probe_arg(struct perf_probe_arg *pa, char *buf, size_t len); 125char *synthesize_perf_probe_arg(struct perf_probe_arg *pa);
126char *synthesize_perf_probe_point(struct perf_probe_point *pp);
127
128int perf_probe_event__copy(struct perf_probe_event *dst,
129 struct perf_probe_event *src);
124 130
125/* Check the perf_probe_event needs debuginfo */ 131/* Check the perf_probe_event needs debuginfo */
126bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); 132bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
@@ -152,9 +158,9 @@ int show_line_range(struct line_range *lr, const char *module, bool user);
152int show_available_vars(struct perf_probe_event *pevs, int npevs, 158int show_available_vars(struct perf_probe_event *pevs, int npevs,
153 struct strfilter *filter); 159 struct strfilter *filter);
154int show_available_funcs(const char *module, struct strfilter *filter, bool user); 160int show_available_funcs(const char *module, struct strfilter *filter, bool user);
155bool arch__prefers_symtab(void);
156void arch__fix_tev_from_maps(struct perf_probe_event *pev, 161void arch__fix_tev_from_maps(struct perf_probe_event *pev,
157 struct probe_trace_event *tev, struct map *map); 162 struct probe_trace_event *tev, struct map *map,
163 struct symbol *sym);
158 164
159/* If there is no space to write, returns -E2BIG. */ 165/* If there is no space to write, returns -E2BIG. */
160int e_snprintf(char *str, size_t size, const char *format, ...) 166int e_snprintf(char *str, size_t size, const char *format, ...)
@@ -166,4 +172,9 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
166int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, 172int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
167 struct perf_probe_arg *pvar); 173 struct perf_probe_arg *pvar);
168 174
175struct map *get_target_map(const char *target, bool user);
176
177void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
178 int ntevs);
179
169#endif /*_PROBE_EVENT_H */ 180#endif /*_PROBE_EVENT_H */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index e3b3b92e4458..9c3b9ed5b3c3 100644
--- a/tools/perf/util/probe-file.c
+++ b/tools/perf/util/probe-file.c
@@ -14,6 +14,7 @@
14 * GNU General Public License for more details. 14 * GNU General Public License for more details.
15 * 15 *
16 */ 16 */
17#include <sys/uio.h>
17#include "util.h" 18#include "util.h"
18#include "event.h" 19#include "event.h"
19#include "strlist.h" 20#include "strlist.h"
@@ -49,7 +50,7 @@ static void print_open_warning(int err, bool uprobe)
49 else 50 else
50 pr_warning("Failed to open %cprobe_events: %s\n", 51 pr_warning("Failed to open %cprobe_events: %s\n",
51 uprobe ? 'u' : 'k', 52 uprobe ? 'u' : 'k',
52 strerror_r(-err, sbuf, sizeof(sbuf))); 53 str_error_r(-err, sbuf, sizeof(sbuf)));
53} 54}
54 55
55static void print_both_open_warning(int kerr, int uerr) 56static void print_both_open_warning(int kerr, int uerr)
@@ -63,9 +64,9 @@ static void print_both_open_warning(int kerr, int uerr)
63 else { 64 else {
64 char sbuf[STRERR_BUFSIZE]; 65 char sbuf[STRERR_BUFSIZE];
65 pr_warning("Failed to open kprobe events: %s.\n", 66 pr_warning("Failed to open kprobe events: %s.\n",
66 strerror_r(-kerr, sbuf, sizeof(sbuf))); 67 str_error_r(-kerr, sbuf, sizeof(sbuf)));
67 pr_warning("Failed to open uprobe events: %s.\n", 68 pr_warning("Failed to open uprobe events: %s.\n",
68 strerror_r(-uerr, sbuf, sizeof(sbuf))); 69 str_error_r(-uerr, sbuf, sizeof(sbuf)));
69 } 70 }
70} 71}
71 72
@@ -132,7 +133,7 @@ int probe_file__open_both(int *kfd, int *ufd, int flag)
132/* Get raw string list of current kprobe_events or uprobe_events */ 133/* Get raw string list of current kprobe_events or uprobe_events */
133struct strlist *probe_file__get_rawlist(int fd) 134struct strlist *probe_file__get_rawlist(int fd)
134{ 135{
135 int ret, idx; 136 int ret, idx, fddup;
136 FILE *fp; 137 FILE *fp;
137 char buf[MAX_CMDLEN]; 138 char buf[MAX_CMDLEN];
138 char *p; 139 char *p;
@@ -142,8 +143,17 @@ struct strlist *probe_file__get_rawlist(int fd)
142 return NULL; 143 return NULL;
143 144
144 sl = strlist__new(NULL, NULL); 145 sl = strlist__new(NULL, NULL);
146 if (sl == NULL)
147 return NULL;
148
149 fddup = dup(fd);
150 if (fddup < 0)
151 goto out_free_sl;
152
153 fp = fdopen(fddup, "r");
154 if (!fp)
155 goto out_close_fddup;
145 156
146 fp = fdopen(dup(fd), "r");
147 while (!feof(fp)) { 157 while (!feof(fp)) {
148 p = fgets(buf, MAX_CMDLEN, fp); 158 p = fgets(buf, MAX_CMDLEN, fp);
149 if (!p) 159 if (!p)
@@ -155,13 +165,21 @@ struct strlist *probe_file__get_rawlist(int fd)
155 ret = strlist__add(sl, buf); 165 ret = strlist__add(sl, buf);
156 if (ret < 0) { 166 if (ret < 0) {
157 pr_debug("strlist__add failed (%d)\n", ret); 167 pr_debug("strlist__add failed (%d)\n", ret);
158 strlist__delete(sl); 168 goto out_close_fp;
159 return NULL;
160 } 169 }
161 } 170 }
162 fclose(fp); 171 fclose(fp);
163 172
164 return sl; 173 return sl;
174
175out_close_fp:
176 fclose(fp);
177 goto out_free_sl;
178out_close_fddup:
179 close(fddup);
180out_free_sl:
181 strlist__delete(sl);
182 return NULL;
165} 183}
166 184
167static struct strlist *__probe_file__get_namelist(int fd, bool include_group) 185static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
@@ -177,7 +195,7 @@ static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
177 if (!rawlist) 195 if (!rawlist)
178 return NULL; 196 return NULL;
179 sl = strlist__new(NULL, NULL); 197 sl = strlist__new(NULL, NULL);
180 strlist__for_each(ent, rawlist) { 198 strlist__for_each_entry(ent, rawlist) {
181 ret = parse_probe_trace_command(ent->s, &tev); 199 ret = parse_probe_trace_command(ent->s, &tev);
182 if (ret < 0) 200 if (ret < 0)
183 break; 201 break;
@@ -220,11 +238,10 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev)
220 238
221 pr_debug("Writing event: %s\n", buf); 239 pr_debug("Writing event: %s\n", buf);
222 if (!probe_event_dry_run) { 240 if (!probe_event_dry_run) {
223 ret = write(fd, buf, strlen(buf)); 241 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
224 if (ret <= 0) {
225 ret = -errno; 242 ret = -errno;
226 pr_warning("Failed to write event: %s\n", 243 pr_warning("Failed to write event: %s\n",
227 strerror_r(errno, sbuf, sizeof(sbuf))); 244 str_error_r(errno, sbuf, sizeof(sbuf)));
228 } 245 }
229 } 246 }
230 free(buf); 247 free(buf);
@@ -262,7 +279,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
262 return 0; 279 return 0;
263error: 280error:
264 pr_warning("Failed to delete event: %s\n", 281 pr_warning("Failed to delete event: %s\n",
265 strerror_r(-ret, buf, sizeof(buf))); 282 str_error_r(-ret, buf, sizeof(buf)));
266 return ret; 283 return ret;
267} 284}
268 285
@@ -281,7 +298,7 @@ int probe_file__get_events(int fd, struct strfilter *filter,
281 if (!namelist) 298 if (!namelist)
282 return -ENOENT; 299 return -ENOENT;
283 300
284 strlist__for_each(ent, namelist) { 301 strlist__for_each_entry(ent, namelist) {
285 p = strchr(ent->s, ':'); 302 p = strchr(ent->s, ':');
286 if ((p && strfilter__compare(filter, p + 1)) || 303 if ((p && strfilter__compare(filter, p + 1)) ||
287 strfilter__compare(filter, ent->s)) { 304 strfilter__compare(filter, ent->s)) {
@@ -299,7 +316,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist)
299 int ret = 0; 316 int ret = 0;
300 struct str_node *ent; 317 struct str_node *ent;
301 318
302 strlist__for_each(ent, namelist) { 319 strlist__for_each_entry(ent, namelist) {
303 ret = __del_trace_probe_event(fd, ent); 320 ret = __del_trace_probe_event(fd, ent);
304 if (ret < 0) 321 if (ret < 0)
305 break; 322 break;
@@ -325,3 +342,538 @@ int probe_file__del_events(int fd, struct strfilter *filter)
325 342
326 return ret; 343 return ret;
327} 344}
345
346/* Caller must ensure to remove this entry from list */
347static void probe_cache_entry__delete(struct probe_cache_entry *entry)
348{
349 if (entry) {
350 BUG_ON(!list_empty(&entry->node));
351
352 strlist__delete(entry->tevlist);
353 clear_perf_probe_event(&entry->pev);
354 zfree(&entry->spev);
355 free(entry);
356 }
357}
358
359static struct probe_cache_entry *
360probe_cache_entry__new(struct perf_probe_event *pev)
361{
362 struct probe_cache_entry *entry = zalloc(sizeof(*entry));
363
364 if (entry) {
365 INIT_LIST_HEAD(&entry->node);
366 entry->tevlist = strlist__new(NULL, NULL);
367 if (!entry->tevlist)
368 zfree(&entry);
369 else if (pev) {
370 entry->spev = synthesize_perf_probe_command(pev);
371 if (!entry->spev ||
372 perf_probe_event__copy(&entry->pev, pev) < 0) {
373 probe_cache_entry__delete(entry);
374 return NULL;
375 }
376 }
377 }
378
379 return entry;
380}
381
382int probe_cache_entry__get_event(struct probe_cache_entry *entry,
383 struct probe_trace_event **tevs)
384{
385 struct probe_trace_event *tev;
386 struct str_node *node;
387 int ret, i;
388
389 ret = strlist__nr_entries(entry->tevlist);
390 if (ret > probe_conf.max_probes)
391 return -E2BIG;
392
393 *tevs = zalloc(ret * sizeof(*tev));
394 if (!*tevs)
395 return -ENOMEM;
396
397 i = 0;
398 strlist__for_each_entry(node, entry->tevlist) {
399 tev = &(*tevs)[i++];
400 ret = parse_probe_trace_command(node->s, tev);
401 if (ret < 0)
402 break;
403 }
404 return i;
405}
406
407/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
408static int probe_cache__open(struct probe_cache *pcache, const char *target)
409{
410 char cpath[PATH_MAX];
411 char sbuildid[SBUILD_ID_SIZE];
412 char *dir_name = NULL;
413 bool is_kallsyms = false;
414 int ret, fd;
415
416 if (target && build_id_cache__cached(target)) {
417 /* This is a cached buildid */
418 strncpy(sbuildid, target, SBUILD_ID_SIZE);
419 dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
420 goto found;
421 }
422
423 if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
424 target = DSO__NAME_KALLSYMS;
425 is_kallsyms = true;
426 ret = sysfs__sprintf_build_id("/", sbuildid);
427 } else
428 ret = filename__sprintf_build_id(target, sbuildid);
429
430 if (ret < 0) {
431 pr_debug("Failed to get build-id from %s.\n", target);
432 return ret;
433 }
434
435 /* If we have no buildid cache, make it */
436 if (!build_id_cache__cached(sbuildid)) {
437 ret = build_id_cache__add_s(sbuildid, target,
438 is_kallsyms, NULL);
439 if (ret < 0) {
440 pr_debug("Failed to add build-id cache: %s\n", target);
441 return ret;
442 }
443 }
444
445 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
446 false);
447found:
448 if (!dir_name) {
449 pr_debug("Failed to get cache from %s\n", target);
450 return -ENOMEM;
451 }
452
453 snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
454 fd = open(cpath, O_CREAT | O_RDWR, 0644);
455 if (fd < 0)
456 pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
457 free(dir_name);
458 pcache->fd = fd;
459
460 return fd;
461}
462
463static int probe_cache__load(struct probe_cache *pcache)
464{
465 struct probe_cache_entry *entry = NULL;
466 char buf[MAX_CMDLEN], *p;
467 int ret = 0, fddup;
468 FILE *fp;
469
470 fddup = dup(pcache->fd);
471 if (fddup < 0)
472 return -errno;
473 fp = fdopen(fddup, "r");
474 if (!fp) {
475 close(fddup);
476 return -EINVAL;
477 }
478
479 while (!feof(fp)) {
480 if (!fgets(buf, MAX_CMDLEN, fp))
481 break;
482 p = strchr(buf, '\n');
483 if (p)
484 *p = '\0';
485 /* #perf_probe_event or %sdt_event */
486 if (buf[0] == '#' || buf[0] == '%') {
487 entry = probe_cache_entry__new(NULL);
488 if (!entry) {
489 ret = -ENOMEM;
490 goto out;
491 }
492 if (buf[0] == '%')
493 entry->sdt = true;
494 entry->spev = strdup(buf + 1);
495 if (entry->spev)
496 ret = parse_perf_probe_command(buf + 1,
497 &entry->pev);
498 else
499 ret = -ENOMEM;
500 if (ret < 0) {
501 probe_cache_entry__delete(entry);
502 goto out;
503 }
504 list_add_tail(&entry->node, &pcache->entries);
505 } else { /* trace_probe_event */
506 if (!entry) {
507 ret = -EINVAL;
508 goto out;
509 }
510 strlist__add(entry->tevlist, buf);
511 }
512 }
513out:
514 fclose(fp);
515 return ret;
516}
517
518static struct probe_cache *probe_cache__alloc(void)
519{
520 struct probe_cache *pcache = zalloc(sizeof(*pcache));
521
522 if (pcache) {
523 INIT_LIST_HEAD(&pcache->entries);
524 pcache->fd = -EINVAL;
525 }
526 return pcache;
527}
528
529void probe_cache__purge(struct probe_cache *pcache)
530{
531 struct probe_cache_entry *entry, *n;
532
533 list_for_each_entry_safe(entry, n, &pcache->entries, node) {
534 list_del_init(&entry->node);
535 probe_cache_entry__delete(entry);
536 }
537}
538
539void probe_cache__delete(struct probe_cache *pcache)
540{
541 if (!pcache)
542 return;
543
544 probe_cache__purge(pcache);
545 if (pcache->fd > 0)
546 close(pcache->fd);
547 free(pcache);
548}
549
550struct probe_cache *probe_cache__new(const char *target)
551{
552 struct probe_cache *pcache = probe_cache__alloc();
553 int ret;
554
555 if (!pcache)
556 return NULL;
557
558 ret = probe_cache__open(pcache, target);
559 if (ret < 0) {
560 pr_debug("Cache open error: %d\n", ret);
561 goto out_err;
562 }
563
564 ret = probe_cache__load(pcache);
565 if (ret < 0) {
566 pr_debug("Cache read error: %d\n", ret);
567 goto out_err;
568 }
569
570 return pcache;
571
572out_err:
573 probe_cache__delete(pcache);
574 return NULL;
575}
576
577static bool streql(const char *a, const char *b)
578{
579 if (a == b)
580 return true;
581
582 if (!a || !b)
583 return false;
584
585 return !strcmp(a, b);
586}
587
588struct probe_cache_entry *
589probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
590{
591 struct probe_cache_entry *entry = NULL;
592 char *cmd = synthesize_perf_probe_command(pev);
593
594 if (!cmd)
595 return NULL;
596
597 for_each_probe_cache_entry(entry, pcache) {
598 if (pev->sdt) {
599 if (entry->pev.event &&
600 streql(entry->pev.event, pev->event) &&
601 (!pev->group ||
602 streql(entry->pev.group, pev->group)))
603 goto found;
604
605 continue;
606 }
607 /* Hit if same event name or same command-string */
608 if ((pev->event &&
609 (streql(entry->pev.group, pev->group) &&
610 streql(entry->pev.event, pev->event))) ||
611 (!strcmp(entry->spev, cmd)))
612 goto found;
613 }
614 entry = NULL;
615
616found:
617 free(cmd);
618 return entry;
619}
620
621struct probe_cache_entry *
622probe_cache__find_by_name(struct probe_cache *pcache,
623 const char *group, const char *event)
624{
625 struct probe_cache_entry *entry = NULL;
626
627 for_each_probe_cache_entry(entry, pcache) {
628 /* Hit if same event name or same command-string */
629 if (streql(entry->pev.group, group) &&
630 streql(entry->pev.event, event))
631 goto found;
632 }
633 entry = NULL;
634
635found:
636 return entry;
637}
638
639int probe_cache__add_entry(struct probe_cache *pcache,
640 struct perf_probe_event *pev,
641 struct probe_trace_event *tevs, int ntevs)
642{
643 struct probe_cache_entry *entry = NULL;
644 char *command;
645 int i, ret = 0;
646
647 if (!pcache || !pev || !tevs || ntevs <= 0) {
648 ret = -EINVAL;
649 goto out_err;
650 }
651
652 /* Remove old cache entry */
653 entry = probe_cache__find(pcache, pev);
654 if (entry) {
655 list_del_init(&entry->node);
656 probe_cache_entry__delete(entry);
657 }
658
659 ret = -ENOMEM;
660 entry = probe_cache_entry__new(pev);
661 if (!entry)
662 goto out_err;
663
664 for (i = 0; i < ntevs; i++) {
665 if (!tevs[i].point.symbol)
666 continue;
667
668 command = synthesize_probe_trace_command(&tevs[i]);
669 if (!command)
670 goto out_err;
671 strlist__add(entry->tevlist, command);
672 free(command);
673 }
674 list_add_tail(&entry->node, &pcache->entries);
675 pr_debug("Added probe cache: %d\n", ntevs);
676 return 0;
677
678out_err:
679 pr_debug("Failed to add probe caches\n");
680 probe_cache_entry__delete(entry);
681 return ret;
682}
683
684#ifdef HAVE_GELF_GETNOTE_SUPPORT
685static unsigned long long sdt_note__get_addr(struct sdt_note *note)
686{
687 return note->bit32 ? (unsigned long long)note->addr.a32[0]
688 : (unsigned long long)note->addr.a64[0];
689}
690
691int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
692{
693 struct probe_cache_entry *entry = NULL;
694 struct list_head sdtlist;
695 struct sdt_note *note;
696 char *buf;
697 char sdtgrp[64];
698 int ret;
699
700 INIT_LIST_HEAD(&sdtlist);
701 ret = get_sdt_note_list(&sdtlist, pathname);
702 if (ret < 0) {
703 pr_debug("Failed to get sdt note: %d\n", ret);
704 return ret;
705 }
706 list_for_each_entry(note, &sdtlist, note_list) {
707 ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
708 if (ret < 0)
709 break;
710 /* Try to find same-name entry */
711 entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
712 if (!entry) {
713 entry = probe_cache_entry__new(NULL);
714 if (!entry) {
715 ret = -ENOMEM;
716 break;
717 }
718 entry->sdt = true;
719 ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
720 note->name, note->name);
721 if (ret < 0)
722 break;
723 entry->pev.event = strdup(note->name);
724 entry->pev.group = strdup(sdtgrp);
725 list_add_tail(&entry->node, &pcache->entries);
726 }
727 ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
728 sdtgrp, note->name, pathname,
729 sdt_note__get_addr(note));
730 if (ret < 0)
731 break;
732 strlist__add(entry->tevlist, buf);
733 free(buf);
734 entry = NULL;
735 }
736 if (entry) {
737 list_del_init(&entry->node);
738 probe_cache_entry__delete(entry);
739 }
740 cleanup_sdt_note_list(&sdtlist);
741 return ret;
742}
743#endif
744
745static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
746{
747 struct str_node *snode;
748 struct stat st;
749 struct iovec iov[3];
750 const char *prefix = entry->sdt ? "%" : "#";
751 int ret;
752 /* Save stat for rollback */
753 ret = fstat(fd, &st);
754 if (ret < 0)
755 return ret;
756
757 pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
758 iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
759 iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
760 iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
761 ret = writev(fd, iov, 3);
762 if (ret < (int)iov[1].iov_len + 2)
763 goto rollback;
764
765 strlist__for_each_entry(snode, entry->tevlist) {
766 iov[0].iov_base = (void *)snode->s;
767 iov[0].iov_len = strlen(snode->s);
768 iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
769 ret = writev(fd, iov, 2);
770 if (ret < (int)iov[0].iov_len + 1)
771 goto rollback;
772 }
773 return 0;
774
775rollback:
776 /* Rollback to avoid cache file corruption */
777 if (ret > 0)
778 ret = -1;
779 if (ftruncate(fd, st.st_size) < 0)
780 ret = -2;
781
782 return ret;
783}
784
785int probe_cache__commit(struct probe_cache *pcache)
786{
787 struct probe_cache_entry *entry;
788 int ret = 0;
789
790 /* TBD: if we do not update existing entries, skip it */
791 ret = lseek(pcache->fd, 0, SEEK_SET);
792 if (ret < 0)
793 goto out;
794
795 ret = ftruncate(pcache->fd, 0);
796 if (ret < 0)
797 goto out;
798
799 for_each_probe_cache_entry(entry, pcache) {
800 ret = probe_cache_entry__write(entry, pcache->fd);
801 pr_debug("Cache committed: %d\n", ret);
802 if (ret < 0)
803 break;
804 }
805out:
806 return ret;
807}
808
809static bool probe_cache_entry__compare(struct probe_cache_entry *entry,
810 struct strfilter *filter)
811{
812 char buf[128], *ptr = entry->spev;
813
814 if (entry->pev.event) {
815 snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
816 ptr = buf;
817 }
818 return strfilter__compare(filter, ptr);
819}
820
821int probe_cache__filter_purge(struct probe_cache *pcache,
822 struct strfilter *filter)
823{
824 struct probe_cache_entry *entry, *tmp;
825
826 list_for_each_entry_safe(entry, tmp, &pcache->entries, node) {
827 if (probe_cache_entry__compare(entry, filter)) {
828 pr_info("Removed cached event: %s\n", entry->spev);
829 list_del_init(&entry->node);
830 probe_cache_entry__delete(entry);
831 }
832 }
833 return 0;
834}
835
836static int probe_cache__show_entries(struct probe_cache *pcache,
837 struct strfilter *filter)
838{
839 struct probe_cache_entry *entry;
840
841 for_each_probe_cache_entry(entry, pcache) {
842 if (probe_cache_entry__compare(entry, filter))
843 printf("%s\n", entry->spev);
844 }
845 return 0;
846}
847
848/* Show all cached probes */
849int probe_cache__show_all_caches(struct strfilter *filter)
850{
851 struct probe_cache *pcache;
852 struct strlist *bidlist;
853 struct str_node *nd;
854 char *buf = strfilter__string(filter);
855
856 pr_debug("list cache with filter: %s\n", buf);
857 free(buf);
858
859 bidlist = build_id_cache__list_all(true);
860 if (!bidlist) {
861 pr_debug("Failed to get buildids: %d\n", errno);
862 return -EINVAL;
863 }
864 strlist__for_each_entry(nd, bidlist) {
865 pcache = probe_cache__new(nd->s);
866 if (!pcache)
867 continue;
868 if (!list_empty(&pcache->entries)) {
869 buf = build_id_cache__origname(nd->s);
870 printf("%s (%s):\n", buf, nd->s);
871 free(buf);
872 probe_cache__show_entries(pcache, filter);
873 }
874 probe_cache__delete(pcache);
875 }
876 strlist__delete(bidlist);
877
878 return 0;
879}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 18ac9cf51c34..9577b5c0b487 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -5,9 +5,27 @@
5#include "strfilter.h" 5#include "strfilter.h"
6#include "probe-event.h" 6#include "probe-event.h"
7 7
8/* Cache of probe definitions */
9struct probe_cache_entry {
10 struct list_head node;
11 bool sdt;
12 struct perf_probe_event pev;
13 char *spev;
14 struct strlist *tevlist;
15};
16
17struct probe_cache {
18 int fd;
19 struct list_head entries;
20};
21
8#define PF_FL_UPROBE 1 22#define PF_FL_UPROBE 1
9#define PF_FL_RW 2 23#define PF_FL_RW 2
24#define for_each_probe_cache_entry(entry, pcache) \
25 list_for_each_entry(entry, &pcache->entries, node)
10 26
27/* probe-file.c depends on libelf */
28#ifdef HAVE_LIBELF_SUPPORT
11int probe_file__open(int flag); 29int probe_file__open(int flag);
12int probe_file__open_both(int *kfd, int *ufd, int flag); 30int probe_file__open_both(int *kfd, int *ufd, int flag);
13struct strlist *probe_file__get_namelist(int fd); 31struct strlist *probe_file__get_namelist(int fd);
@@ -18,5 +36,29 @@ int probe_file__get_events(int fd, struct strfilter *filter,
18 struct strlist *plist); 36 struct strlist *plist);
19int probe_file__del_strlist(int fd, struct strlist *namelist); 37int probe_file__del_strlist(int fd, struct strlist *namelist);
20 38
39int probe_cache_entry__get_event(struct probe_cache_entry *entry,
40 struct probe_trace_event **tevs);
21 41
42struct probe_cache *probe_cache__new(const char *target);
43int probe_cache__add_entry(struct probe_cache *pcache,
44 struct perf_probe_event *pev,
45 struct probe_trace_event *tevs, int ntevs);
46int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname);
47int probe_cache__commit(struct probe_cache *pcache);
48void probe_cache__purge(struct probe_cache *pcache);
49void probe_cache__delete(struct probe_cache *pcache);
50int probe_cache__filter_purge(struct probe_cache *pcache,
51 struct strfilter *filter);
52struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
53 struct perf_probe_event *pev);
54struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
55 const char *group, const char *event);
56int probe_cache__show_all_caches(struct strfilter *filter);
57#else /* ! HAVE_LIBELF_SUPPORT */
58static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
59{
60 return NULL;
61}
62#define probe_cache__delete(pcache) do {} while (0)
63#endif
22#endif 64#endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index b3bd0fba0237..5c290c682afe 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -297,10 +297,13 @@ static int convert_variable_type(Dwarf_Die *vr_die,
297 char sbuf[STRERR_BUFSIZE]; 297 char sbuf[STRERR_BUFSIZE];
298 int bsize, boffs, total; 298 int bsize, boffs, total;
299 int ret; 299 int ret;
300 char sign;
300 301
301 /* TODO: check all types */ 302 /* TODO: check all types */
302 if (cast && strcmp(cast, "string") != 0) { 303 if (cast && strcmp(cast, "string") != 0 &&
304 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
303 /* Non string type is OK */ 305 /* Non string type is OK */
306 /* and respect signedness cast */
304 tvar->type = strdup(cast); 307 tvar->type = strdup(cast);
305 return (tvar->type == NULL) ? -ENOMEM : 0; 308 return (tvar->type == NULL) ? -ENOMEM : 0;
306 } 309 }
@@ -361,6 +364,13 @@ static int convert_variable_type(Dwarf_Die *vr_die,
361 return (tvar->type == NULL) ? -ENOMEM : 0; 364 return (tvar->type == NULL) ? -ENOMEM : 0;
362 } 365 }
363 366
367 if (cast && (strcmp(cast, "u") == 0))
368 sign = 'u';
369 else if (cast && (strcmp(cast, "s") == 0))
370 sign = 's';
371 else
372 sign = die_is_signed_type(&type) ? 's' : 'u';
373
364 ret = dwarf_bytesize(&type); 374 ret = dwarf_bytesize(&type);
365 if (ret <= 0) 375 if (ret <= 0)
366 /* No size ... try to use default type */ 376 /* No size ... try to use default type */
@@ -373,15 +383,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
373 dwarf_diename(&type), MAX_BASIC_TYPE_BITS); 383 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
374 ret = MAX_BASIC_TYPE_BITS; 384 ret = MAX_BASIC_TYPE_BITS;
375 } 385 }
376 ret = snprintf(buf, 16, "%c%d", 386 ret = snprintf(buf, 16, "%c%d", sign, ret);
377 die_is_signed_type(&type) ? 's' : 'u', ret);
378 387
379formatted: 388formatted:
380 if (ret < 0 || ret >= 16) { 389 if (ret < 0 || ret >= 16) {
381 if (ret >= 16) 390 if (ret >= 16)
382 ret = -E2BIG; 391 ret = -E2BIG;
383 pr_warning("Failed to convert variable type: %s\n", 392 pr_warning("Failed to convert variable type: %s\n",
384 strerror_r(-ret, sbuf, sizeof(sbuf))); 393 str_error_r(-ret, sbuf, sizeof(sbuf)));
385 return ret; 394 return ret;
386 } 395 }
387 tvar->type = strdup(buf); 396 tvar->type = strdup(buf);
@@ -553,7 +562,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
553static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) 562static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
554{ 563{
555 Dwarf_Die vr_die; 564 Dwarf_Die vr_die;
556 char buf[32], *ptr; 565 char *buf, *ptr;
557 int ret = 0; 566 int ret = 0;
558 567
559 /* Copy raw parameters */ 568 /* Copy raw parameters */
@@ -563,13 +572,13 @@ static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf)
563 if (pf->pvar->name) 572 if (pf->pvar->name)
564 pf->tvar->name = strdup(pf->pvar->name); 573 pf->tvar->name = strdup(pf->pvar->name);
565 else { 574 else {
566 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32); 575 buf = synthesize_perf_probe_arg(pf->pvar);
567 if (ret < 0) 576 if (!buf)
568 return ret; 577 return -ENOMEM;
569 ptr = strchr(buf, ':'); /* Change type separator to _ */ 578 ptr = strchr(buf, ':'); /* Change type separator to _ */
570 if (ptr) 579 if (ptr)
571 *ptr = '_'; 580 *ptr = '_';
572 pf->tvar->name = strdup(buf); 581 pf->tvar->name = buf;
573 } 582 }
574 if (pf->tvar->name == NULL) 583 if (pf->tvar->name == NULL)
575 return -ENOMEM; 584 return -ENOMEM;
@@ -809,7 +818,7 @@ static int find_lazy_match_lines(struct intlist *list,
809 fp = fopen(fname, "r"); 818 fp = fopen(fname, "r");
810 if (!fp) { 819 if (!fp) {
811 pr_warning("Failed to open %s: %s\n", fname, 820 pr_warning("Failed to open %s: %s\n", fname,
812 strerror_r(errno, sbuf, sizeof(sbuf))); 821 str_error_r(errno, sbuf, sizeof(sbuf)));
813 return -errno; 822 return -errno;
814 } 823 }
815 824
@@ -1294,6 +1303,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1294{ 1303{
1295 struct available_var_finder *af = data; 1304 struct available_var_finder *af = data;
1296 struct variable_list *vl; 1305 struct variable_list *vl;
1306 struct strbuf buf = STRBUF_INIT;
1297 int tag, ret; 1307 int tag, ret;
1298 1308
1299 vl = &af->vls[af->nvls - 1]; 1309 vl = &af->vls[af->nvls - 1];
@@ -1307,25 +1317,26 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1307 if (ret == 0 || ret == -ERANGE) { 1317 if (ret == 0 || ret == -ERANGE) {
1308 int ret2; 1318 int ret2;
1309 bool externs = !af->child; 1319 bool externs = !af->child;
1310 struct strbuf buf;
1311 1320
1312 strbuf_init(&buf, 64); 1321 if (strbuf_init(&buf, 64) < 0)
1322 goto error;
1313 1323
1314 if (probe_conf.show_location_range) { 1324 if (probe_conf.show_location_range) {
1315 if (!externs) { 1325 if (!externs)
1316 if (ret) 1326 ret2 = strbuf_add(&buf,
1317 strbuf_add(&buf, "[INV]\t", 6); 1327 ret ? "[INV]\t" : "[VAL]\t", 6);
1318 else 1328 else
1319 strbuf_add(&buf, "[VAL]\t", 6); 1329 ret2 = strbuf_add(&buf, "[EXT]\t", 6);
1320 } else 1330 if (ret2)
1321 strbuf_add(&buf, "[EXT]\t", 6); 1331 goto error;
1322 } 1332 }
1323 1333
1324 ret2 = die_get_varname(die_mem, &buf); 1334 ret2 = die_get_varname(die_mem, &buf);
1325 1335
1326 if (!ret2 && probe_conf.show_location_range && 1336 if (!ret2 && probe_conf.show_location_range &&
1327 !externs) { 1337 !externs) {
1328 strbuf_addch(&buf, '\t'); 1338 if (strbuf_addch(&buf, '\t') < 0)
1339 goto error;
1329 ret2 = die_get_var_range(&af->pf.sp_die, 1340 ret2 = die_get_var_range(&af->pf.sp_die,
1330 die_mem, &buf); 1341 die_mem, &buf);
1331 } 1342 }
@@ -1343,6 +1354,10 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1343 return DIE_FIND_CB_CONTINUE; 1354 return DIE_FIND_CB_CONTINUE;
1344 else 1355 else
1345 return DIE_FIND_CB_SIBLING; 1356 return DIE_FIND_CB_SIBLING;
1357error:
1358 strbuf_release(&buf);
1359 pr_debug("Error in strbuf\n");
1360 return DIE_FIND_CB_END;
1346} 1361}
1347 1362
1348/* Add a found vars into available variables list */ 1363/* Add a found vars into available variables list */
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 8162ba0e2e57..b7d4f4aeee61 100644
--- a/tools/perf/util/python-ext-sources
+++ b/tools/perf/util/python-ext-sources
@@ -13,6 +13,7 @@ util/cpumap.c
13../lib/bitmap.c 13../lib/bitmap.c
14../lib/find_bit.c 14../lib/find_bit.c
15../lib/hweight.c 15../lib/hweight.c
16../lib/vsprintf.c
16util/thread_map.c 17util/thread_map.c
17util/util.c 18util/util.c
18util/xyarray.c 19util/xyarray.c
@@ -23,3 +24,4 @@ util/strlist.c
23util/trace-event.c 24util/trace-event.c
24../lib/rbtree.c 25../lib/rbtree.c
25util/string.c 26util/string.c
27util/symbol_fprintf.c
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index 98f127abfa42..a5fbc012e3df 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -2,6 +2,7 @@
2#include <structmember.h> 2#include <structmember.h>
3#include <inttypes.h> 3#include <inttypes.h>
4#include <poll.h> 4#include <poll.h>
5#include <linux/err.h>
5#include "evlist.h" 6#include "evlist.h"
6#include "evsel.h" 7#include "evsel.h"
7#include "event.h" 8#include "event.h"
@@ -47,6 +48,7 @@ PyMODINIT_FUNC initperf(void);
47 48
48struct pyrf_event { 49struct pyrf_event {
49 PyObject_HEAD 50 PyObject_HEAD
51 struct perf_evsel *evsel;
50 struct perf_sample sample; 52 struct perf_sample sample;
51 union perf_event event; 53 union perf_event event;
52}; 54};
@@ -288,6 +290,85 @@ static PyObject *pyrf_sample_event__repr(struct pyrf_event *pevent)
288 return ret; 290 return ret;
289} 291}
290 292
293static bool is_tracepoint(struct pyrf_event *pevent)
294{
295 return pevent->evsel->attr.type == PERF_TYPE_TRACEPOINT;
296}
297
298static PyObject*
299tracepoint_field(struct pyrf_event *pe, struct format_field *field)
300{
301 struct pevent *pevent = field->event->pevent;
302 void *data = pe->sample.raw_data;
303 PyObject *ret = NULL;
304 unsigned long long val;
305 unsigned int offset, len;
306
307 if (field->flags & FIELD_IS_ARRAY) {
308 offset = field->offset;
309 len = field->size;
310 if (field->flags & FIELD_IS_DYNAMIC) {
311 val = pevent_read_number(pevent, data + offset, len);
312 offset = val;
313 len = offset >> 16;
314 offset &= 0xffff;
315 }
316 if (field->flags & FIELD_IS_STRING &&
317 is_printable_array(data + offset, len)) {
318 ret = PyString_FromString((char *)data + offset);
319 } else {
320 ret = PyByteArray_FromStringAndSize((const char *) data + offset, len);
321 field->flags &= ~FIELD_IS_STRING;
322 }
323 } else {
324 val = pevent_read_number(pevent, data + field->offset,
325 field->size);
326 if (field->flags & FIELD_IS_POINTER)
327 ret = PyLong_FromUnsignedLong((unsigned long) val);
328 else if (field->flags & FIELD_IS_SIGNED)
329 ret = PyLong_FromLong((long) val);
330 else
331 ret = PyLong_FromUnsignedLong((unsigned long) val);
332 }
333
334 return ret;
335}
336
337static PyObject*
338get_tracepoint_field(struct pyrf_event *pevent, PyObject *attr_name)
339{
340 const char *str = PyString_AsString(PyObject_Str(attr_name));
341 struct perf_evsel *evsel = pevent->evsel;
342 struct format_field *field;
343
344 if (!evsel->tp_format) {
345 struct event_format *tp_format;
346
347 tp_format = trace_event__tp_format_id(evsel->attr.config);
348 if (!tp_format)
349 return NULL;
350
351 evsel->tp_format = tp_format;
352 }
353
354 field = pevent_find_any_field(evsel->tp_format, str);
355 if (!field)
356 return NULL;
357
358 return tracepoint_field(pevent, field);
359}
360
361static PyObject*
362pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name)
363{
364 PyObject *obj = NULL;
365
366 if (is_tracepoint(pevent))
367 obj = get_tracepoint_field(pevent, attr_name);
368
369 return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name);
370}
371
291static PyTypeObject pyrf_sample_event__type = { 372static PyTypeObject pyrf_sample_event__type = {
292 PyVarObject_HEAD_INIT(NULL, 0) 373 PyVarObject_HEAD_INIT(NULL, 0)
293 .tp_name = "perf.sample_event", 374 .tp_name = "perf.sample_event",
@@ -296,6 +377,7 @@ static PyTypeObject pyrf_sample_event__type = {
296 .tp_doc = pyrf_sample_event__doc, 377 .tp_doc = pyrf_sample_event__doc,
297 .tp_members = pyrf_sample_event__members, 378 .tp_members = pyrf_sample_event__members,
298 .tp_repr = (reprfunc)pyrf_sample_event__repr, 379 .tp_repr = (reprfunc)pyrf_sample_event__repr,
380 .tp_getattro = (getattrofunc) pyrf_sample_event__getattro,
299}; 381};
300 382
301static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object."); 383static char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_switch event object.");
@@ -653,6 +735,7 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
653 attr.precise_ip = precise_ip; 735 attr.precise_ip = precise_ip;
654 attr.mmap_data = mmap_data; 736 attr.mmap_data = mmap_data;
655 attr.sample_id_all = sample_id_all; 737 attr.sample_id_all = sample_id_all;
738 attr.size = sizeof(attr);
656 739
657 perf_evsel__init(&pevsel->evsel, &attr, idx); 740 perf_evsel__init(&pevsel->evsel, &attr, idx);
658 return 0; 741 return 0;
@@ -863,13 +946,22 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
863 if (event != NULL) { 946 if (event != NULL) {
864 PyObject *pyevent = pyrf_event__new(event); 947 PyObject *pyevent = pyrf_event__new(event);
865 struct pyrf_event *pevent = (struct pyrf_event *)pyevent; 948 struct pyrf_event *pevent = (struct pyrf_event *)pyevent;
866 949 struct perf_evsel *evsel;
867 perf_evlist__mmap_consume(evlist, cpu);
868 950
869 if (pyevent == NULL) 951 if (pyevent == NULL)
870 return PyErr_NoMemory(); 952 return PyErr_NoMemory();
871 953
872 err = perf_evlist__parse_sample(evlist, event, &pevent->sample); 954 evsel = perf_evlist__event2evsel(evlist, event);
955 if (!evsel)
956 return Py_None;
957
958 pevent->evsel = evsel;
959
960 err = perf_evsel__parse_sample(evsel, event, &pevent->sample);
961
962 /* Consume the even only after we parsed it out. */
963 perf_evlist__mmap_consume(evlist, cpu);
964
873 if (err) 965 if (err)
874 return PyErr_Format(PyExc_OSError, 966 return PyErr_Format(PyExc_OSError,
875 "perf: can't parse sample, err=%d", err); 967 "perf: can't parse sample, err=%d", err);
@@ -957,7 +1049,7 @@ static PyObject *pyrf_evlist__item(PyObject *obj, Py_ssize_t i)
957 if (i >= pevlist->evlist.nr_entries) 1049 if (i >= pevlist->evlist.nr_entries)
958 return NULL; 1050 return NULL;
959 1051
960 evlist__for_each(&pevlist->evlist, pos) { 1052 evlist__for_each_entry(&pevlist->evlist, pos) {
961 if (i-- == 0) 1053 if (i-- == 0)
962 break; 1054 break;
963 } 1055 }
@@ -1073,7 +1165,32 @@ static struct {
1073 { .name = NULL, }, 1165 { .name = NULL, },
1074}; 1166};
1075 1167
1168static PyObject *pyrf__tracepoint(struct pyrf_evsel *pevsel,
1169 PyObject *args, PyObject *kwargs)
1170{
1171 struct event_format *tp_format;
1172 static char *kwlist[] = { "sys", "name", NULL };
1173 char *sys = NULL;
1174 char *name = NULL;
1175
1176 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ss", kwlist,
1177 &sys, &name))
1178 return NULL;
1179
1180 tp_format = trace_event__tp_format(sys, name);
1181 if (IS_ERR(tp_format))
1182 return PyInt_FromLong(-1);
1183
1184 return PyInt_FromLong(tp_format->id);
1185}
1186
1076static PyMethodDef perf__methods[] = { 1187static PyMethodDef perf__methods[] = {
1188 {
1189 .ml_name = "tracepoint",
1190 .ml_meth = (PyCFunction) pyrf__tracepoint,
1191 .ml_flags = METH_VARARGS | METH_KEYWORDS,
1192 .ml_doc = PyDoc_STR("Get tracepoint config.")
1193 },
1077 { .ml_name = NULL, } 1194 { .ml_name = NULL, }
1078}; 1195};
1079 1196
@@ -1100,6 +1217,33 @@ PyMODINIT_FUNC initperf(void)
1100 Py_INCREF(&pyrf_evsel__type); 1217 Py_INCREF(&pyrf_evsel__type);
1101 PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type); 1218 PyModule_AddObject(module, "evsel", (PyObject*)&pyrf_evsel__type);
1102 1219
1220 Py_INCREF(&pyrf_mmap_event__type);
1221 PyModule_AddObject(module, "mmap_event", (PyObject *)&pyrf_mmap_event__type);
1222
1223 Py_INCREF(&pyrf_lost_event__type);
1224 PyModule_AddObject(module, "lost_event", (PyObject *)&pyrf_lost_event__type);
1225
1226 Py_INCREF(&pyrf_comm_event__type);
1227 PyModule_AddObject(module, "comm_event", (PyObject *)&pyrf_comm_event__type);
1228
1229 Py_INCREF(&pyrf_task_event__type);
1230 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
1231
1232 Py_INCREF(&pyrf_throttle_event__type);
1233 PyModule_AddObject(module, "throttle_event", (PyObject *)&pyrf_throttle_event__type);
1234
1235 Py_INCREF(&pyrf_task_event__type);
1236 PyModule_AddObject(module, "task_event", (PyObject *)&pyrf_task_event__type);
1237
1238 Py_INCREF(&pyrf_read_event__type);
1239 PyModule_AddObject(module, "read_event", (PyObject *)&pyrf_read_event__type);
1240
1241 Py_INCREF(&pyrf_sample_event__type);
1242 PyModule_AddObject(module, "sample_event", (PyObject *)&pyrf_sample_event__type);
1243
1244 Py_INCREF(&pyrf_context_switch_event__type);
1245 PyModule_AddObject(module, "switch_event", (PyObject *)&pyrf_context_switch_event__type);
1246
1103 Py_INCREF(&pyrf_thread_map__type); 1247 Py_INCREF(&pyrf_thread_map__type);
1104 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type); 1248 PyModule_AddObject(module, "thread_map", (PyObject*)&pyrf_thread_map__type);
1105 1249
diff --git a/tools/perf/util/quote.c b/tools/perf/util/quote.c
index 01f03242b86a..639d1da2f978 100644
--- a/tools/perf/util/quote.c
+++ b/tools/perf/util/quote.c
@@ -1,5 +1,7 @@
1#include "cache.h" 1#include <stdlib.h>
2#include "strbuf.h"
2#include "quote.h" 3#include "quote.h"
4#include "util.h"
3 5
4/* Help to copy the thing properly quoted for the shell safety. 6/* Help to copy the thing properly quoted for the shell safety.
5 * any single quote is replaced with '\'', any exclamation point 7 * any single quote is replaced with '\'', any exclamation point
@@ -17,38 +19,42 @@ static inline int need_bs_quote(char c)
17 return (c == '\'' || c == '!'); 19 return (c == '\'' || c == '!');
18} 20}
19 21
20static void sq_quote_buf(struct strbuf *dst, const char *src) 22static int sq_quote_buf(struct strbuf *dst, const char *src)
21{ 23{
22 char *to_free = NULL; 24 char *to_free = NULL;
25 int ret;
23 26
24 if (dst->buf == src) 27 if (dst->buf == src)
25 to_free = strbuf_detach(dst, NULL); 28 to_free = strbuf_detach(dst, NULL);
26 29
27 strbuf_addch(dst, '\''); 30 ret = strbuf_addch(dst, '\'');
28 while (*src) { 31 while (!ret && *src) {
29 size_t len = strcspn(src, "'!"); 32 size_t len = strcspn(src, "'!");
30 strbuf_add(dst, src, len); 33 ret = strbuf_add(dst, src, len);
31 src += len; 34 src += len;
32 while (need_bs_quote(*src)) { 35 while (!ret && need_bs_quote(*src))
33 strbuf_addstr(dst, "'\\"); 36 ret = strbuf_addf(dst, "'\\%c\'", *src++);
34 strbuf_addch(dst, *src++);
35 strbuf_addch(dst, '\'');
36 }
37 } 37 }
38 strbuf_addch(dst, '\''); 38 if (!ret)
39 ret = strbuf_addch(dst, '\'');
39 free(to_free); 40 free(to_free);
41
42 return ret;
40} 43}
41 44
42void sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen) 45int sq_quote_argv(struct strbuf *dst, const char** argv, size_t maxlen)
43{ 46{
44 int i; 47 int i, ret;
45 48
46 /* Copy into destination buffer. */ 49 /* Copy into destination buffer. */
47 strbuf_grow(dst, 255); 50 ret = strbuf_grow(dst, 255);
48 for (i = 0; argv[i]; ++i) { 51 for (i = 0; !ret && argv[i]; ++i) {
49 strbuf_addch(dst, ' '); 52 ret = strbuf_addch(dst, ' ');
50 sq_quote_buf(dst, argv[i]); 53 if (ret)
54 break;
55 ret = sq_quote_buf(dst, argv[i]);
51 if (maxlen && dst->len > maxlen) 56 if (maxlen && dst->len > maxlen)
52 die("Too many or long arguments"); 57 die("Too many or long arguments");
53 } 58 }
59 return ret;
54} 60}
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index 3340c9c4a6ca..055ca45bed99 100644
--- a/tools/perf/util/quote.h
+++ b/tools/perf/util/quote.h
@@ -2,7 +2,6 @@
2#define __PERF_QUOTE_H 2#define __PERF_QUOTE_H
3 3
4#include <stddef.h> 4#include <stddef.h>
5#include <stdio.h>
6 5
7/* Help to copy the thing properly quoted for the shell safety. 6/* Help to copy the thing properly quoted for the shell safety.
8 * any single quote is replaced with '\'', any exclamation point 7 * any single quote is replaced with '\'', any exclamation point
@@ -24,6 +23,8 @@
24 * sq_quote() in a real application. 23 * sq_quote() in a real application.
25 */ 24 */
26 25
27void sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); 26struct strbuf;
27
28int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen);
28 29
29#endif /* __PERF_QUOTE_H */ 30#endif /* __PERF_QUOTE_H */
diff --git a/tools/perf/util/rb_resort.h b/tools/perf/util/rb_resort.h
new file mode 100644
index 000000000000..808cc45611fe
--- /dev/null
+++ b/tools/perf/util/rb_resort.h
@@ -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_entry(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_entry(__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_ */
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 0467367dc315..98bf584853ea 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -129,7 +129,8 @@ bool perf_can_record_cpu_wide(void)
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;
@@ -147,8 +148,8 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
147 148
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_entry(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 }
@@ -160,18 +161,18 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts)
160 * match the id. 161 * match the id.
161 */ 162 */
162 use_sample_identifier = perf_can_sample_identifier(); 163 use_sample_identifier = perf_can_sample_identifier();
163 evlist__for_each(evlist, evsel) 164 evlist__for_each_entry(evlist, evsel)
164 perf_evsel__set_sample_id(evsel, use_sample_identifier); 165 perf_evsel__set_sample_id(evsel, use_sample_identifier);
165 } else if (evlist->nr_entries > 1) { 166 } else if (evlist->nr_entries > 1) {
166 struct perf_evsel *first = perf_evlist__first(evlist); 167 struct perf_evsel *first = perf_evlist__first(evlist);
167 168
168 evlist__for_each(evlist, evsel) { 169 evlist__for_each_entry(evlist, evsel) {
169 if (evsel->attr.sample_type == first->attr.sample_type) 170 if (evsel->attr.sample_type == first->attr.sample_type)
170 continue; 171 continue;
171 use_sample_identifier = perf_can_sample_identifier(); 172 use_sample_identifier = perf_can_sample_identifier();
172 break; 173 break;
173 } 174 }
174 evlist__for_each(evlist, evsel) 175 evlist__for_each_entry(evlist, evsel)
175 perf_evsel__set_sample_id(evsel, use_sample_identifier); 176 perf_evsel__set_sample_id(evsel, use_sample_identifier);
176 } 177 }
177 178
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index b3aabc0d4eb0..5d1eb1ccd96c 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -31,6 +31,8 @@
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,89 @@ static void define_event_symbols(struct event_format *event,
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, scripting_max_stack) != 0) {
268 pr_err("Failed to resolve callchain. Skipping\n");
269 goto exit;
270 }
271 callchain_cursor_commit(&callchain_cursor);
272
273
274 while (1) {
275 HV *elem;
276 struct callchain_cursor_node *node;
277 node = callchain_cursor_current(&callchain_cursor);
278 if (!node)
279 break;
280
281 elem = newHV();
282 if (!elem)
283 goto exit;
284
285 if (!hv_stores(elem, "ip", newSVuv(node->ip))) {
286 hv_undef(elem);
287 goto exit;
288 }
289
290 if (node->sym) {
291 HV *sym = newHV();
292 if (!sym) {
293 hv_undef(elem);
294 goto exit;
295 }
296 if (!hv_stores(sym, "start", newSVuv(node->sym->start)) ||
297 !hv_stores(sym, "end", newSVuv(node->sym->end)) ||
298 !hv_stores(sym, "binding", newSVuv(node->sym->binding)) ||
299 !hv_stores(sym, "name", newSVpvn(node->sym->name,
300 node->sym->namelen)) ||
301 !hv_stores(elem, "sym", newRV_noinc((SV*)sym))) {
302 hv_undef(sym);
303 hv_undef(elem);
304 goto exit;
305 }
306 }
307
308 if (node->map) {
309 struct map *map = node->map;
310 const char *dsoname = "[unknown]";
311 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
312 if (symbol_conf.show_kernel_path && map->dso->long_name)
313 dsoname = map->dso->long_name;
314 else if (map->dso->name)
315 dsoname = map->dso->name;
316 }
317 if (!hv_stores(elem, "dso", newSVpv(dsoname,0))) {
318 hv_undef(elem);
319 goto exit;
320 }
321 }
322
323 callchain_cursor_advance(&callchain_cursor);
324 av_push(list, newRV_noinc((SV*)elem));
325 }
326
327exit:
328 return newRV_noinc((SV*)list);
329}
330
251static void perl_process_tracepoint(struct perf_sample *sample, 331static void perl_process_tracepoint(struct perf_sample *sample,
252 struct perf_evsel *evsel, 332 struct perf_evsel *evsel,
253 struct thread *thread) 333 struct addr_location *al)
254{ 334{
335 struct thread *thread = al->thread;
255 struct event_format *event = evsel->tp_format; 336 struct event_format *event = evsel->tp_format;
256 struct format_field *field; 337 struct format_field *field;
257 static char handler[256]; 338 static char handler[256];
@@ -295,6 +376,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
295 XPUSHs(sv_2mortal(newSVuv(ns))); 376 XPUSHs(sv_2mortal(newSVuv(ns)));
296 XPUSHs(sv_2mortal(newSViv(pid))); 377 XPUSHs(sv_2mortal(newSViv(pid)));
297 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 378 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
379 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
298 380
299 /* common fields other than pid can be accessed via xsub fns */ 381 /* common fields other than pid can be accessed via xsub fns */
300 382
@@ -329,6 +411,7 @@ static void perl_process_tracepoint(struct perf_sample *sample,
329 XPUSHs(sv_2mortal(newSVuv(nsecs))); 411 XPUSHs(sv_2mortal(newSVuv(nsecs)));
330 XPUSHs(sv_2mortal(newSViv(pid))); 412 XPUSHs(sv_2mortal(newSViv(pid)));
331 XPUSHs(sv_2mortal(newSVpv(comm, 0))); 413 XPUSHs(sv_2mortal(newSVpv(comm, 0)));
414 XPUSHs(sv_2mortal(perl_process_callchain(sample, evsel, al)));
332 call_pv("main::trace_unhandled", G_SCALAR); 415 call_pv("main::trace_unhandled", G_SCALAR);
333 } 416 }
334 SPAGAIN; 417 SPAGAIN;
@@ -366,7 +449,7 @@ static void perl_process_event(union perf_event *event,
366 struct perf_evsel *evsel, 449 struct perf_evsel *evsel,
367 struct addr_location *al) 450 struct addr_location *al)
368{ 451{
369 perl_process_tracepoint(sample, evsel, al->thread); 452 perl_process_tracepoint(sample, evsel, al);
370 perl_process_event_generic(event, sample, evsel); 453 perl_process_event_generic(event, sample, evsel);
371} 454}
372 455
@@ -490,7 +573,27 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
490 fprintf(ofp, "use Perf::Trace::Util;\n\n"); 573 fprintf(ofp, "use Perf::Trace::Util;\n\n");
491 574
492 fprintf(ofp, "sub trace_begin\n{\n\t# optional\n}\n\n"); 575 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"); 576 fprintf(ofp, "sub trace_end\n{\n\t# optional\n}\n");
577
578
579 fprintf(ofp, "\n\
580sub print_backtrace\n\
581{\n\
582 my $callchain = shift;\n\
583 for my $node (@$callchain)\n\
584 {\n\
585 if(exists $node->{sym})\n\
586 {\n\
587 printf( \"\\t[\\%%x] \\%%s\\n\", $node->{ip}, $node->{sym}{name});\n\
588 }\n\
589 else\n\
590 {\n\
591 printf( \"\\t[\\%%x]\\n\", $node{ip});\n\
592 }\n\
593 }\n\
594}\n\n\
595");
596
494 597
495 while ((event = trace_find_next_event(pevent, event))) { 598 while ((event = trace_find_next_event(pevent, event))) {
496 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name); 599 fprintf(ofp, "sub %s::%s\n{\n", event->system, event->name);
@@ -502,7 +605,8 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
502 fprintf(ofp, "$common_secs, "); 605 fprintf(ofp, "$common_secs, ");
503 fprintf(ofp, "$common_nsecs,\n"); 606 fprintf(ofp, "$common_nsecs,\n");
504 fprintf(ofp, "\t $common_pid, "); 607 fprintf(ofp, "\t $common_pid, ");
505 fprintf(ofp, "$common_comm,\n\t "); 608 fprintf(ofp, "$common_comm, ");
609 fprintf(ofp, "$common_callchain,\n\t ");
506 610
507 not_first = 0; 611 not_first = 0;
508 count = 0; 612 count = 0;
@@ -519,7 +623,7 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
519 623
520 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 624 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
521 "$common_secs, $common_nsecs,\n\t " 625 "$common_secs, $common_nsecs,\n\t "
522 "$common_pid, $common_comm);\n\n"); 626 "$common_pid, $common_comm, $common_callchain);\n\n");
523 627
524 fprintf(ofp, "\tprintf(\""); 628 fprintf(ofp, "\tprintf(\"");
525 629
@@ -581,17 +685,22 @@ static int perl_generate_script(struct pevent *pevent, const char *outfile)
581 fprintf(ofp, "$%s", f->name); 685 fprintf(ofp, "$%s", f->name);
582 } 686 }
583 687
584 fprintf(ofp, ");\n"); 688 fprintf(ofp, ");\n\n");
689
690 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
691
585 fprintf(ofp, "}\n\n"); 692 fprintf(ofp, "}\n\n");
586 } 693 }
587 694
588 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, " 695 fprintf(ofp, "sub trace_unhandled\n{\n\tmy ($event_name, $context, "
589 "$common_cpu, $common_secs, $common_nsecs,\n\t " 696 "$common_cpu, $common_secs, $common_nsecs,\n\t "
590 "$common_pid, $common_comm) = @_;\n\n"); 697 "$common_pid, $common_comm, $common_callchain) = @_;\n\n");
591 698
592 fprintf(ofp, "\tprint_header($event_name, $common_cpu, " 699 fprintf(ofp, "\tprint_header($event_name, $common_cpu, "
593 "$common_secs, $common_nsecs,\n\t $common_pid, " 700 "$common_secs, $common_nsecs,\n\t $common_pid, "
594 "$common_comm);\n}\n\n"); 701 "$common_comm, $common_callchain);\n");
702 fprintf(ofp, "\tprint_backtrace($common_callchain);\n");
703 fprintf(ofp, "}\n\n");
595 704
596 fprintf(ofp, "sub print_header\n{\n" 705 fprintf(ofp, "sub print_header\n{\n"
597 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n" 706 "\tmy ($event_name, $cpu, $secs, $nsecs, $pid, $comm) = @_;\n\n"
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index fbd05242b4e5..e0203b979474 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -41,6 +41,7 @@
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"
@@ -272,7 +273,7 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
272 struct format_field *field, void *data) 273 struct format_field *field, void *data)
273{ 274{
274 bool is_array = field->flags & FIELD_IS_ARRAY; 275 bool is_array = field->flags & FIELD_IS_ARRAY;
275 PyObject *obj, *list = NULL; 276 PyObject *obj = NULL, *list = NULL;
276 unsigned long long val; 277 unsigned long long val;
277 unsigned int item_size, n_items, i; 278 unsigned int item_size, n_items, i;
278 279
@@ -323,7 +324,7 @@ static PyObject *python_process_callchain(struct perf_sample *sample,
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");
@@ -385,13 +386,12 @@ exit:
385 return pylist; 386 return pylist;
386} 387}
387 388
388
389static void python_process_tracepoint(struct perf_sample *sample, 389static void python_process_tracepoint(struct perf_sample *sample,
390 struct perf_evsel *evsel, 390 struct perf_evsel *evsel,
391 struct addr_location *al) 391 struct addr_location *al)
392{ 392{
393 struct event_format *event = evsel->tp_format; 393 struct event_format *event = evsel->tp_format;
394 PyObject *handler, *context, *t, *obj, *callchain; 394 PyObject *handler, *context, *t, *obj = NULL, *callchain;
395 PyObject *dict = NULL; 395 PyObject *dict = NULL;
396 static char handler_name[256]; 396 static char handler_name[256];
397 struct format_field *field; 397 struct format_field *field;
@@ -407,8 +407,11 @@ static void python_process_tracepoint(struct perf_sample *sample,
407 if (!t) 407 if (!t)
408 Py_FatalError("couldn't create Python tuple"); 408 Py_FatalError("couldn't create Python tuple");
409 409
410 if (!event) 410 if (!event) {
411 die("ug! no event found for type %d", (int)evsel->attr.config); 411 snprintf(handler_name, sizeof(handler_name),
412 "ug! no event found for type %" PRIu64, (u64)evsel->attr.config);
413 Py_FatalError(handler_name);
414 }
412 415
413 pid = raw_field_value(event, "common_pid", data); 416 pid = raw_field_value(event, "common_pid", data);
414 417
@@ -453,14 +456,26 @@ static void python_process_tracepoint(struct perf_sample *sample,
453 pydict_set_item_string_decref(dict, "common_callchain", callchain); 456 pydict_set_item_string_decref(dict, "common_callchain", callchain);
454 } 457 }
455 for (field = event->format.fields; field; field = field->next) { 458 for (field = event->format.fields; field; field = field->next) {
456 if (field->flags & FIELD_IS_STRING) { 459 unsigned int offset, len;
457 int offset; 460 unsigned long long val;
461
462 if (field->flags & FIELD_IS_ARRAY) {
463 offset = field->offset;
464 len = field->size;
458 if (field->flags & FIELD_IS_DYNAMIC) { 465 if (field->flags & FIELD_IS_DYNAMIC) {
459 offset = *(int *)(data + field->offset); 466 val = pevent_read_number(scripting_context->pevent,
467 data + offset, len);
468 offset = val;
469 len = offset >> 16;
460 offset &= 0xffff; 470 offset &= 0xffff;
461 } else 471 }
462 offset = field->offset; 472 if (field->flags & FIELD_IS_STRING &&
463 obj = PyString_FromString((char *)data + offset); 473 is_printable_array(data + offset, len)) {
474 obj = PyString_FromString((char *) data + offset);
475 } else {
476 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
477 field->flags &= ~FIELD_IS_STRING;
478 }
464 } else { /* FIELD_IS_NUMERIC */ 479 } else { /* FIELD_IS_NUMERIC */
465 obj = get_field_numeric_entry(event, field, data); 480 obj = get_field_numeric_entry(event, field, data);
466 } 481 }
@@ -614,7 +629,7 @@ static int python_export_dso(struct db_export *dbe, struct dso *dso,
614 struct machine *machine) 629 struct machine *machine)
615{ 630{
616 struct tables *tables = container_of(dbe, struct tables, dbe); 631 struct tables *tables = container_of(dbe, struct tables, dbe);
617 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 632 char sbuild_id[SBUILD_ID_SIZE];
618 PyObject *t; 633 PyObject *t;
619 634
620 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 635 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
@@ -681,7 +696,7 @@ static int python_export_sample(struct db_export *dbe,
681 struct tables *tables = container_of(dbe, struct tables, dbe); 696 struct tables *tables = container_of(dbe, struct tables, dbe);
682 PyObject *t; 697 PyObject *t;
683 698
684 t = tuple_new(21); 699 t = tuple_new(22);
685 700
686 tuple_set_u64(t, 0, es->db_id); 701 tuple_set_u64(t, 0, es->db_id);
687 tuple_set_u64(t, 1, es->evsel->db_id); 702 tuple_set_u64(t, 1, es->evsel->db_id);
@@ -704,6 +719,7 @@ static int python_export_sample(struct db_export *dbe,
704 tuple_set_u64(t, 18, es->sample->data_src); 719 tuple_set_u64(t, 18, es->sample->data_src);
705 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); 720 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)); 721 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX));
722 tuple_set_u64(t, 21, es->call_path_id);
707 723
708 call_object(tables->sample_handler, t, "sample_table"); 724 call_object(tables->sample_handler, t, "sample_table");
709 725
@@ -998,8 +1014,10 @@ static void set_table_handlers(struct tables *tables)
998{ 1014{
999 const char *perf_db_export_mode = "perf_db_export_mode"; 1015 const char *perf_db_export_mode = "perf_db_export_mode";
1000 const char *perf_db_export_calls = "perf_db_export_calls"; 1016 const char *perf_db_export_calls = "perf_db_export_calls";
1001 PyObject *db_export_mode, *db_export_calls; 1017 const char *perf_db_export_callchains = "perf_db_export_callchains";
1018 PyObject *db_export_mode, *db_export_calls, *db_export_callchains;
1002 bool export_calls = false; 1019 bool export_calls = false;
1020 bool export_callchains = false;
1003 int ret; 1021 int ret;
1004 1022
1005 memset(tables, 0, sizeof(struct tables)); 1023 memset(tables, 0, sizeof(struct tables));
@@ -1016,6 +1034,7 @@ static void set_table_handlers(struct tables *tables)
1016 if (!ret) 1034 if (!ret)
1017 return; 1035 return;
1018 1036
1037 /* handle export calls */
1019 tables->dbe.crp = NULL; 1038 tables->dbe.crp = NULL;
1020 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); 1039 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
1021 if (db_export_calls) { 1040 if (db_export_calls) {
@@ -1033,6 +1052,33 @@ static void set_table_handlers(struct tables *tables)
1033 Py_FatalError("failed to create calls processor"); 1052 Py_FatalError("failed to create calls processor");
1034 } 1053 }
1035 1054
1055 /* handle export callchains */
1056 tables->dbe.cpr = NULL;
1057 db_export_callchains = PyDict_GetItemString(main_dict,
1058 perf_db_export_callchains);
1059 if (db_export_callchains) {
1060 ret = PyObject_IsTrue(db_export_callchains);
1061 if (ret == -1)
1062 handler_call_die(perf_db_export_callchains);
1063 export_callchains = !!ret;
1064 }
1065
1066 if (export_callchains) {
1067 /*
1068 * Attempt to use the call path root from the call return
1069 * processor, if the call return processor is in use. Otherwise,
1070 * we allocate a new call path root. This prevents exporting
1071 * duplicate call path ids when both are in use simultaniously.
1072 */
1073 if (tables->dbe.crp)
1074 tables->dbe.cpr = tables->dbe.crp->cpr;
1075 else
1076 tables->dbe.cpr = call_path_root__new();
1077
1078 if (!tables->dbe.cpr)
1079 Py_FatalError("failed to create call path root");
1080 }
1081
1036 tables->db_export_mode = true; 1082 tables->db_export_mode = true;
1037 /* 1083 /*
1038 * Reserve per symbol space for symbol->db_id via symbol__priv() 1084 * Reserve per symbol space for symbol->db_id via symbol__priv()
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 4abd85c6346d..5d61242a6e64 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -83,7 +83,7 @@ static bool perf_session__has_comm_exec(struct perf_session *session)
83{ 83{
84 struct perf_evsel *evsel; 84 struct perf_evsel *evsel;
85 85
86 evlist__for_each(session->evlist, evsel) { 86 evlist__for_each_entry(session->evlist, evsel) {
87 if (evsel->attr.comm_exec) 87 if (evsel->attr.comm_exec)
88 return true; 88 return true;
89 } 89 }
@@ -178,6 +178,8 @@ static void perf_session__delete_threads(struct perf_session *session)
178 178
179void perf_session__delete(struct perf_session *session) 179void perf_session__delete(struct perf_session *session)
180{ 180{
181 if (session == NULL)
182 return;
181 auxtrace__free(session); 183 auxtrace__free(session);
182 auxtrace_index__free(&session->auxtrace_index); 184 auxtrace_index__free(&session->auxtrace_index);
183 perf_session__destroy_kernel_maps(session); 185 perf_session__destroy_kernel_maps(session);
@@ -409,6 +411,8 @@ void perf_tool__fill_defaults(struct perf_tool *tool)
409 tool->stat = process_stat_stub; 411 tool->stat = process_stat_stub;
410 if (tool->stat_round == NULL) 412 if (tool->stat_round == NULL)
411 tool->stat_round = process_stat_round_stub; 413 tool->stat_round = process_stat_round_stub;
414 if (tool->time_conv == NULL)
415 tool->time_conv = process_event_op2_stub;
412} 416}
413 417
414static void swap_sample_id_all(union perf_event *event, void *data) 418static void swap_sample_id_all(union perf_event *event, void *data)
@@ -555,7 +559,7 @@ static u8 revbyte(u8 b)
555 559
556/* 560/*
557 * XXX this is hack in attempt to carry flags bitfield 561 * XXX this is hack in attempt to carry flags bitfield
558 * throught endian village. ABI says: 562 * through endian village. ABI says:
559 * 563 *
560 * Bit-fields are allocated from right to left (least to most significant) 564 * Bit-fields are allocated from right to left (least to most significant)
561 * on little-endian implementations and from left to right (most to least 565 * on little-endian implementations and from left to right (most to least
@@ -591,6 +595,7 @@ do { \
591 if (bswap_safe(f, 0)) \ 595 if (bswap_safe(f, 0)) \
592 attr->f = bswap_##sz(attr->f); \ 596 attr->f = bswap_##sz(attr->f); \
593} while(0) 597} while(0)
598#define bswap_field_16(f) bswap_field(f, 16)
594#define bswap_field_32(f) bswap_field(f, 32) 599#define bswap_field_32(f) bswap_field(f, 32)
595#define bswap_field_64(f) bswap_field(f, 64) 600#define bswap_field_64(f) bswap_field(f, 64)
596 601
@@ -606,6 +611,7 @@ do { \
606 bswap_field_64(sample_regs_user); 611 bswap_field_64(sample_regs_user);
607 bswap_field_32(sample_stack_user); 612 bswap_field_32(sample_stack_user);
608 bswap_field_32(aux_watermark); 613 bswap_field_32(aux_watermark);
614 bswap_field_16(sample_max_stack);
609 615
610 /* 616 /*
611 * After read_format are bitfields. Check read_format because 617 * After read_format are bitfields. Check read_format because
@@ -794,6 +800,7 @@ static perf_event__swap_op perf_event__swap_ops[] = {
794 [PERF_RECORD_STAT] = perf_event__stat_swap, 800 [PERF_RECORD_STAT] = perf_event__stat_swap,
795 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap, 801 [PERF_RECORD_STAT_ROUND] = perf_event__stat_round_swap,
796 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap, 802 [PERF_RECORD_EVENT_UPDATE] = perf_event__event_update_swap,
803 [PERF_RECORD_TIME_CONV] = perf_event__all64_swap,
797 [PERF_RECORD_HEADER_MAX] = NULL, 804 [PERF_RECORD_HEADER_MAX] = NULL,
798}; 805};
799 806
@@ -904,7 +911,7 @@ static void callchain__printf(struct perf_evsel *evsel,
904 unsigned int i; 911 unsigned int i;
905 struct ip_callchain *callchain = sample->callchain; 912 struct ip_callchain *callchain = sample->callchain;
906 913
907 if (has_branch_callstack(evsel)) 914 if (perf_evsel__has_branch_callstack(evsel))
908 callchain__lbr_callstack_printf(sample); 915 callchain__lbr_callstack_printf(sample);
909 916
910 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr); 917 printf("... FP chain: nr:%" PRIu64 "\n", callchain->nr);
@@ -1078,7 +1085,7 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event,
1078 if (sample_type & PERF_SAMPLE_CALLCHAIN) 1085 if (sample_type & PERF_SAMPLE_CALLCHAIN)
1079 callchain__printf(evsel, sample); 1086 callchain__printf(evsel, sample);
1080 1087
1081 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !has_branch_callstack(evsel)) 1088 if ((sample_type & PERF_SAMPLE_BRANCH_STACK) && !perf_evsel__has_branch_callstack(evsel))
1082 branch_stack__printf(sample); 1089 branch_stack__printf(sample);
1083 1090
1084 if (sample_type & PERF_SAMPLE_REGS_USER) 1091 if (sample_type & PERF_SAMPLE_REGS_USER)
@@ -1341,6 +1348,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,
1341 return tool->stat(tool, event, session); 1348 return tool->stat(tool, event, session);
1342 case PERF_RECORD_STAT_ROUND: 1349 case PERF_RECORD_STAT_ROUND:
1343 return tool->stat_round(tool, event, session); 1350 return tool->stat_round(tool, event, session);
1351 case PERF_RECORD_TIME_CONV:
1352 session->time_conv = event->time_conv;
1353 return tool->time_conv(tool, event, session);
1344 default: 1354 default:
1345 return -EINVAL; 1355 return -EINVAL;
1346 } 1356 }
@@ -1489,10 +1499,27 @@ int perf_session__register_idle_thread(struct perf_session *session)
1489 return err; 1499 return err;
1490} 1500}
1491 1501
1502static void
1503perf_session__warn_order(const struct perf_session *session)
1504{
1505 const struct ordered_events *oe = &session->ordered_events;
1506 struct perf_evsel *evsel;
1507 bool should_warn = true;
1508
1509 evlist__for_each_entry(session->evlist, evsel) {
1510 if (evsel->attr.write_backward)
1511 should_warn = false;
1512 }
1513
1514 if (!should_warn)
1515 return;
1516 if (oe->nr_unordered_events != 0)
1517 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1518}
1519
1492static void perf_session__warn_about_errors(const struct perf_session *session) 1520static void perf_session__warn_about_errors(const struct perf_session *session)
1493{ 1521{
1494 const struct events_stats *stats = &session->evlist->stats; 1522 const struct events_stats *stats = &session->evlist->stats;
1495 const struct ordered_events *oe = &session->ordered_events;
1496 1523
1497 if (session->tool->lost == perf_event__process_lost && 1524 if (session->tool->lost == perf_event__process_lost &&
1498 stats->nr_events[PERF_RECORD_LOST] != 0) { 1525 stats->nr_events[PERF_RECORD_LOST] != 0) {
@@ -1549,8 +1576,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1549 stats->nr_unprocessable_samples); 1576 stats->nr_unprocessable_samples);
1550 } 1577 }
1551 1578
1552 if (oe->nr_unordered_events != 0) 1579 perf_session__warn_order(session);
1553 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1554 1580
1555 events_stats__auxtrace_error_warn(stats); 1581 events_stats__auxtrace_error_warn(stats);
1556 1582
@@ -1830,7 +1856,11 @@ out:
1830out_err: 1856out_err:
1831 ui_progress__finish(); 1857 ui_progress__finish();
1832 perf_session__warn_about_errors(session); 1858 perf_session__warn_about_errors(session);
1833 ordered_events__free(&session->ordered_events); 1859 /*
1860 * We may switching perf.data output, make ordered_events
1861 * reusable.
1862 */
1863 ordered_events__reinit(&session->ordered_events);
1834 auxtrace__free_events(session); 1864 auxtrace__free_events(session);
1835 session->one_mmap = false; 1865 session->one_mmap = false;
1836 return err; 1866 return err;
@@ -1858,7 +1888,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg)
1858{ 1888{
1859 struct perf_evsel *evsel; 1889 struct perf_evsel *evsel;
1860 1890
1861 evlist__for_each(session->evlist, evsel) { 1891 evlist__for_each_entry(session->evlist, evsel) {
1862 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) 1892 if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
1863 return true; 1893 return true;
1864 } 1894 }
@@ -1940,112 +1970,13 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1940{ 1970{
1941 struct perf_evsel *pos; 1971 struct perf_evsel *pos;
1942 1972
1943 evlist__for_each(session->evlist, pos) { 1973 evlist__for_each_entry(session->evlist, pos) {
1944 if (pos->attr.type == type) 1974 if (pos->attr.type == type)
1945 return pos; 1975 return pos;
1946 } 1976 }
1947 return NULL; 1977 return NULL;
1948} 1978}
1949 1979
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, 1980int perf_session__cpu_bitmap(struct perf_session *session,
2050 const char *cpu_list, unsigned long *cpu_bitmap) 1981 const char *cpu_list, unsigned long *cpu_bitmap)
2051{ 1982{
@@ -2194,7 +2125,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool,
2194 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) / 2125 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
2195 sizeof(struct id_index_entry); 2126 sizeof(struct id_index_entry);
2196 2127
2197 evlist__for_each(evlist, evsel) 2128 evlist__for_each_entry(evlist, evsel)
2198 nr += evsel->ids; 2129 nr += evsel->ids;
2199 2130
2200 n = nr > max_nr ? max_nr : nr; 2131 n = nr > max_nr ? max_nr : nr;
@@ -2207,7 +2138,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool,
2207 ev->id_index.header.size = sz; 2138 ev->id_index.header.size = sz;
2208 ev->id_index.nr = n; 2139 ev->id_index.nr = n;
2209 2140
2210 evlist__for_each(evlist, evsel) { 2141 evlist__for_each_entry(evlist, evsel) {
2211 u32 j; 2142 u32 j;
2212 2143
2213 for (j = 0; j < evsel->ids; j++) { 2144 for (j = 0; j < evsel->ids; j++) {
diff --git a/tools/perf/util/session.h b/tools/perf/util/session.h
index 5f792e35d4c1..4bd758553450 100644
--- a/tools/perf/util/session.h
+++ b/tools/perf/util/session.h
@@ -26,6 +26,7 @@ struct perf_session {
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 {
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);
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
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index f5ba111cd9fb..3d3cb8392c86 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -21,13 +21,6 @@ const char *sort_order;
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/*
@@ -86,8 +79,8 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
86{ 79{
87 const char *comm = thread__comm_str(he->thread); 80 const char *comm = thread__comm_str(he->thread);
88 81
89 width = max(7U, width) - 6; 82 width = max(7U, width) - 8;
90 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid, 83 return repsep_snprintf(bf, size, "%7d:%-*.*s", he->thread->tid,
91 width, width, comm ?: ""); 84 width, width, comm ?: "");
92} 85}
93 86
@@ -102,7 +95,7 @@ static int hist_entry__thread_filter(struct hist_entry *he, int type, const void
102} 95}
103 96
104struct sort_entry sort_thread = { 97struct sort_entry sort_thread = {
105 .se_header = " Pid:Command", 98 .se_header = " Pid:Command",
106 .se_cmp = sort__thread_cmp, 99 .se_cmp = sort__thread_cmp,
107 .se_snprintf = hist_entry__thread_snprintf, 100 .se_snprintf = hist_entry__thread_snprintf,
108 .se_filter = hist_entry__thread_filter, 101 .se_filter = hist_entry__thread_filter,
@@ -244,7 +237,7 @@ sort__sym_cmp(struct hist_entry *left, struct hist_entry *right)
244 * comparing symbol address alone is not enough since it's a 237 * 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;
@@ -360,6 +353,88 @@ struct sort_entry sort_srcline = {
360 .se_width_idx = HISTC_SRCLINE, 353 .se_width_idx = HISTC_SRCLINE,
361}; 354};
362 355
356/* --sort srcline_from */
357
358static int64_t
359sort__srcline_from_cmp(struct hist_entry *left, struct hist_entry *right)
360{
361 if (!left->branch_info->srcline_from) {
362 struct map *map = left->branch_info->from.map;
363 if (!map)
364 left->branch_info->srcline_from = SRCLINE_UNKNOWN;
365 else
366 left->branch_info->srcline_from = get_srcline(map->dso,
367 map__rip_2objdump(map,
368 left->branch_info->from.al_addr),
369 left->branch_info->from.sym, true);
370 }
371 if (!right->branch_info->srcline_from) {
372 struct map *map = right->branch_info->from.map;
373 if (!map)
374 right->branch_info->srcline_from = SRCLINE_UNKNOWN;
375 else
376 right->branch_info->srcline_from = get_srcline(map->dso,
377 map__rip_2objdump(map,
378 right->branch_info->from.al_addr),
379 right->branch_info->from.sym, true);
380 }
381 return strcmp(right->branch_info->srcline_from, left->branch_info->srcline_from);
382}
383
384static int hist_entry__srcline_from_snprintf(struct hist_entry *he, char *bf,
385 size_t size, unsigned int width)
386{
387 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_from);
388}
389
390struct sort_entry sort_srcline_from = {
391 .se_header = "From Source:Line",
392 .se_cmp = sort__srcline_from_cmp,
393 .se_snprintf = hist_entry__srcline_from_snprintf,
394 .se_width_idx = HISTC_SRCLINE_FROM,
395};
396
397/* --sort srcline_to */
398
399static int64_t
400sort__srcline_to_cmp(struct hist_entry *left, struct hist_entry *right)
401{
402 if (!left->branch_info->srcline_to) {
403 struct map *map = left->branch_info->to.map;
404 if (!map)
405 left->branch_info->srcline_to = SRCLINE_UNKNOWN;
406 else
407 left->branch_info->srcline_to = get_srcline(map->dso,
408 map__rip_2objdump(map,
409 left->branch_info->to.al_addr),
410 left->branch_info->from.sym, true);
411 }
412 if (!right->branch_info->srcline_to) {
413 struct map *map = right->branch_info->to.map;
414 if (!map)
415 right->branch_info->srcline_to = SRCLINE_UNKNOWN;
416 else
417 right->branch_info->srcline_to = get_srcline(map->dso,
418 map__rip_2objdump(map,
419 right->branch_info->to.al_addr),
420 right->branch_info->to.sym, true);
421 }
422 return strcmp(right->branch_info->srcline_to, left->branch_info->srcline_to);
423}
424
425static int hist_entry__srcline_to_snprintf(struct hist_entry *he, char *bf,
426 size_t size, unsigned int width)
427{
428 return repsep_snprintf(bf, size, "%-*.*s", width, width, he->branch_info->srcline_to);
429}
430
431struct sort_entry sort_srcline_to = {
432 .se_header = "To Source:Line",
433 .se_cmp = sort__srcline_to_cmp,
434 .se_snprintf = hist_entry__srcline_to_snprintf,
435 .se_width_idx = HISTC_SRCLINE_TO,
436};
437
363/* --sort srcfile */ 438/* --sort srcfile */
364 439
365static char no_srcfile[1]; 440static char no_srcfile[1];
@@ -513,7 +588,11 @@ static char *get_trace_output(struct hist_entry *he)
513 } else { 588 } else {
514 pevent_event_info(&seq, evsel->tp_format, &rec); 589 pevent_event_info(&seq, evsel->tp_format, &rec);
515 } 590 }
516 return seq.buffer; 591 /*
592 * Trim the buffer, it starts at 4KB and we're not going to
593 * add anything more to this buffer.
594 */
595 return realloc(seq.buffer, seq.len + 1);
517} 596}
518 597
519static int64_t 598static int64_t
@@ -1143,7 +1222,7 @@ struct sort_entry sort_mem_daddr_dso = {
1143 .se_header = "Data Object", 1222 .se_header = "Data Object",
1144 .se_cmp = sort__dso_daddr_cmp, 1223 .se_cmp = sort__dso_daddr_cmp,
1145 .se_snprintf = hist_entry__dso_daddr_snprintf, 1224 .se_snprintf = hist_entry__dso_daddr_snprintf,
1146 .se_width_idx = HISTC_MEM_DADDR_SYMBOL, 1225 .se_width_idx = HISTC_MEM_DADDR_DSO,
1147}; 1226};
1148 1227
1149struct sort_entry sort_mem_locked = { 1228struct sort_entry sort_mem_locked = {
@@ -1354,6 +1433,8 @@ static struct sort_dimension bstack_sort_dimensions[] = {
1354 DIM(SORT_IN_TX, "in_tx", sort_in_tx), 1433 DIM(SORT_IN_TX, "in_tx", sort_in_tx),
1355 DIM(SORT_ABORT, "abort", sort_abort), 1434 DIM(SORT_ABORT, "abort", sort_abort),
1356 DIM(SORT_CYCLES, "cycles", sort_cycles), 1435 DIM(SORT_CYCLES, "cycles", sort_cycles),
1436 DIM(SORT_SRCLINE_FROM, "srcline_from", sort_srcline_from),
1437 DIM(SORT_SRCLINE_TO, "srcline_to", sort_srcline_to),
1357}; 1438};
1358 1439
1359#undef DIM 1440#undef DIM
@@ -1411,7 +1492,7 @@ void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1411} 1492}
1412 1493
1413static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1494static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1414 struct perf_evsel *evsel) 1495 struct hists *hists)
1415{ 1496{
1416 struct hpp_sort_entry *hse; 1497 struct hpp_sort_entry *hse;
1417 size_t len = fmt->user_len; 1498 size_t len = fmt->user_len;
@@ -1419,14 +1500,14 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1419 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1500 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1420 1501
1421 if (!len) 1502 if (!len)
1422 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); 1503 len = hists__col_len(hists, hse->se->se_width_idx);
1423 1504
1424 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name); 1505 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1425} 1506}
1426 1507
1427static int __sort__hpp_width(struct perf_hpp_fmt *fmt, 1508static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1428 struct perf_hpp *hpp __maybe_unused, 1509 struct perf_hpp *hpp __maybe_unused,
1429 struct perf_evsel *evsel) 1510 struct hists *hists)
1430{ 1511{
1431 struct hpp_sort_entry *hse; 1512 struct hpp_sort_entry *hse;
1432 size_t len = fmt->user_len; 1513 size_t len = fmt->user_len;
@@ -1434,7 +1515,7 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1434 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1515 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1435 1516
1436 if (!len) 1517 if (!len)
1437 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); 1518 len = hists__col_len(hists, hse->se->se_width_idx);
1438 1519
1439 return len; 1520 return len;
1440} 1521}
@@ -1716,7 +1797,7 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1716} 1797}
1717 1798
1718static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1799static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1719 struct perf_evsel *evsel __maybe_unused) 1800 struct hists *hists __maybe_unused)
1720{ 1801{
1721 struct hpp_dynamic_entry *hde; 1802 struct hpp_dynamic_entry *hde;
1722 size_t len = fmt->user_len; 1803 size_t len = fmt->user_len;
@@ -1731,7 +1812,7 @@ static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1731 1812
1732static int __sort__hde_width(struct perf_hpp_fmt *fmt, 1813static int __sort__hde_width(struct perf_hpp_fmt *fmt,
1733 struct perf_hpp *hpp __maybe_unused, 1814 struct perf_hpp *hpp __maybe_unused,
1734 struct perf_evsel *evsel __maybe_unused) 1815 struct hists *hists __maybe_unused)
1735{ 1816{
1736 struct hpp_dynamic_entry *hde; 1817 struct hpp_dynamic_entry *hde;
1737 size_t len = fmt->user_len; 1818 size_t len = fmt->user_len;
@@ -1992,7 +2073,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
1992 } 2073 }
1993 2074
1994 full_name = !!strchr(event_name, ':'); 2075 full_name = !!strchr(event_name, ':');
1995 evlist__for_each(evlist, pos) { 2076 evlist__for_each_entry(evlist, pos) {
1996 /* case 2 */ 2077 /* case 2 */
1997 if (full_name && !strcmp(pos->name, event_name)) 2078 if (full_name && !strcmp(pos->name, event_name))
1998 return pos; 2079 return pos;
@@ -2048,7 +2129,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
2048 int ret; 2129 int ret;
2049 struct perf_evsel *evsel; 2130 struct perf_evsel *evsel;
2050 2131
2051 evlist__for_each(evlist, evsel) { 2132 evlist__for_each_entry(evlist, evsel) {
2052 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2133 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
2053 continue; 2134 continue;
2054 2135
@@ -2066,7 +2147,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
2066 struct perf_evsel *evsel; 2147 struct perf_evsel *evsel;
2067 struct format_field *field; 2148 struct format_field *field;
2068 2149
2069 evlist__for_each(evlist, evsel) { 2150 evlist__for_each_entry(evlist, evsel) {
2070 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2151 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
2071 continue; 2152 continue;
2072 2153
@@ -2163,7 +2244,7 @@ static int __sort_dimension__add(struct sort_dimension *sd,
2163 return -1; 2244 return -1;
2164 2245
2165 if (sd->entry->se_collapse) 2246 if (sd->entry->se_collapse)
2166 sort__need_collapse = 1; 2247 list->need_collapse = 1;
2167 2248
2168 sd->taken = 1; 2249 sd->taken = 1;
2169 2250
@@ -2245,9 +2326,9 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2245 pr_err("Invalid regex: %s\n%s", parent_pattern, err); 2326 pr_err("Invalid regex: %s\n%s", parent_pattern, err);
2246 return -EINVAL; 2327 return -EINVAL;
2247 } 2328 }
2248 sort__has_parent = 1; 2329 list->parent = 1;
2249 } else if (sd->entry == &sort_sym) { 2330 } else if (sd->entry == &sort_sym) {
2250 sort__has_sym = 1; 2331 list->sym = 1;
2251 /* 2332 /*
2252 * perf diff displays the performance difference amongst 2333 * perf diff displays the performance difference amongst
2253 * two or more perf.data files. Those files could come 2334 * two or more perf.data files. Those files could come
@@ -2258,13 +2339,13 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2258 sd->entry->se_collapse = sort__sym_sort; 2339 sd->entry->se_collapse = sort__sym_sort;
2259 2340
2260 } else if (sd->entry == &sort_dso) { 2341 } else if (sd->entry == &sort_dso) {
2261 sort__has_dso = 1; 2342 list->dso = 1;
2262 } else if (sd->entry == &sort_socket) { 2343 } else if (sd->entry == &sort_socket) {
2263 sort__has_socket = 1; 2344 list->socket = 1;
2264 } else if (sd->entry == &sort_thread) { 2345 } else if (sd->entry == &sort_thread) {
2265 sort__has_thread = 1; 2346 list->thread = 1;
2266 } else if (sd->entry == &sort_comm) { 2347 } else if (sd->entry == &sort_comm) {
2267 sort__has_comm = 1; 2348 list->comm = 1;
2268 } 2349 }
2269 2350
2270 return __sort_dimension__add(sd, list, level); 2351 return __sort_dimension__add(sd, list, level);
@@ -2289,7 +2370,7 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2289 return -EINVAL; 2370 return -EINVAL;
2290 2371
2291 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to) 2372 if (sd->entry == &sort_sym_from || sd->entry == &sort_sym_to)
2292 sort__has_sym = 1; 2373 list->sym = 1;
2293 2374
2294 __sort_dimension__add(sd, list, level); 2375 __sort_dimension__add(sd, list, level);
2295 return 0; 2376 return 0;
@@ -2304,8 +2385,11 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2304 if (sort__mode != SORT_MODE__MEMORY) 2385 if (sort__mode != SORT_MODE__MEMORY)
2305 return -EINVAL; 2386 return -EINVAL;
2306 2387
2388 if (sd->entry == &sort_mem_dcacheline && cacheline_size == 0)
2389 return -EINVAL;
2390
2307 if (sd->entry == &sort_mem_daddr_sym) 2391 if (sd->entry == &sort_mem_daddr_sym)
2308 sort__has_sym = 1; 2392 list->sym = 1;
2309 2393
2310 __sort_dimension__add(sd, list, level); 2394 __sort_dimension__add(sd, list, level);
2311 return 0; 2395 return 0;
@@ -2347,7 +2431,10 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
2347 if (*tok) { 2431 if (*tok) {
2348 ret = sort_dimension__add(list, tok, evlist, level); 2432 ret = sort_dimension__add(list, tok, evlist, level);
2349 if (ret == -EINVAL) { 2433 if (ret == -EINVAL) {
2350 error("Invalid --sort key: `%s'", tok); 2434 if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok)))
2435 error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
2436 else
2437 error("Invalid --sort key: `%s'", tok);
2351 break; 2438 break;
2352 } else if (ret == -ESRCH) { 2439 } else if (ret == -ESRCH) {
2353 error("Unknown --sort key: `%s'", tok); 2440 error("Unknown --sort key: `%s'", tok);
@@ -2379,7 +2466,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
2379 if (evlist == NULL) 2466 if (evlist == NULL)
2380 goto out_no_evlist; 2467 goto out_no_evlist;
2381 2468
2382 evlist__for_each(evlist, evsel) { 2469 evlist__for_each_entry(evlist, evsel) {
2383 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { 2470 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2384 use_trace = false; 2471 use_trace = false;
2385 break; 2472 break;
@@ -2749,10 +2836,10 @@ int setup_sorting(struct perf_evlist *evlist)
2749 2836
2750void reset_output_field(void) 2837void reset_output_field(void)
2751{ 2838{
2752 sort__need_collapse = 0; 2839 perf_hpp_list.need_collapse = 0;
2753 sort__has_parent = 0; 2840 perf_hpp_list.parent = 0;
2754 sort__has_sym = 0; 2841 perf_hpp_list.sym = 0;
2755 sort__has_dso = 0; 2842 perf_hpp_list.dso = 0;
2756 2843
2757 field_order = NULL; 2844 field_order = NULL;
2758 sort_order = NULL; 2845 sort_order = NULL;
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index 3f4e35998119..7ca37ea17395 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -31,13 +31,6 @@ extern const char *parent_pattern;
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;
@@ -74,6 +67,11 @@ struct hist_entry_diff {
74 }; 67 };
75}; 68};
76 69
70struct hist_entry_ops {
71 void *(*new)(size_t size);
72 void (*free)(void *ptr);
73};
74
77/** 75/**
78 * struct hist_entry - histogram entry 76 * struct hist_entry - histogram entry
79 * 77 *
@@ -132,6 +130,7 @@ struct hist_entry {
132 void *trace_output; 130 void *trace_output;
133 struct perf_hpp_list *hpp_list; 131 struct perf_hpp_list *hpp_list;
134 struct hist_entry *parent_he; 132 struct hist_entry *parent_he;
133 struct hist_entry_ops *ops;
135 union { 134 union {
136 /* this is for hierarchical entry structure */ 135 /* this is for hierarchical entry structure */
137 struct { 136 struct {
@@ -222,6 +221,8 @@ enum sort_type {
222 SORT_ABORT, 221 SORT_ABORT,
223 SORT_IN_TX, 222 SORT_IN_TX,
224 SORT_CYCLES, 223 SORT_CYCLES,
224 SORT_SRCLINE_FROM,
225 SORT_SRCLINE_TO,
225 226
226 /* memory mode specific sort keys */ 227 /* memory mode specific sort keys */
227 __SORT_MEMORY_MODE, 228 __SORT_MEMORY_MODE,
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index fdb71961143e..8a2bbd2a4d82 100644
--- a/tools/perf/util/stat-shadow.c
+++ b/tools/perf/util/stat-shadow.c
@@ -36,6 +36,11 @@ static struct stats runtime_dtlb_cache_stats[NUM_CTX][MAX_NR_CPUS];
36static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS]; 36static struct stats runtime_cycles_in_tx_stats[NUM_CTX][MAX_NR_CPUS];
37static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS]; 37static struct stats runtime_transaction_stats[NUM_CTX][MAX_NR_CPUS];
38static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS]; 38static struct stats runtime_elision_stats[NUM_CTX][MAX_NR_CPUS];
39static struct stats runtime_topdown_total_slots[NUM_CTX][MAX_NR_CPUS];
40static struct stats runtime_topdown_slots_issued[NUM_CTX][MAX_NR_CPUS];
41static struct stats runtime_topdown_slots_retired[NUM_CTX][MAX_NR_CPUS];
42static struct stats runtime_topdown_fetch_bubbles[NUM_CTX][MAX_NR_CPUS];
43static struct stats runtime_topdown_recovery_bubbles[NUM_CTX][MAX_NR_CPUS];
39static bool have_frontend_stalled; 44static bool have_frontend_stalled;
40 45
41struct stats walltime_nsecs_stats; 46struct stats walltime_nsecs_stats;
@@ -82,6 +87,11 @@ void perf_stat__reset_shadow_stats(void)
82 sizeof(runtime_transaction_stats)); 87 sizeof(runtime_transaction_stats));
83 memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats)); 88 memset(runtime_elision_stats, 0, sizeof(runtime_elision_stats));
84 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats)); 89 memset(&walltime_nsecs_stats, 0, sizeof(walltime_nsecs_stats));
90 memset(runtime_topdown_total_slots, 0, sizeof(runtime_topdown_total_slots));
91 memset(runtime_topdown_slots_retired, 0, sizeof(runtime_topdown_slots_retired));
92 memset(runtime_topdown_slots_issued, 0, sizeof(runtime_topdown_slots_issued));
93 memset(runtime_topdown_fetch_bubbles, 0, sizeof(runtime_topdown_fetch_bubbles));
94 memset(runtime_topdown_recovery_bubbles, 0, sizeof(runtime_topdown_recovery_bubbles));
85} 95}
86 96
87/* 97/*
@@ -94,7 +104,8 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
94{ 104{
95 int ctx = evsel_context(counter); 105 int ctx = evsel_context(counter);
96 106
97 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK)) 107 if (perf_evsel__match(counter, SOFTWARE, SW_TASK_CLOCK) ||
108 perf_evsel__match(counter, SOFTWARE, SW_CPU_CLOCK))
98 update_stats(&runtime_nsecs_stats[cpu], count[0]); 109 update_stats(&runtime_nsecs_stats[cpu], count[0]);
99 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES)) 110 else if (perf_evsel__match(counter, HARDWARE, HW_CPU_CYCLES))
100 update_stats(&runtime_cycles_stats[ctx][cpu], count[0]); 111 update_stats(&runtime_cycles_stats[ctx][cpu], count[0]);
@@ -104,6 +115,16 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
104 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); 115 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
105 else if (perf_stat_evsel__is(counter, ELISION_START)) 116 else if (perf_stat_evsel__is(counter, ELISION_START))
106 update_stats(&runtime_elision_stats[ctx][cpu], count[0]); 117 update_stats(&runtime_elision_stats[ctx][cpu], count[0]);
118 else if (perf_stat_evsel__is(counter, TOPDOWN_TOTAL_SLOTS))
119 update_stats(&runtime_topdown_total_slots[ctx][cpu], count[0]);
120 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_ISSUED))
121 update_stats(&runtime_topdown_slots_issued[ctx][cpu], count[0]);
122 else if (perf_stat_evsel__is(counter, TOPDOWN_SLOTS_RETIRED))
123 update_stats(&runtime_topdown_slots_retired[ctx][cpu], count[0]);
124 else if (perf_stat_evsel__is(counter, TOPDOWN_FETCH_BUBBLES))
125 update_stats(&runtime_topdown_fetch_bubbles[ctx][cpu],count[0]);
126 else if (perf_stat_evsel__is(counter, TOPDOWN_RECOVERY_BUBBLES))
127 update_stats(&runtime_topdown_recovery_bubbles[ctx][cpu], count[0]);
107 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 128 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
108 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]); 129 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]);
109 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 130 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
@@ -188,7 +209,7 @@ static void print_stalled_cycles_backend(int cpu,
188 209
189 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio); 210 color = get_ratio_color(GRC_STALLED_CYCLES_BE, ratio);
190 211
191 out->print_metric(out->ctx, color, "%6.2f%%", "backend cycles idle", ratio); 212 out->print_metric(out->ctx, color, "%7.2f%%", "backend cycles idle", ratio);
192} 213}
193 214
194static void print_branch_misses(int cpu, 215static void print_branch_misses(int cpu,
@@ -301,6 +322,107 @@ static void print_ll_cache_misses(int cpu,
301 out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio); 322 out->print_metric(out->ctx, color, "%7.2f%%", "of all LL-cache hits", ratio);
302} 323}
303 324
325/*
326 * High level "TopDown" CPU core pipe line bottleneck break down.
327 *
328 * Basic concept following
329 * Yasin, A Top Down Method for Performance analysis and Counter architecture
330 * ISPASS14
331 *
332 * The CPU pipeline is divided into 4 areas that can be bottlenecks:
333 *
334 * Frontend -> Backend -> Retiring
335 * BadSpeculation in addition means out of order execution that is thrown away
336 * (for example branch mispredictions)
337 * Frontend is instruction decoding.
338 * Backend is execution, like computation and accessing data in memory
339 * Retiring is good execution that is not directly bottlenecked
340 *
341 * The formulas are computed in slots.
342 * A slot is an entry in the pipeline each for the pipeline width
343 * (for example a 4-wide pipeline has 4 slots for each cycle)
344 *
345 * Formulas:
346 * BadSpeculation = ((SlotsIssued - SlotsRetired) + RecoveryBubbles) /
347 * TotalSlots
348 * Retiring = SlotsRetired / TotalSlots
349 * FrontendBound = FetchBubbles / TotalSlots
350 * BackendBound = 1.0 - BadSpeculation - Retiring - FrontendBound
351 *
352 * The kernel provides the mapping to the low level CPU events and any scaling
353 * needed for the CPU pipeline width, for example:
354 *
355 * TotalSlots = Cycles * 4
356 *
357 * The scaling factor is communicated in the sysfs unit.
358 *
359 * In some cases the CPU may not be able to measure all the formulas due to
360 * missing events. In this case multiple formulas are combined, as possible.
361 *
362 * Full TopDown supports more levels to sub-divide each area: for example
363 * BackendBound into computing bound and memory bound. For now we only
364 * support Level 1 TopDown.
365 */
366
367static double sanitize_val(double x)
368{
369 if (x < 0 && x >= -0.02)
370 return 0.0;
371 return x;
372}
373
374static double td_total_slots(int ctx, int cpu)
375{
376 return avg_stats(&runtime_topdown_total_slots[ctx][cpu]);
377}
378
379static double td_bad_spec(int ctx, int cpu)
380{
381 double bad_spec = 0;
382 double total_slots;
383 double total;
384
385 total = avg_stats(&runtime_topdown_slots_issued[ctx][cpu]) -
386 avg_stats(&runtime_topdown_slots_retired[ctx][cpu]) +
387 avg_stats(&runtime_topdown_recovery_bubbles[ctx][cpu]);
388 total_slots = td_total_slots(ctx, cpu);
389 if (total_slots)
390 bad_spec = total / total_slots;
391 return sanitize_val(bad_spec);
392}
393
394static double td_retiring(int ctx, int cpu)
395{
396 double retiring = 0;
397 double total_slots = td_total_slots(ctx, cpu);
398 double ret_slots = avg_stats(&runtime_topdown_slots_retired[ctx][cpu]);
399
400 if (total_slots)
401 retiring = ret_slots / total_slots;
402 return retiring;
403}
404
405static double td_fe_bound(int ctx, int cpu)
406{
407 double fe_bound = 0;
408 double total_slots = td_total_slots(ctx, cpu);
409 double fetch_bub = avg_stats(&runtime_topdown_fetch_bubbles[ctx][cpu]);
410
411 if (total_slots)
412 fe_bound = fetch_bub / total_slots;
413 return fe_bound;
414}
415
416static double td_be_bound(int ctx, int cpu)
417{
418 double sum = (td_fe_bound(ctx, cpu) +
419 td_bad_spec(ctx, cpu) +
420 td_retiring(ctx, cpu));
421 if (sum == 0)
422 return 0;
423 return sanitize_val(1.0 - sum);
424}
425
304void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 426void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
305 double avg, int cpu, 427 double avg, int cpu,
306 struct perf_stat_output_ctx *out) 428 struct perf_stat_output_ctx *out)
@@ -308,6 +430,7 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
308 void *ctxp = out->ctx; 430 void *ctxp = out->ctx;
309 print_metric_t print_metric = out->print_metric; 431 print_metric_t print_metric = out->print_metric;
310 double total, ratio = 0.0, total2; 432 double total, ratio = 0.0, total2;
433 const char *color = NULL;
311 int ctx = evsel_context(evsel); 434 int ctx = evsel_context(evsel);
312 435
313 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 436 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
@@ -444,12 +567,53 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
444 ratio = total / avg; 567 ratio = total / avg;
445 568
446 print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio); 569 print_metric(ctxp, NULL, "%8.0f", "cycles / elision", ratio);
447 } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK)) { 570 } else if (perf_evsel__match(evsel, SOFTWARE, SW_TASK_CLOCK) ||
571 perf_evsel__match(evsel, SOFTWARE, SW_CPU_CLOCK)) {
448 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0) 572 if ((ratio = avg_stats(&walltime_nsecs_stats)) != 0)
449 print_metric(ctxp, NULL, "%8.3f", "CPUs utilized", 573 print_metric(ctxp, NULL, "%8.3f", "CPUs utilized",
450 avg / ratio); 574 avg / ratio);
451 else 575 else
452 print_metric(ctxp, NULL, NULL, "CPUs utilized", 0); 576 print_metric(ctxp, NULL, NULL, "CPUs utilized", 0);
577 } else if (perf_stat_evsel__is(evsel, TOPDOWN_FETCH_BUBBLES)) {
578 double fe_bound = td_fe_bound(ctx, cpu);
579
580 if (fe_bound > 0.2)
581 color = PERF_COLOR_RED;
582 print_metric(ctxp, color, "%8.1f%%", "frontend bound",
583 fe_bound * 100.);
584 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_RETIRED)) {
585 double retiring = td_retiring(ctx, cpu);
586
587 if (retiring > 0.7)
588 color = PERF_COLOR_GREEN;
589 print_metric(ctxp, color, "%8.1f%%", "retiring",
590 retiring * 100.);
591 } else if (perf_stat_evsel__is(evsel, TOPDOWN_RECOVERY_BUBBLES)) {
592 double bad_spec = td_bad_spec(ctx, cpu);
593
594 if (bad_spec > 0.1)
595 color = PERF_COLOR_RED;
596 print_metric(ctxp, color, "%8.1f%%", "bad speculation",
597 bad_spec * 100.);
598 } else if (perf_stat_evsel__is(evsel, TOPDOWN_SLOTS_ISSUED)) {
599 double be_bound = td_be_bound(ctx, cpu);
600 const char *name = "backend bound";
601 static int have_recovery_bubbles = -1;
602
603 /* In case the CPU does not support topdown-recovery-bubbles */
604 if (have_recovery_bubbles < 0)
605 have_recovery_bubbles = pmu_have_event("cpu",
606 "topdown-recovery-bubbles");
607 if (!have_recovery_bubbles)
608 name = "backend bound/bad spec";
609
610 if (be_bound > 0.2)
611 color = PERF_COLOR_RED;
612 if (td_total_slots(ctx, cpu) > 0)
613 print_metric(ctxp, color, "%8.1f%%", name,
614 be_bound * 100.);
615 else
616 print_metric(ctxp, NULL, NULL, name, 0);
453 } else if (runtime_nsecs_stats[cpu].n != 0) { 617 } else if (runtime_nsecs_stats[cpu].n != 0) {
454 char unit = 'M'; 618 char unit = 'M';
455 char unit_buf[10]; 619 char unit_buf[10];
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index 4d9b481cf3b6..39345c2ddfc2 100644
--- a/tools/perf/util/stat.c
+++ b/tools/perf/util/stat.c
@@ -79,6 +79,11 @@ static const char *id_str[PERF_STAT_EVSEL_ID__MAX] = {
79 ID(TRANSACTION_START, cpu/tx-start/), 79 ID(TRANSACTION_START, cpu/tx-start/),
80 ID(ELISION_START, cpu/el-start/), 80 ID(ELISION_START, cpu/el-start/),
81 ID(CYCLES_IN_TX_CP, cpu/cycles-ct/), 81 ID(CYCLES_IN_TX_CP, cpu/cycles-ct/),
82 ID(TOPDOWN_TOTAL_SLOTS, topdown-total-slots),
83 ID(TOPDOWN_SLOTS_ISSUED, topdown-slots-issued),
84 ID(TOPDOWN_SLOTS_RETIRED, topdown-slots-retired),
85 ID(TOPDOWN_FETCH_BUBBLES, topdown-fetch-bubbles),
86 ID(TOPDOWN_RECOVERY_BUBBLES, topdown-recovery-bubbles),
82}; 87};
83#undef ID 88#undef ID
84 89
@@ -157,7 +162,7 @@ int perf_evlist__alloc_stats(struct perf_evlist *evlist, bool alloc_raw)
157{ 162{
158 struct perf_evsel *evsel; 163 struct perf_evsel *evsel;
159 164
160 evlist__for_each(evlist, evsel) { 165 evlist__for_each_entry(evlist, evsel) {
161 if (perf_evsel__alloc_stats(evsel, alloc_raw)) 166 if (perf_evsel__alloc_stats(evsel, alloc_raw))
162 goto out_free; 167 goto out_free;
163 } 168 }
@@ -173,7 +178,7 @@ void perf_evlist__free_stats(struct perf_evlist *evlist)
173{ 178{
174 struct perf_evsel *evsel; 179 struct perf_evsel *evsel;
175 180
176 evlist__for_each(evlist, evsel) { 181 evlist__for_each_entry(evlist, evsel) {
177 perf_evsel__free_stat_priv(evsel); 182 perf_evsel__free_stat_priv(evsel);
178 perf_evsel__free_counts(evsel); 183 perf_evsel__free_counts(evsel);
179 perf_evsel__free_prev_raw_counts(evsel); 184 perf_evsel__free_prev_raw_counts(evsel);
@@ -184,7 +189,7 @@ void perf_evlist__reset_stats(struct perf_evlist *evlist)
184{ 189{
185 struct perf_evsel *evsel; 190 struct perf_evsel *evsel;
186 191
187 evlist__for_each(evlist, evsel) { 192 evlist__for_each_entry(evlist, evsel) {
188 perf_evsel__reset_stat_priv(evsel); 193 perf_evsel__reset_stat_priv(evsel);
189 perf_evsel__reset_counts(evsel); 194 perf_evsel__reset_counts(evsel);
190 } 195 }
@@ -307,6 +312,7 @@ int perf_stat_process_counter(struct perf_stat_config *config,
307 struct perf_counts_values *aggr = &counter->counts->aggr; 312 struct perf_counts_values *aggr = &counter->counts->aggr;
308 struct perf_stat_evsel *ps = counter->priv; 313 struct perf_stat_evsel *ps = counter->priv;
309 u64 *count = counter->counts->aggr.values; 314 u64 *count = counter->counts->aggr.values;
315 u64 val;
310 int i, ret; 316 int i, ret;
311 317
312 aggr->val = aggr->ena = aggr->run = 0; 318 aggr->val = aggr->ena = aggr->run = 0;
@@ -346,7 +352,8 @@ int perf_stat_process_counter(struct perf_stat_config *config,
346 /* 352 /*
347 * Save the full runtime - to allow normalization during printout: 353 * Save the full runtime - to allow normalization during printout:
348 */ 354 */
349 perf_stat__update_shadow_stats(counter, count, 0); 355 val = counter->scale * *count;
356 perf_stat__update_shadow_stats(counter, &val, 0);
350 357
351 return 0; 358 return 0;
352} 359}
diff --git a/tools/perf/util/stat.h b/tools/perf/util/stat.h
index 0150e786ccc7..c29bb94c48a4 100644
--- a/tools/perf/util/stat.h
+++ b/tools/perf/util/stat.h
@@ -17,6 +17,11 @@ enum perf_stat_evsel_id {
17 PERF_STAT_EVSEL_ID__TRANSACTION_START, 17 PERF_STAT_EVSEL_ID__TRANSACTION_START,
18 PERF_STAT_EVSEL_ID__ELISION_START, 18 PERF_STAT_EVSEL_ID__ELISION_START,
19 PERF_STAT_EVSEL_ID__CYCLES_IN_TX_CP, 19 PERF_STAT_EVSEL_ID__CYCLES_IN_TX_CP,
20 PERF_STAT_EVSEL_ID__TOPDOWN_TOTAL_SLOTS,
21 PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_ISSUED,
22 PERF_STAT_EVSEL_ID__TOPDOWN_SLOTS_RETIRED,
23 PERF_STAT_EVSEL_ID__TOPDOWN_FETCH_BUBBLES,
24 PERF_STAT_EVSEL_ID__TOPDOWN_RECOVERY_BUBBLES,
20 PERF_STAT_EVSEL_ID__MAX, 25 PERF_STAT_EVSEL_ID__MAX,
21}; 26};
22 27
diff --git a/tools/perf/util/strbuf.c b/tools/perf/util/strbuf.c
index 8fb73295ec34..817593908d47 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -1,4 +1,5 @@
1#include "cache.h" 1#include "debug.h"
2#include "util.h"
2#include <linux/kernel.h> 3#include <linux/kernel.h>
3 4
4int prefixcmp(const char *str, const char *prefix) 5int prefixcmp(const char *str, const char *prefix)
@@ -17,12 +18,13 @@ int prefixcmp(const char *str, const char *prefix)
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)
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)
112 strbuf_release(sb); 151 strbuf_release(sb);
113 else 152 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';
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index ab9be0fbbd40..b268a6648a5d 100644
--- a/tools/perf/util/strbuf.h
+++ b/tools/perf/util/strbuf.h
@@ -40,6 +40,9 @@
40 40
41#include <assert.h> 41#include <assert.h>
42#include <stdarg.h> 42#include <stdarg.h>
43#include <stddef.h>
44#include <string.h>
45#include <sys/types.h>
43 46
44extern char strbuf_slopbuf[]; 47extern char strbuf_slopbuf[];
45struct strbuf { 48struct strbuf {
@@ -51,7 +54,7 @@ struct strbuf {
51#define STRBUF_INIT { 0, 0, strbuf_slopbuf } 54#define STRBUF_INIT { 0, 0, strbuf_slopbuf }
52 55
53/*----- strbuf life cycle -----*/ 56/*----- strbuf life cycle -----*/
54void strbuf_init(struct strbuf *buf, ssize_t hint); 57int strbuf_init(struct strbuf *buf, ssize_t hint);
55void strbuf_release(struct strbuf *buf); 58void strbuf_release(struct strbuf *buf);
56char *strbuf_detach(struct strbuf *buf, size_t *); 59char *strbuf_detach(struct strbuf *buf, size_t *);
57 60
@@ -60,26 +63,31 @@ static inline ssize_t strbuf_avail(const struct strbuf *sb) {
60 return sb->alloc ? sb->alloc - sb->len - 1 : 0; 63 return sb->alloc ? sb->alloc - sb->len - 1 : 0;
61} 64}
62 65
63void strbuf_grow(struct strbuf *buf, size_t); 66int strbuf_grow(struct strbuf *buf, size_t);
64 67
65static inline void strbuf_setlen(struct strbuf *sb, size_t len) { 68static inline int strbuf_setlen(struct strbuf *sb, size_t len) {
66 if (!sb->alloc) 69 int ret;
67 strbuf_grow(sb, 0); 70 if (!sb->alloc) {
71 ret = strbuf_grow(sb, 0);
72 if (ret)
73 return ret;
74 }
68 assert(len < sb->alloc); 75 assert(len < sb->alloc);
69 sb->len = len; 76 sb->len = len;
70 sb->buf[len] = '\0'; 77 sb->buf[len] = '\0';
78 return 0;
71} 79}
72 80
73/*----- add data in your buffer -----*/ 81/*----- add data in your buffer -----*/
74void strbuf_addch(struct strbuf *sb, int c); 82int strbuf_addch(struct strbuf *sb, int c);
75 83
76void strbuf_add(struct strbuf *buf, const void *, size_t); 84int strbuf_add(struct strbuf *buf, const void *, size_t);
77static inline void strbuf_addstr(struct strbuf *sb, const char *s) { 85static inline int strbuf_addstr(struct strbuf *sb, const char *s) {
78 strbuf_add(sb, s, strlen(s)); 86 return strbuf_add(sb, s, strlen(s));
79} 87}
80 88
81__attribute__((format(printf,2,3))) 89__attribute__((format(printf,2,3)))
82void strbuf_addf(struct strbuf *sb, const char *fmt, ...); 90int strbuf_addf(struct strbuf *sb, const char *fmt, ...);
83 91
84/* XXX: if read fails, any partial read is undone */ 92/* XXX: if read fails, any partial read is undone */
85ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint); 93ssize_t strbuf_read(struct strbuf *, int fd, ssize_t hint);
diff --git a/tools/perf/util/strlist.h b/tools/perf/util/strlist.h
index ca990029e243..19207e50fce5 100644
--- a/tools/perf/util/strlist.h
+++ b/tools/perf/util/strlist.h
@@ -73,7 +73,7 @@ static inline struct str_node *strlist__next(struct str_node *sn)
73 * @pos: the &struct str_node to use as a loop cursor. 73 * @pos: the &struct str_node to use as a loop cursor.
74 * @slist: the &struct strlist for loop. 74 * @slist: the &struct strlist for loop.
75 */ 75 */
76#define strlist__for_each(pos, slist) \ 76#define strlist__for_each_entry(pos, slist) \
77 for (pos = strlist__first(slist); pos; pos = strlist__next(pos)) 77 for (pos = strlist__first(slist); pos; pos = strlist__next(pos))
78 78
79/** 79/**
@@ -83,7 +83,7 @@ static inline struct str_node *strlist__next(struct str_node *sn)
83 * @n: another &struct str_node to use as temporary storage. 83 * @n: another &struct str_node to use as temporary storage.
84 * @slist: the &struct strlist for loop. 84 * @slist: the &struct strlist for loop.
85 */ 85 */
86#define strlist__for_each_safe(pos, n, slist) \ 86#define strlist__for_each_entry_safe(pos, n, slist) \
87 for (pos = strlist__first(slist), n = strlist__next(pos); pos;\ 87 for (pos = strlist__first(slist), n = strlist__next(pos); pos;\
88 pos = n, n = strlist__next(n)) 88 pos = n, n = strlist__next(n))
89#endif /* __PERF_STRLIST_H */ 89#endif /* __PERF_STRLIST_H */
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index bc229a74c6a9..a811c13a74d6 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -7,6 +7,7 @@
7 7
8#include "symbol.h" 8#include "symbol.h"
9#include "demangle-java.h" 9#include "demangle-java.h"
10#include "demangle-rust.h"
10#include "machine.h" 11#include "machine.h"
11#include "vdso.h" 12#include "vdso.h"
12#include <symbol/kallsyms.h> 13#include <symbol/kallsyms.h>
@@ -16,6 +17,7 @@
16#define EM_AARCH64 183 /* ARM 64 bit */ 17#define EM_AARCH64 183 /* ARM 64 bit */
17#endif 18#endif
18 19
20typedef Elf64_Nhdr GElf_Nhdr;
19 21
20#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT 22#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
21extern char *cplus_demangle(const char *, int); 23extern char *cplus_demangle(const char *, int);
@@ -54,6 +56,14 @@ static int elf_getphdrnum(Elf *elf, size_t *dst)
54} 56}
55#endif 57#endif
56 58
59#ifndef HAVE_ELF_GETSHDRSTRNDX_SUPPORT
60static int elf_getshdrstrndx(Elf *elf __maybe_unused, size_t *dst __maybe_unused)
61{
62 pr_err("%s: update your libelf to > 0.140, this one lacks elf_getshdrstrndx().\n", __func__);
63 return -1;
64}
65#endif
66
57#ifndef NT_GNU_BUILD_ID 67#ifndef NT_GNU_BUILD_ID
58#define NT_GNU_BUILD_ID 3 68#define NT_GNU_BUILD_ID 3
59#endif 69#endif
@@ -709,17 +719,10 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
709 if (ss->opdshdr.sh_type != SHT_PROGBITS) 719 if (ss->opdshdr.sh_type != SHT_PROGBITS)
710 ss->opdsec = NULL; 720 ss->opdsec = NULL;
711 721
712 if (dso->kernel == DSO_TYPE_USER) { 722 if (dso->kernel == DSO_TYPE_USER)
713 GElf_Shdr shdr; 723 ss->adjust_symbols = true;
714 ss->adjust_symbols = (ehdr.e_type == ET_EXEC || 724 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); 725 ss->adjust_symbols = elf__needs_adjust_symbols(ehdr);
722 }
723 726
724 ss->name = strdup(name); 727 ss->name = strdup(name);
725 if (!ss->name) { 728 if (!ss->name) {
@@ -777,7 +780,8 @@ static bool want_demangle(bool is_kernel_sym)
777 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle; 780 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
778} 781}
779 782
780void __weak arch__elf_sym_adjust(GElf_Sym *sym __maybe_unused) { } 783void __weak arch__sym_update(struct symbol *s __maybe_unused,
784 GElf_Sym *sym __maybe_unused) { }
781 785
782int dso__load_sym(struct dso *dso, struct map *map, 786int dso__load_sym(struct dso *dso, struct map *map,
783 struct symsrc *syms_ss, struct symsrc *runtime_ss, 787 struct symsrc *syms_ss, struct symsrc *runtime_ss,
@@ -833,7 +837,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
833 sec = syms_ss->symtab; 837 sec = syms_ss->symtab;
834 shdr = syms_ss->symshdr; 838 shdr = syms_ss->symshdr;
835 839
836 if (elf_section_by_name(elf, &ehdr, &tshdr, ".text", NULL)) 840 if (elf_section_by_name(runtime_ss->elf, &runtime_ss->ehdr, &tshdr,
841 ".text", NULL))
837 dso->text_offset = tshdr.sh_addr - tshdr.sh_offset; 842 dso->text_offset = tshdr.sh_addr - tshdr.sh_offset;
838 843
839 if (runtime_ss->opdsec) 844 if (runtime_ss->opdsec)
@@ -954,8 +959,6 @@ int dso__load_sym(struct dso *dso, struct map *map,
954 (sym.st_value & 1)) 959 (sym.st_value & 1))
955 --sym.st_value; 960 --sym.st_value;
956 961
957 arch__elf_sym_adjust(&sym);
958
959 if (dso->kernel || kmodule) { 962 if (dso->kernel || kmodule) {
960 char dso_name[PATH_MAX]; 963 char dso_name[PATH_MAX];
961 964
@@ -1080,6 +1083,13 @@ new_symbol:
1080 demangled = bfd_demangle(NULL, elf_name, demangle_flags); 1083 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
1081 if (demangled == NULL) 1084 if (demangled == NULL)
1082 demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET); 1085 demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
1086 else if (rust_is_mangled(demangled))
1087 /*
1088 * Input to Rust demangling is the BFD-demangled
1089 * name which it Rust-demangles in place.
1090 */
1091 rust_demangle_sym(demangled);
1092
1083 if (demangled != NULL) 1093 if (demangled != NULL)
1084 elf_name = demangled; 1094 elf_name = demangled;
1085 } 1095 }
@@ -1089,6 +1099,8 @@ new_symbol:
1089 if (!f) 1099 if (!f)
1090 goto out_elf_end; 1100 goto out_elf_end;
1091 1101
1102 arch__sym_update(f, &sym);
1103
1092 if (filter && filter(curr_map, f)) 1104 if (filter && filter(curr_map, f))
1093 symbol__delete(f); 1105 symbol__delete(f);
1094 else { 1106 else {
@@ -1787,6 +1799,260 @@ void kcore_extract__delete(struct kcore_extract *kce)
1787 unlink(kce->extract_filename); 1799 unlink(kce->extract_filename);
1788} 1800}
1789 1801
1802#ifdef HAVE_GELF_GETNOTE_SUPPORT
1803/**
1804 * populate_sdt_note : Parse raw data and identify SDT note
1805 * @elf: elf of the opened file
1806 * @data: raw data of a section with description offset applied
1807 * @len: note description size
1808 * @type: type of the note
1809 * @sdt_notes: List to add the SDT note
1810 *
1811 * Responsible for parsing the @data in section .note.stapsdt in @elf and
1812 * if its an SDT note, it appends to @sdt_notes list.
1813 */
1814static int populate_sdt_note(Elf **elf, const char *data, size_t len,
1815 struct list_head *sdt_notes)
1816{
1817 const char *provider, *name;
1818 struct sdt_note *tmp = NULL;
1819 GElf_Ehdr ehdr;
1820 GElf_Addr base_off = 0;
1821 GElf_Shdr shdr;
1822 int ret = -EINVAL;
1823
1824 union {
1825 Elf64_Addr a64[NR_ADDR];
1826 Elf32_Addr a32[NR_ADDR];
1827 } buf;
1828
1829 Elf_Data dst = {
1830 .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
1831 .d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, EV_CURRENT),
1832 .d_off = 0, .d_align = 0
1833 };
1834 Elf_Data src = {
1835 .d_buf = (void *) data, .d_type = ELF_T_ADDR,
1836 .d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
1837 .d_align = 0
1838 };
1839
1840 tmp = (struct sdt_note *)calloc(1, sizeof(struct sdt_note));
1841 if (!tmp) {
1842 ret = -ENOMEM;
1843 goto out_err;
1844 }
1845
1846 INIT_LIST_HEAD(&tmp->note_list);
1847
1848 if (len < dst.d_size + 3)
1849 goto out_free_note;
1850
1851 /* Translation from file representation to memory representation */
1852 if (gelf_xlatetom(*elf, &dst, &src,
1853 elf_getident(*elf, NULL)[EI_DATA]) == NULL) {
1854 pr_err("gelf_xlatetom : %s\n", elf_errmsg(-1));
1855 goto out_free_note;
1856 }
1857
1858 /* Populate the fields of sdt_note */
1859 provider = data + dst.d_size;
1860
1861 name = (const char *)memchr(provider, '\0', data + len - provider);
1862 if (name++ == NULL)
1863 goto out_free_note;
1864
1865 tmp->provider = strdup(provider);
1866 if (!tmp->provider) {
1867 ret = -ENOMEM;
1868 goto out_free_note;
1869 }
1870 tmp->name = strdup(name);
1871 if (!tmp->name) {
1872 ret = -ENOMEM;
1873 goto out_free_prov;
1874 }
1875
1876 if (gelf_getclass(*elf) == ELFCLASS32) {
1877 memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
1878 tmp->bit32 = true;
1879 } else {
1880 memcpy(&tmp->addr, &buf, 3 * sizeof(Elf64_Addr));
1881 tmp->bit32 = false;
1882 }
1883
1884 if (!gelf_getehdr(*elf, &ehdr)) {
1885 pr_debug("%s : cannot get elf header.\n", __func__);
1886 ret = -EBADF;
1887 goto out_free_name;
1888 }
1889
1890 /* Adjust the prelink effect :
1891 * Find out the .stapsdt.base section.
1892 * This scn will help us to handle prelinking (if present).
1893 * Compare the retrieved file offset of the base section with the
1894 * base address in the description of the SDT note. If its different,
1895 * then accordingly, adjust the note location.
1896 */
1897 if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) {
1898 base_off = shdr.sh_offset;
1899 if (base_off) {
1900 if (tmp->bit32)
1901 tmp->addr.a32[0] = tmp->addr.a32[0] + base_off -
1902 tmp->addr.a32[1];
1903 else
1904 tmp->addr.a64[0] = tmp->addr.a64[0] + base_off -
1905 tmp->addr.a64[1];
1906 }
1907 }
1908
1909 list_add_tail(&tmp->note_list, sdt_notes);
1910 return 0;
1911
1912out_free_name:
1913 free(tmp->name);
1914out_free_prov:
1915 free(tmp->provider);
1916out_free_note:
1917 free(tmp);
1918out_err:
1919 return ret;
1920}
1921
1922/**
1923 * construct_sdt_notes_list : constructs a list of SDT notes
1924 * @elf : elf to look into
1925 * @sdt_notes : empty list_head
1926 *
1927 * Scans the sections in 'elf' for the section
1928 * .note.stapsdt. It, then calls populate_sdt_note to find
1929 * out the SDT events and populates the 'sdt_notes'.
1930 */
1931static int construct_sdt_notes_list(Elf *elf, struct list_head *sdt_notes)
1932{
1933 GElf_Ehdr ehdr;
1934 Elf_Scn *scn = NULL;
1935 Elf_Data *data;
1936 GElf_Shdr shdr;
1937 size_t shstrndx, next;
1938 GElf_Nhdr nhdr;
1939 size_t name_off, desc_off, offset;
1940 int ret = 0;
1941
1942 if (gelf_getehdr(elf, &ehdr) == NULL) {
1943 ret = -EBADF;
1944 goto out_ret;
1945 }
1946 if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
1947 ret = -EBADF;
1948 goto out_ret;
1949 }
1950
1951 /* Look for the required section */
1952 scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN, NULL);
1953 if (!scn) {
1954 ret = -ENOENT;
1955 goto out_ret;
1956 }
1957
1958 if ((shdr.sh_type != SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC)) {
1959 ret = -ENOENT;
1960 goto out_ret;
1961 }
1962
1963 data = elf_getdata(scn, NULL);
1964
1965 /* Get the SDT notes */
1966 for (offset = 0; (next = gelf_getnote(data, offset, &nhdr, &name_off,
1967 &desc_off)) > 0; offset = next) {
1968 if (nhdr.n_namesz == sizeof(SDT_NOTE_NAME) &&
1969 !memcmp(data->d_buf + name_off, SDT_NOTE_NAME,
1970 sizeof(SDT_NOTE_NAME))) {
1971 /* Check the type of the note */
1972 if (nhdr.n_type != SDT_NOTE_TYPE)
1973 goto out_ret;
1974
1975 ret = populate_sdt_note(&elf, ((data->d_buf) + desc_off),
1976 nhdr.n_descsz, sdt_notes);
1977 if (ret < 0)
1978 goto out_ret;
1979 }
1980 }
1981 if (list_empty(sdt_notes))
1982 ret = -ENOENT;
1983
1984out_ret:
1985 return ret;
1986}
1987
1988/**
1989 * get_sdt_note_list : Wrapper to construct a list of sdt notes
1990 * @head : empty list_head
1991 * @target : file to find SDT notes from
1992 *
1993 * This opens the file, initializes
1994 * the ELF and then calls construct_sdt_notes_list.
1995 */
1996int get_sdt_note_list(struct list_head *head, const char *target)
1997{
1998 Elf *elf;
1999 int fd, ret;
2000
2001 fd = open(target, O_RDONLY);
2002 if (fd < 0)
2003 return -EBADF;
2004
2005 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
2006 if (!elf) {
2007 ret = -EBADF;
2008 goto out_close;
2009 }
2010 ret = construct_sdt_notes_list(elf, head);
2011 elf_end(elf);
2012out_close:
2013 close(fd);
2014 return ret;
2015}
2016
2017/**
2018 * cleanup_sdt_note_list : free the sdt notes' list
2019 * @sdt_notes: sdt notes' list
2020 *
2021 * Free up the SDT notes in @sdt_notes.
2022 * Returns the number of SDT notes free'd.
2023 */
2024int cleanup_sdt_note_list(struct list_head *sdt_notes)
2025{
2026 struct sdt_note *tmp, *pos;
2027 int nr_free = 0;
2028
2029 list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) {
2030 list_del(&pos->note_list);
2031 free(pos->name);
2032 free(pos->provider);
2033 free(pos);
2034 nr_free++;
2035 }
2036 return nr_free;
2037}
2038
2039/**
2040 * sdt_notes__get_count: Counts the number of sdt events
2041 * @start: list_head to sdt_notes list
2042 *
2043 * Returns the number of SDT notes in a list
2044 */
2045int sdt_notes__get_count(struct list_head *start)
2046{
2047 struct sdt_note *sdt_ptr;
2048 int count = 0;
2049
2050 list_for_each_entry(sdt_ptr, start, note_list)
2051 count++;
2052 return count;
2053}
2054#endif
2055
1790void symbol__elf_init(void) 2056void symbol__elf_init(void)
1791{ 2057{
1792 elf_version(EV_CURRENT); 2058 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index e7588dc91518..37e8d20ae03e 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -255,40 +255,6 @@ void symbol__delete(struct symbol *sym)
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)
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 else 306 else
341 return s; 307 return s;
@@ -364,11 +330,6 @@ static struct symbol *symbols__next(struct symbol *sym)
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)
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)
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)
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,
1284 else 1242 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 else 1247 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{
@@ -1466,7 +1430,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1466 * Read the build id if possible. This is required for 1430 * Read the build id if possible. This is required for
1467 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 1431 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
1468 */ 1432 */
1469 if (is_regular_file(name) && 1433 if (is_regular_file(dso->long_name) &&
1470 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) 1434 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
1471 dso__set_build_id(dso, build_id); 1435 dso__set_build_id(dso, build_id);
1472 1436
@@ -1644,25 +1608,27 @@ out:
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_entry(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,15 +1636,29 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1670 } 1636 }
1671 } 1637 }
1672 1638
1673 closedir(d); 1639 strlist__delete(dirs);
1674 1640
1675 return ret; 1641 return ret;
1676} 1642}
1677 1643
1644/*
1645 * Use open(O_RDONLY) to check readability directly instead of access(R_OK)
1646 * since access(R_OK) only checks with real UID/GID but open() use effective
1647 * UID/GID and actual capabilities (e.g. /proc/kcore requires CAP_SYS_RAWIO).
1648 */
1649static bool filename__readable(const char *file)
1650{
1651 int fd = open(file, O_RDONLY);
1652 if (fd < 0)
1653 return false;
1654 close(fd);
1655 return true;
1656}
1657
1678static char *dso__find_kallsyms(struct dso *dso, struct map *map) 1658static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1679{ 1659{
1680 u8 host_build_id[BUILD_ID_SIZE]; 1660 u8 host_build_id[BUILD_ID_SIZE];
1681 char sbuild_id[BUILD_ID_SIZE * 2 + 1]; 1661 char sbuild_id[SBUILD_ID_SIZE];
1682 bool is_host = false; 1662 bool is_host = false;
1683 char path[PATH_MAX]; 1663 char path[PATH_MAX];
1684 1664
@@ -1694,58 +1674,43 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1694 sizeof(host_build_id)) == 0) 1674 sizeof(host_build_id)) == 0)
1695 is_host = dso__build_id_equal(dso, host_build_id); 1675 is_host = dso__build_id_equal(dso, host_build_id);
1696 1676
1697 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1677 /* Try a fast path for /proc/kallsyms if possible */
1698
1699 scnprintf(path, sizeof(path), "%s/[kernel.kcore]/%s", buildid_dir,
1700 sbuild_id);
1701
1702 /* Use /proc/kallsyms if possible */
1703 if (is_host) { 1678 if (is_host) {
1704 DIR *d;
1705 int fd;
1706
1707 /* If no cached kcore go with /proc/kallsyms */
1708 d = opendir(path);
1709 if (!d)
1710 goto proc_kallsyms;
1711 closedir(d);
1712
1713 /* 1679 /*
1714 * Do not check the build-id cache, until we know we cannot use 1680 * Do not check the build-id cache, unless we know we cannot use
1715 * /proc/kcore. 1681 * /proc/kcore or module maps don't match to /proc/kallsyms.
1682 * To check readability of /proc/kcore, do not use access(R_OK)
1683 * since /proc/kcore requires CAP_SYS_RAWIO to read and access
1684 * can't check it.
1716 */ 1685 */
1717 fd = open("/proc/kcore", O_RDONLY); 1686 if (filename__readable("/proc/kcore") &&
1718 if (fd != -1) { 1687 !validate_kcore_addresses("/proc/kallsyms", map))
1719 close(fd); 1688 goto proc_kallsyms;
1720 /* If module maps match go with /proc/kallsyms */
1721 if (!validate_kcore_addresses("/proc/kallsyms", map))
1722 goto proc_kallsyms;
1723 }
1724
1725 /* Find kallsyms in build-id cache with kcore */
1726 if (!find_matching_kcore(map, path, sizeof(path)))
1727 return strdup(path);
1728
1729 goto proc_kallsyms;
1730 } 1689 }
1731 1690
1691 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1692
1732 /* Find kallsyms in build-id cache with kcore */ 1693 /* Find kallsyms in build-id cache with kcore */
1694 scnprintf(path, sizeof(path), "%s/%s/%s",
1695 buildid_dir, DSO__NAME_KCORE, sbuild_id);
1696
1733 if (!find_matching_kcore(map, path, sizeof(path))) 1697 if (!find_matching_kcore(map, path, sizeof(path)))
1734 return strdup(path); 1698 return strdup(path);
1735 1699
1736 scnprintf(path, sizeof(path), "%s/[kernel.kallsyms]/%s", 1700 /* Use current /proc/kallsyms if possible */
1737 buildid_dir, sbuild_id); 1701 if (is_host) {
1702proc_kallsyms:
1703 return strdup("/proc/kallsyms");
1704 }
1738 1705
1739 if (access(path, F_OK)) { 1706 /* Finally, find a cache of kallsyms */
1707 if (!build_id_cache__kallsyms_path(sbuild_id, path, sizeof(path))) {
1740 pr_err("No kallsyms or vmlinux with build-id %s was found\n", 1708 pr_err("No kallsyms or vmlinux with build-id %s was found\n",
1741 sbuild_id); 1709 sbuild_id);
1742 return NULL; 1710 return NULL;
1743 } 1711 }
1744 1712
1745 return strdup(path); 1713 return strdup(path);
1746
1747proc_kallsyms:
1748 return strdup("/proc/kallsyms");
1749} 1714}
1750 1715
1751static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1716static int dso__load_kernel_sym(struct dso *dso, struct map *map,
@@ -1803,7 +1768,7 @@ do_kallsyms:
1803 1768
1804 if (err > 0 && !dso__is_kcore(dso)) { 1769 if (err > 0 && !dso__is_kcore(dso)) {
1805 dso->binary_type = DSO_BINARY_TYPE__KALLSYMS; 1770 dso->binary_type = DSO_BINARY_TYPE__KALLSYMS;
1806 dso__set_long_name(dso, "[kernel.kallsyms]", false); 1771 dso__set_long_name(dso, DSO__NAME_KALLSYMS, false);
1807 map__fixup_start(map); 1772 map__fixup_start(map);
1808 map__fixup_end(map); 1773 map__fixup_end(map);
1809 } 1774 }
@@ -1967,17 +1932,17 @@ int setup_intlist(struct intlist **list, const char *list_str,
1967static bool symbol__read_kptr_restrict(void) 1932static bool symbol__read_kptr_restrict(void)
1968{ 1933{
1969 bool value = false; 1934 bool value = false;
1935 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
1970 1936
1971 if (geteuid() != 0) { 1937 if (fp != NULL) {
1972 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r"); 1938 char line[8];
1973 if (fp != NULL) {
1974 char line[8];
1975 1939
1976 if (fgets(line, sizeof(line), fp) != NULL) 1940 if (fgets(line, sizeof(line), fp) != NULL)
1977 value = atoi(line) != 0; 1941 value = (geteuid() != 0) ?
1942 (atoi(line) != 0) :
1943 (atoi(line) == 2);
1978 1944
1979 fclose(fp); 1945 fclose(fp);
1980 }
1981 } 1946 }
1982 1947
1983 return value; 1948 return value;
@@ -2067,3 +2032,26 @@ void symbol__exit(void)
2067 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL; 2032 symbol_conf.sym_list = symbol_conf.dso_list = symbol_conf.comm_list = NULL;
2068 symbol_conf.initialized = false; 2033 symbol_conf.initialized = false;
2069} 2034}
2035
2036int symbol__config_symfs(const struct option *opt __maybe_unused,
2037 const char *dir, int unset __maybe_unused)
2038{
2039 char *bf = NULL;
2040 int ret;
2041
2042 symbol_conf.symfs = strdup(dir);
2043 if (symbol_conf.symfs == NULL)
2044 return -ENOMEM;
2045
2046 /* skip the locally configured cache if a symfs is given, and
2047 * config buildid dir to symfs/.debug
2048 */
2049 ret = asprintf(&bf, "%s/%s", dir, ".debug");
2050 if (ret < 0)
2051 return -ENOMEM;
2052
2053 set_buildid_dir(bf);
2054
2055 free(bf);
2056 return 0;
2057}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index c8b7544d9267..699f7cbcfe72 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -44,6 +44,9 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
44#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ 44#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */
45#endif 45#endif
46 46
47#define DSO__NAME_KALLSYMS "[kernel.kallsyms]"
48#define DSO__NAME_KCORE "[kernel.kcore]"
49
47/** struct symbol - symtab entry 50/** struct symbol - symtab entry
48 * 51 *
49 * @ignore - resolvable but tools ignore it (e.g. idle routines) 52 * @ignore - resolvable but tools ignore it (e.g. idle routines)
@@ -55,6 +58,7 @@ struct symbol {
55 u16 namelen; 58 u16 namelen;
56 u8 binding; 59 u8 binding;
57 bool ignore; 60 bool ignore;
61 u8 arch_sym;
58 char name[0]; 62 char name[0];
59}; 63};
60 64
@@ -140,6 +144,11 @@ struct symbol_conf {
140 144
141extern struct symbol_conf symbol_conf; 145extern struct symbol_conf symbol_conf;
142 146
147struct symbol_name_rb_node {
148 struct rb_node rb_node;
149 struct symbol sym;
150};
151
143static inline int __symbol__join_symfs(char *bf, size_t size, const char *path) 152static inline int __symbol__join_symfs(char *bf, size_t size, const char *path)
144{ 153{
145 return path__join(bf, size, symbol_conf.symfs, path); 154 return path__join(bf, size, symbol_conf.symfs, path);
@@ -177,6 +186,8 @@ struct branch_info {
177 struct addr_map_symbol from; 186 struct addr_map_symbol from;
178 struct addr_map_symbol to; 187 struct addr_map_symbol to;
179 struct branch_flags flags; 188 struct branch_flags flags;
189 char *srcline_from;
190 char *srcline_to;
180}; 191};
181 192
182struct mem_info { 193struct mem_info {
@@ -235,9 +246,14 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
235 symbol_filter_t filter); 246 symbol_filter_t filter);
236int dso__load_vmlinux_path(struct dso *dso, struct map *map, 247int dso__load_vmlinux_path(struct dso *dso, struct map *map,
237 symbol_filter_t filter); 248 symbol_filter_t filter);
249int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
250 bool no_kcore, symbol_filter_t filter);
238int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 251int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
239 symbol_filter_t filter); 252 symbol_filter_t filter);
240 253
254void dso__insert_symbol(struct dso *dso, enum map_type type,
255 struct symbol *sym);
256
241struct symbol *dso__find_symbol(struct dso *dso, enum map_type type, 257struct symbol *dso__find_symbol(struct dso *dso, enum map_type type,
242 u64 addr); 258 u64 addr);
243struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type, 259struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
@@ -262,14 +278,22 @@ int symbol__init(struct perf_env *env);
262void symbol__exit(void); 278void symbol__exit(void);
263void symbol__elf_init(void); 279void symbol__elf_init(void);
264struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 280struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
281size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
282 const struct addr_location *al,
283 bool unknown_as_addr, FILE *fp);
265size_t symbol__fprintf_symname_offs(const struct symbol *sym, 284size_t symbol__fprintf_symname_offs(const struct symbol *sym,
266 const struct addr_location *al, FILE *fp); 285 const struct addr_location *al, FILE *fp);
286size_t __symbol__fprintf_symname(const struct symbol *sym,
287 const struct addr_location *al,
288 bool unknown_as_addr, FILE *fp);
267size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp); 289size_t symbol__fprintf_symname(const struct symbol *sym, FILE *fp);
268size_t symbol__fprintf(struct symbol *sym, FILE *fp); 290size_t symbol__fprintf(struct symbol *sym, FILE *fp);
269bool symbol_type__is_a(char symbol_type, enum map_type map_type); 291bool symbol_type__is_a(char symbol_type, enum map_type map_type);
270bool symbol__restricted_filename(const char *filename, 292bool symbol__restricted_filename(const char *filename,
271 const char *restricted_filename); 293 const char *restricted_filename);
272bool symbol__is_idle(struct symbol *sym); 294bool symbol__is_idle(struct symbol *sym);
295int symbol__config_symfs(const struct option *opt __maybe_unused,
296 const char *dir, int unset __maybe_unused);
273 297
274int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss, 298int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
275 struct symsrc *runtime_ss, symbol_filter_t filter, 299 struct symsrc *runtime_ss, symbol_filter_t filter,
@@ -310,7 +334,7 @@ int setup_intlist(struct intlist **list, const char *list_str,
310 334
311#ifdef HAVE_LIBELF_SUPPORT 335#ifdef HAVE_LIBELF_SUPPORT
312bool elf__needs_adjust_symbols(GElf_Ehdr ehdr); 336bool elf__needs_adjust_symbols(GElf_Ehdr ehdr);
313void arch__elf_sym_adjust(GElf_Sym *sym); 337void arch__sym_update(struct symbol *s, GElf_Sym *sym);
314#endif 338#endif
315 339
316#define SYMBOL_A 0 340#define SYMBOL_A 0
@@ -318,4 +342,26 @@ void arch__elf_sym_adjust(GElf_Sym *sym);
318 342
319int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb); 343int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
320 344
345/* structure containing an SDT note's info */
346struct sdt_note {
347 char *name; /* name of the note*/
348 char *provider; /* provider name */
349 bool bit32; /* whether the location is 32 bits? */
350 union { /* location, base and semaphore addrs */
351 Elf64_Addr a64[3];
352 Elf32_Addr a32[3];
353 } addr;
354 struct list_head note_list; /* SDT notes' list */
355};
356
357int get_sdt_note_list(struct list_head *head, const char *target);
358int cleanup_sdt_note_list(struct list_head *sdt_notes);
359int sdt_notes__get_count(struct list_head *start);
360
361#define SDT_BASE_SCN ".stapsdt.base"
362#define SDT_NOTE_SCN ".note.stapsdt"
363#define SDT_NOTE_TYPE 3
364#define SDT_NOTE_NAME "stapsdt"
365#define NR_ADDR 3
366
321#endif /* __PERF_SYMBOL */ 367#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/symbol_fprintf.c b/tools/perf/util/symbol_fprintf.c
new file mode 100644
index 000000000000..a680bdaa65dc
--- /dev/null
+++ b/tools/perf/util/symbol_fprintf.c
@@ -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}
diff --git a/tools/perf/util/syscalltbl.c b/tools/perf/util/syscalltbl.c
new file mode 100644
index 000000000000..bbb4c1957578
--- /dev/null
+++ b/tools/perf/util/syscalltbl.c
@@ -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 */
diff --git a/tools/perf/util/syscalltbl.h b/tools/perf/util/syscalltbl.h
new file mode 100644
index 000000000000..e2951510484f
--- /dev/null
+++ b/tools/perf/util/syscalltbl.h
@@ -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 */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index a53603b27e52..21c4d9b23c24 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -7,6 +7,7 @@
7 */ 7 */
8 8
9#include "target.h" 9#include "target.h"
10#include "util.h"
10#include "debug.h" 11#include "debug.h"
11 12
12#include <pwd.h> 13#include <pwd.h>
@@ -121,11 +122,7 @@ int target__strerror(struct target *target, int errnum,
121 BUG_ON(buflen == 0); 122 BUG_ON(buflen == 0);
122 123
123 if (errnum >= 0) { 124 if (errnum >= 0) {
124 const char *err = strerror_r(errnum, buf, buflen); 125 str_error_r(errnum, buf, buflen);
125
126 if (err != buf)
127 scnprintf(buf, buflen, "%s", err);
128
129 return 0; 126 return 0;
130 } 127 }
131 128
diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c
index 679688e70ae7..d3301529f6a7 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -22,44 +22,9 @@
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 2048 28#define STACK_GROWTH 2048
64 29
65/** 30/**
@@ -335,108 +300,6 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
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)
@@ -753,3 +616,10 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
753 616
754 return err; 617 return err;
755} 618}
619
620size_t thread_stack__depth(struct thread *thread)
621{
622 if (!thread->ts)
623 return 0;
624 return thread->ts->cnt;
625}
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index e1528f1374c3..b7e41c4ebfdd 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -19,17 +19,16 @@
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 {
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 call 72 * information.
74 * @sym: symbol of function called 73 * @cpr: call path root
75 * @ip: only if sym is null, the ip of the function 74 * @process: call-back that accepts call/return information
76 * @db_id: id used for db-export 75 * @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,
@@ -98,6 +87,7 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
98 size_t sz, u64 ip); 87 size_t sz, u64 ip);
99int thread_stack__flush(struct thread *thread); 88int thread_stack__flush(struct thread *thread);
100void thread_stack__free(struct thread *thread); 89void thread_stack__free(struct thread *thread);
90size_t thread_stack__depth(struct thread *thread);
101 91
102struct call_return_processor * 92struct call_return_processor *
103call_return_processor__new(int (*process)(struct call_return *cr, void *data), 93call_return_processor__new(int (*process)(struct call_return *cr, void *data),
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index dfd00c6dad6e..8b10a55410a2 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -10,6 +10,8 @@
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;
@@ -41,9 +43,6 @@ struct thread *thread__new(pid_t pid, pid_t tid)
41 thread->cpu = -1; 43 thread->cpu = -1;
42 INIT_LIST_HEAD(&thread->comm_list); 44 INIT_LIST_HEAD(&thread->comm_list);
43 45
44 if (unwind__prepare_access(thread) < 0)
45 goto err_thread;
46
47 comm_str = malloc(32); 46 comm_str = malloc(32);
48 if (!comm_str) 47 if (!comm_str)
49 goto err_thread; 48 goto err_thread;
@@ -153,6 +152,23 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
153 return 0; 152 return 0;
154} 153}
155 154
155int thread__set_comm_from_proc(struct thread *thread)
156{
157 char path[64];
158 char *comm = NULL;
159 size_t sz;
160 int err = -1;
161
162 if (!(snprintf(path, sizeof(path), "%d/task/%d/comm",
163 thread->pid_, thread->tid) >= (int)sizeof(path)) &&
164 procfs__read_str(path, &comm, &sz) == 0) {
165 comm[sz - 1] = '\0';
166 err = thread__set_comm(thread, comm, 0);
167 }
168
169 return err;
170}
171
156const char *thread__comm_str(const struct thread *thread) 172const char *thread__comm_str(const struct thread *thread)
157{ 173{
158 const struct comm *comm = thread__comm(thread); 174 const struct comm *comm = thread__comm(thread);
@@ -182,10 +198,51 @@ size_t thread__fprintf(struct thread *thread, FILE *fp)
182 map_groups__fprintf(thread->mg, fp); 198 map_groups__fprintf(thread->mg, fp);
183} 199}
184 200
185void thread__insert_map(struct thread *thread, struct map *map) 201int thread__insert_map(struct thread *thread, struct map *map)
186{ 202{
203 int ret;
204
205 ret = unwind__prepare_access(thread, map, NULL);
206 if (ret)
207 return ret;
208
187 map_groups__fixup_overlappings(thread->mg, map, stderr); 209 map_groups__fixup_overlappings(thread->mg, map, stderr);
188 map_groups__insert(thread->mg, map); 210 map_groups__insert(thread->mg, map);
211
212 return 0;
213}
214
215static int __thread__prepare_access(struct thread *thread)
216{
217 bool initialized = false;
218 int i, err = 0;
219
220 for (i = 0; i < MAP__NR_TYPES; ++i) {
221 struct maps *maps = &thread->mg->maps[i];
222 struct map *map;
223
224 pthread_rwlock_rdlock(&maps->lock);
225
226 for (map = maps__first(maps); map; map = map__next(map)) {
227 err = unwind__prepare_access(thread, map, &initialized);
228 if (err || initialized)
229 break;
230 }
231
232 pthread_rwlock_unlock(&maps->lock);
233 }
234
235 return err;
236}
237
238static int thread__prepare_access(struct thread *thread)
239{
240 int err = 0;
241
242 if (symbol_conf.use_callchain)
243 err = __thread__prepare_access(thread);
244
245 return err;
189} 246}
190 247
191static int thread__clone_map_groups(struct thread *thread, 248static int thread__clone_map_groups(struct thread *thread,
@@ -195,7 +252,7 @@ static int thread__clone_map_groups(struct thread *thread,
195 252
196 /* This is new thread, we share map groups for process. */ 253 /* This is new thread, we share map groups for process. */
197 if (thread->pid_ == parent->pid_) 254 if (thread->pid_ == parent->pid_)
198 return 0; 255 return thread__prepare_access(thread);
199 256
200 if (thread->mg == parent->mg) { 257 if (thread->mg == parent->mg) {
201 pr_debug("broken map groups on thread %d/%d parent %d/%d\n", 258 pr_debug("broken map groups on thread %d/%d parent %d/%d\n",
@@ -205,7 +262,7 @@ static int thread__clone_map_groups(struct thread *thread,
205 262
206 /* But this one is new process, copy maps. */ 263 /* But this one is new process, copy maps. */
207 for (i = 0; i < MAP__NR_TYPES; ++i) 264 for (i = 0; i < MAP__NR_TYPES; ++i)
208 if (map_groups__clone(thread->mg, parent->mg, i) < 0) 265 if (map_groups__clone(thread, parent->mg, i) < 0)
209 return -ENOMEM; 266 return -ENOMEM;
210 267
211 return 0; 268 return 0;
@@ -233,7 +290,7 @@ void thread__find_cpumode_addr_location(struct thread *thread,
233 struct addr_location *al) 290 struct addr_location *al)
234{ 291{
235 size_t i; 292 size_t i;
236 const u8 const cpumodes[] = { 293 const u8 cpumodes[] = {
237 PERF_RECORD_MISC_USER, 294 PERF_RECORD_MISC_USER,
238 PERF_RECORD_MISC_KERNEL, 295 PERF_RECORD_MISC_KERNEL,
239 PERF_RECORD_MISC_GUEST_USER, 296 PERF_RECORD_MISC_GUEST_USER,
@@ -246,3 +303,14 @@ void thread__find_cpumode_addr_location(struct thread *thread,
246 break; 303 break;
247 } 304 }
248} 305}
306
307struct thread *thread__main_thread(struct machine *machine, struct thread *thread)
308{
309 if (thread->pid_ == thread->tid)
310 return thread__get(thread);
311
312 if (thread->pid_ == -1)
313 return NULL;
314
315 return machine__find_thread(machine, thread->pid_, thread->pid_);
316}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index a0ac0317affb..99263cb6e6b6 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -11,6 +11,7 @@
11#include <intlist.h> 11#include <intlist.h>
12 12
13struct thread_stack; 13struct thread_stack;
14struct unwind_libunwind_ops;
14 15
15struct thread { 16struct thread {
16 union { 17 union {
@@ -32,6 +33,10 @@ struct thread {
32 33
33 void *priv; 34 void *priv;
34 struct thread_stack *ts; 35 struct thread_stack *ts;
36#ifdef HAVE_LIBUNWIND_SUPPORT
37 void *addr_space;
38 struct unwind_libunwind_ops *unwind_libunwind_ops;
39#endif
35}; 40};
36 41
37struct machine; 42struct machine;
@@ -65,14 +70,18 @@ static inline int thread__set_comm(struct thread *thread, const char *comm,
65 return __thread__set_comm(thread, comm, timestamp, false); 70 return __thread__set_comm(thread, comm, timestamp, false);
66} 71}
67 72
73int thread__set_comm_from_proc(struct thread *thread);
74
68int thread__comm_len(struct thread *thread); 75int thread__comm_len(struct thread *thread);
69struct comm *thread__comm(const struct thread *thread); 76struct comm *thread__comm(const struct thread *thread);
70struct comm *thread__exec_comm(const struct thread *thread); 77struct comm *thread__exec_comm(const struct thread *thread);
71const char *thread__comm_str(const struct thread *thread); 78const char *thread__comm_str(const struct thread *thread);
72void thread__insert_map(struct thread *thread, struct map *map); 79int thread__insert_map(struct thread *thread, struct map *map);
73int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 80int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
74size_t thread__fprintf(struct thread *thread, FILE *fp); 81size_t thread__fprintf(struct thread *thread, FILE *fp);
75 82
83struct thread *thread__main_thread(struct machine *machine, struct thread *thread);
84
76void thread__find_addr_map(struct thread *thread, 85void thread__find_addr_map(struct thread *thread,
77 u8 cpumode, enum map_type type, u64 addr, 86 u8 cpumode, enum map_type type, u64 addr,
78 struct addr_location *al); 87 struct addr_location *al);
diff --git a/tools/perf/util/thread_map.c b/tools/perf/util/thread_map.c
index 267112b4e3db..40585f5b7027 100644
--- a/tools/perf/util/thread_map.c
+++ b/tools/perf/util/thread_map.c
@@ -202,7 +202,7 @@ static struct thread_map *thread_map__new_by_pid_str(const char *pid_str)
202 if (!slist) 202 if (!slist)
203 return NULL; 203 return NULL;
204 204
205 strlist__for_each(pos, slist) { 205 strlist__for_each_entry(pos, slist) {
206 pid = strtol(pos->s, &end_ptr, 10); 206 pid = strtol(pos->s, &end_ptr, 10);
207 207
208 if (pid == INT_MIN || pid == INT_MAX || 208 if (pid == INT_MIN || pid == INT_MAX ||
@@ -260,7 +260,7 @@ struct thread_map *thread_map__new_dummy(void)
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;
@@ -278,7 +278,7 @@ static struct thread_map *thread_map__new_by_tid_str(const char *tid_str)
278 if (!slist) 278 if (!slist)
279 return NULL; 279 return NULL;
280 280
281 strlist__for_each(pos, slist) { 281 strlist__for_each_entry(pos, slist) {
282 tid = strtol(pos->s, &end_ptr, 10); 282 tid = strtol(pos->s, &end_ptr, 10);
283 283
284 if (tid == INT_MIN || tid == INT_MAX || 284 if (tid == INT_MIN || tid == INT_MAX ||
@@ -436,3 +436,15 @@ struct thread_map *thread_map__new_event(struct thread_map_event *event)
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}
diff --git a/tools/perf/util/thread_map.h b/tools/perf/util/thread_map.h
index 85e4c7c4fbde..bd3b971588da 100644
--- a/tools/perf/util/thread_map.h
+++ b/tools/perf/util/thread_map.h
@@ -31,6 +31,8 @@ void thread_map__put(struct thread_map *map);
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)
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 */
diff --git a/tools/perf/util/tool.h b/tools/perf/util/tool.h
index 55de4cffcd4e..ac2590a3de2d 100644
--- a/tools/perf/util/tool.h
+++ b/tools/perf/util/tool.h
@@ -57,6 +57,7 @@ struct perf_tool {
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,
diff --git a/tools/perf/util/top.h b/tools/perf/util/top.h
index f92c37abb0a8..b2940c88734a 100644
--- a/tools/perf/util/top.h
+++ b/tools/perf/util/top.h
@@ -27,7 +27,6 @@ struct perf_top {
27 int max_stack; 27 int max_stack;
28 bool hide_kernel_symbols, hide_user_symbols, zero; 28 bool hide_kernel_symbols, hide_user_symbols, zero;
29 bool use_tui, use_stdio; 29 bool use_tui, use_stdio;
30 bool kptr_restrict_warned;
31 bool vmlinux_warned; 30 bool vmlinux_warned;
32 bool dump_symtab; 31 bool dump_symtab;
33 struct hist_entry *sym_filter_entry; 32 struct hist_entry *sym_filter_entry;
diff --git a/tools/perf/util/trace-event.c b/tools/perf/util/trace-event.c
index 8ae051e0ec79..c330780674fc 100644
--- a/tools/perf/util/trace-event.c
+++ b/tools/perf/util/trace-event.c
@@ -105,3 +105,11 @@ trace_event__tp_format(const char *sys, const char *name)
105 105
106 return tp_format(sys, name); 106 return tp_format(sys, name);
107} 107}
108
109struct event_format *trace_event__tp_format_id(int id)
110{
111 if (!tevent_initialized && trace_event__init2())
112 return ERR_PTR(-ENOMEM);
113
114 return pevent_find_event(tevent.pevent, id);
115}
diff --git a/tools/perf/util/trace-event.h b/tools/perf/util/trace-event.h
index bce5b1dac268..b0af9c81bb0d 100644
--- a/tools/perf/util/trace-event.h
+++ b/tools/perf/util/trace-event.h
@@ -23,6 +23,8 @@ int trace_event__register_resolver(struct machine *machine,
23struct event_format* 23struct event_format*
24trace_event__tp_format(const char *sys, const char *name); 24trace_event__tp_format(const char *sys, const char *name);
25 25
26struct event_format *trace_event__tp_format_id(int id);
27
26int bigendian(void); 28int bigendian(void);
27 29
28void event_format__fprintf(struct event_format *event, 30void event_format__fprintf(struct event_format *event,
diff --git a/tools/perf/util/trigger.h b/tools/perf/util/trigger.h
new file mode 100644
index 000000000000..e97d7016d771
--- /dev/null
+++ b/tools/perf/util/trigger.h
@@ -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
diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h
index a8b78f1b3243..d5b11e2b85e0 100644
--- a/tools/perf/util/tsc.h
+++ b/tools/perf/util/tsc.h
@@ -3,10 +3,29 @@
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#endif 31#endif
diff --git a/tools/perf/util/unwind-libdw.c b/tools/perf/util/unwind-libdw.c
index cf5e250bc78e..783a53fb7a4e 100644
--- a/tools/perf/util/unwind-libdw.c
+++ b/tools/perf/util/unwind-libdw.c
@@ -66,7 +66,7 @@ static int entry(u64 ip, struct unwind_info *ui)
66 if (__report_module(&al, ip, ui)) 66 if (__report_module(&al, ip, ui))
67 return -1; 67 return -1;
68 68
69 e->ip = ip; 69 e->ip = al.addr;
70 e->map = al.map; 70 e->map = al.map;
71 e->sym = al.sym; 71 e->sym = al.sym;
72 72
diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unwind-libunwind-local.c
new file mode 100644
index 000000000000..20c2e5743903
--- /dev/null
+++ b/tools/perf/util/unwind-libunwind-local.c
@@ -0,0 +1,699 @@
1/*
2 * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
3 *
4 * Lots of this code have been borrowed or heavily inspired from parts of
5 * the libunwind 0.99 code which are (amongst other contributors I may have
6 * forgotten):
7 *
8 * Copyright (C) 2002-2007 Hewlett-Packard Co
9 * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
10 *
11 * And the bugs have been added by:
12 *
13 * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
14 * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
15 *
16 */
17
18#include <elf.h>
19#include <gelf.h>
20#include <fcntl.h>
21#include <string.h>
22#include <unistd.h>
23#include <sys/mman.h>
24#include <linux/list.h>
25#ifndef REMOTE_UNWIND_LIBUNWIND
26#include <libunwind.h>
27#include <libunwind-ptrace.h>
28#endif
29#include "callchain.h"
30#include "thread.h"
31#include "session.h"
32#include "perf_regs.h"
33#include "unwind.h"
34#include "symbol.h"
35#include "util.h"
36#include "debug.h"
37#include "asm/bug.h"
38
39extern int
40UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
41 unw_word_t ip,
42 unw_dyn_info_t *di,
43 unw_proc_info_t *pi,
44 int need_unwind_info, void *arg);
45
46#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
47
48extern int
49UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
50 unw_word_t ip,
51 unw_word_t segbase,
52 const char *obj_name, unw_word_t start,
53 unw_word_t end);
54
55#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
56
57#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
58#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
59
60/* Pointer-encoding formats: */
61#define DW_EH_PE_omit 0xff
62#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
63#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
64#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
65#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
66#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
67
68/* Pointer-encoding application: */
69#define DW_EH_PE_absptr 0x00 /* absolute value */
70#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
71
72/*
73 * The following are not documented by LSB v1.3, yet they are used by
74 * GCC, presumably they aren't documented by LSB since they aren't
75 * used on Linux:
76 */
77#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
78#define DW_EH_PE_aligned 0x50 /* aligned pointer */
79
80/* Flags intentionaly not handled, since they're not needed:
81 * #define DW_EH_PE_indirect 0x80
82 * #define DW_EH_PE_uleb128 0x01
83 * #define DW_EH_PE_udata2 0x02
84 * #define DW_EH_PE_sleb128 0x09
85 * #define DW_EH_PE_sdata2 0x0a
86 * #define DW_EH_PE_textrel 0x20
87 * #define DW_EH_PE_datarel 0x30
88 */
89
90struct unwind_info {
91 struct perf_sample *sample;
92 struct machine *machine;
93 struct thread *thread;
94};
95
96#define dw_read(ptr, type, end) ({ \
97 type *__p = (type *) ptr; \
98 type __v; \
99 if ((__p + 1) > (type *) end) \
100 return -EINVAL; \
101 __v = *__p++; \
102 ptr = (typeof(ptr)) __p; \
103 __v; \
104 })
105
106static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
107 u8 encoding)
108{
109 u8 *cur = *p;
110 *val = 0;
111
112 switch (encoding) {
113 case DW_EH_PE_omit:
114 *val = 0;
115 goto out;
116 case DW_EH_PE_ptr:
117 *val = dw_read(cur, unsigned long, end);
118 goto out;
119 default:
120 break;
121 }
122
123 switch (encoding & DW_EH_PE_APPL_MASK) {
124 case DW_EH_PE_absptr:
125 break;
126 case DW_EH_PE_pcrel:
127 *val = (unsigned long) cur;
128 break;
129 default:
130 return -EINVAL;
131 }
132
133 if ((encoding & 0x07) == 0x00)
134 encoding |= DW_EH_PE_udata4;
135
136 switch (encoding & DW_EH_PE_FORMAT_MASK) {
137 case DW_EH_PE_sdata4:
138 *val += dw_read(cur, s32, end);
139 break;
140 case DW_EH_PE_udata4:
141 *val += dw_read(cur, u32, end);
142 break;
143 case DW_EH_PE_sdata8:
144 *val += dw_read(cur, s64, end);
145 break;
146 case DW_EH_PE_udata8:
147 *val += dw_read(cur, u64, end);
148 break;
149 default:
150 return -EINVAL;
151 }
152
153 out:
154 *p = cur;
155 return 0;
156}
157
158#define dw_read_encoded_value(ptr, end, enc) ({ \
159 u64 __v; \
160 if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
161 return -EINVAL; \
162 } \
163 __v; \
164 })
165
166static u64 elf_section_offset(int fd, const char *name)
167{
168 Elf *elf;
169 GElf_Ehdr ehdr;
170 GElf_Shdr shdr;
171 u64 offset = 0;
172
173 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
174 if (elf == NULL)
175 return 0;
176
177 do {
178 if (gelf_getehdr(elf, &ehdr) == NULL)
179 break;
180
181 if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
182 break;
183
184 offset = shdr.sh_offset;
185 } while (0);
186
187 elf_end(elf);
188 return offset;
189}
190
191#ifndef NO_LIBUNWIND_DEBUG_FRAME
192static int elf_is_exec(int fd, const char *name)
193{
194 Elf *elf;
195 GElf_Ehdr ehdr;
196 int retval = 0;
197
198 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
199 if (elf == NULL)
200 return 0;
201 if (gelf_getehdr(elf, &ehdr) == NULL)
202 goto out;
203
204 retval = (ehdr.e_type == ET_EXEC);
205
206out:
207 elf_end(elf);
208 pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
209 return retval;
210}
211#endif
212
213struct table_entry {
214 u32 start_ip_offset;
215 u32 fde_offset;
216};
217
218struct eh_frame_hdr {
219 unsigned char version;
220 unsigned char eh_frame_ptr_enc;
221 unsigned char fde_count_enc;
222 unsigned char table_enc;
223
224 /*
225 * The rest of the header is variable-length and consists of the
226 * following members:
227 *
228 * encoded_t eh_frame_ptr;
229 * encoded_t fde_count;
230 */
231
232 /* A single encoded pointer should not be more than 8 bytes. */
233 u64 enc[2];
234
235 /*
236 * struct {
237 * encoded_t start_ip;
238 * encoded_t fde_addr;
239 * } binary_search_table[fde_count];
240 */
241 char data[0];
242} __packed;
243
244static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
245 u64 offset, u64 *table_data, u64 *segbase,
246 u64 *fde_count)
247{
248 struct eh_frame_hdr hdr;
249 u8 *enc = (u8 *) &hdr.enc;
250 u8 *end = (u8 *) &hdr.data;
251 ssize_t r;
252
253 r = dso__data_read_offset(dso, machine, offset,
254 (u8 *) &hdr, sizeof(hdr));
255 if (r != sizeof(hdr))
256 return -EINVAL;
257
258 /* We dont need eh_frame_ptr, just skip it. */
259 dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
260
261 *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
262 *segbase = offset;
263 *table_data = (enc - (u8 *) &hdr) + offset;
264 return 0;
265}
266
267static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
268 u64 *table_data, u64 *segbase,
269 u64 *fde_count)
270{
271 int ret = -EINVAL, fd;
272 u64 offset = dso->data.eh_frame_hdr_offset;
273
274 if (offset == 0) {
275 fd = dso__data_get_fd(dso, machine);
276 if (fd < 0)
277 return -EINVAL;
278
279 /* Check the .eh_frame section for unwinding info */
280 offset = elf_section_offset(fd, ".eh_frame_hdr");
281 dso->data.eh_frame_hdr_offset = offset;
282 dso__data_put_fd(dso);
283 }
284
285 if (offset)
286 ret = unwind_spec_ehframe(dso, machine, offset,
287 table_data, segbase,
288 fde_count);
289
290 return ret;
291}
292
293#ifndef NO_LIBUNWIND_DEBUG_FRAME
294static int read_unwind_spec_debug_frame(struct dso *dso,
295 struct machine *machine, u64 *offset)
296{
297 int fd;
298 u64 ofs = dso->data.debug_frame_offset;
299
300 if (ofs == 0) {
301 fd = dso__data_get_fd(dso, machine);
302 if (fd < 0)
303 return -EINVAL;
304
305 /* Check the .debug_frame section for unwinding info */
306 ofs = elf_section_offset(fd, ".debug_frame");
307 dso->data.debug_frame_offset = ofs;
308 dso__data_put_fd(dso);
309 }
310
311 *offset = ofs;
312 if (*offset)
313 return 0;
314
315 return -EINVAL;
316}
317#endif
318
319static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
320{
321 struct addr_location al;
322
323 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
324 MAP__FUNCTION, ip, &al);
325 if (!al.map) {
326 /*
327 * We've seen cases (softice) where DWARF unwinder went
328 * through non executable mmaps, which we need to lookup
329 * in MAP__VARIABLE tree.
330 */
331 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
332 MAP__VARIABLE, ip, &al);
333 }
334 return al.map;
335}
336
337static int
338find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
339 int need_unwind_info, void *arg)
340{
341 struct unwind_info *ui = arg;
342 struct map *map;
343 unw_dyn_info_t di;
344 u64 table_data, segbase, fde_count;
345 int ret = -EINVAL;
346
347 map = find_map(ip, ui);
348 if (!map || !map->dso)
349 return -EINVAL;
350
351 pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
352
353 /* Check the .eh_frame section for unwinding info */
354 if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
355 &table_data, &segbase, &fde_count)) {
356 memset(&di, 0, sizeof(di));
357 di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
358 di.start_ip = map->start;
359 di.end_ip = map->end;
360 di.u.rti.segbase = map->start + segbase;
361 di.u.rti.table_data = map->start + table_data;
362 di.u.rti.table_len = fde_count * sizeof(struct table_entry)
363 / sizeof(unw_word_t);
364 ret = dwarf_search_unwind_table(as, ip, &di, pi,
365 need_unwind_info, arg);
366 }
367
368#ifndef NO_LIBUNWIND_DEBUG_FRAME
369 /* Check the .debug_frame section for unwinding info */
370 if (ret < 0 &&
371 !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
372 int fd = dso__data_get_fd(map->dso, ui->machine);
373 int is_exec = elf_is_exec(fd, map->dso->name);
374 unw_word_t base = is_exec ? 0 : map->start;
375 const char *symfile;
376
377 if (fd >= 0)
378 dso__data_put_fd(map->dso);
379
380 symfile = map->dso->symsrc_filename ?: map->dso->name;
381
382 memset(&di, 0, sizeof(di));
383 if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
384 map->start, map->end))
385 return dwarf_search_unwind_table(as, ip, &di, pi,
386 need_unwind_info, arg);
387 }
388#endif
389
390 return ret;
391}
392
393static int access_fpreg(unw_addr_space_t __maybe_unused as,
394 unw_regnum_t __maybe_unused num,
395 unw_fpreg_t __maybe_unused *val,
396 int __maybe_unused __write,
397 void __maybe_unused *arg)
398{
399 pr_err("unwind: access_fpreg unsupported\n");
400 return -UNW_EINVAL;
401}
402
403static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
404 unw_word_t __maybe_unused *dil_addr,
405 void __maybe_unused *arg)
406{
407 return -UNW_ENOINFO;
408}
409
410static int resume(unw_addr_space_t __maybe_unused as,
411 unw_cursor_t __maybe_unused *cu,
412 void __maybe_unused *arg)
413{
414 pr_err("unwind: resume unsupported\n");
415 return -UNW_EINVAL;
416}
417
418static int
419get_proc_name(unw_addr_space_t __maybe_unused as,
420 unw_word_t __maybe_unused addr,
421 char __maybe_unused *bufp, size_t __maybe_unused buf_len,
422 unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
423{
424 pr_err("unwind: get_proc_name unsupported\n");
425 return -UNW_EINVAL;
426}
427
428static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
429 unw_word_t *data)
430{
431 struct map *map;
432 ssize_t size;
433
434 map = find_map(addr, ui);
435 if (!map) {
436 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
437 return -1;
438 }
439
440 if (!map->dso)
441 return -1;
442
443 size = dso__data_read_addr(map->dso, map, ui->machine,
444 addr, (u8 *) data, sizeof(*data));
445
446 return !(size == sizeof(*data));
447}
448
449static int access_mem(unw_addr_space_t __maybe_unused as,
450 unw_word_t addr, unw_word_t *valp,
451 int __write, void *arg)
452{
453 struct unwind_info *ui = arg;
454 struct stack_dump *stack = &ui->sample->user_stack;
455 u64 start, end;
456 int offset;
457 int ret;
458
459 /* Don't support write, probably not needed. */
460 if (__write || !stack || !ui->sample->user_regs.regs) {
461 *valp = 0;
462 return 0;
463 }
464
465 ret = perf_reg_value(&start, &ui->sample->user_regs,
466 LIBUNWIND__ARCH_REG_SP);
467 if (ret)
468 return ret;
469
470 end = start + stack->size;
471
472 /* Check overflow. */
473 if (addr + sizeof(unw_word_t) < addr)
474 return -EINVAL;
475
476 if (addr < start || addr + sizeof(unw_word_t) >= end) {
477 ret = access_dso_mem(ui, addr, valp);
478 if (ret) {
479 pr_debug("unwind: access_mem %p not inside range"
480 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
481 (void *) (uintptr_t) addr, start, end);
482 *valp = 0;
483 return ret;
484 }
485 return 0;
486 }
487
488 offset = addr - start;
489 *valp = *(unw_word_t *)&stack->data[offset];
490 pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
491 (void *) (uintptr_t) addr, (unsigned long)*valp, offset);
492 return 0;
493}
494
495static int access_reg(unw_addr_space_t __maybe_unused as,
496 unw_regnum_t regnum, unw_word_t *valp,
497 int __write, void *arg)
498{
499 struct unwind_info *ui = arg;
500 int id, ret;
501 u64 val;
502
503 /* Don't support write, I suspect we don't need it. */
504 if (__write) {
505 pr_err("unwind: access_reg w %d\n", regnum);
506 return 0;
507 }
508
509 if (!ui->sample->user_regs.regs) {
510 *valp = 0;
511 return 0;
512 }
513
514 id = LIBUNWIND__ARCH_REG_ID(regnum);
515 if (id < 0)
516 return -EINVAL;
517
518 ret = perf_reg_value(&val, &ui->sample->user_regs, id);
519 if (ret) {
520 pr_err("unwind: can't read reg %d\n", regnum);
521 return ret;
522 }
523
524 *valp = (unw_word_t) val;
525 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
526 return 0;
527}
528
529static void put_unwind_info(unw_addr_space_t __maybe_unused as,
530 unw_proc_info_t *pi __maybe_unused,
531 void *arg __maybe_unused)
532{
533 pr_debug("unwind: put_unwind_info called\n");
534}
535
536static int entry(u64 ip, struct thread *thread,
537 unwind_entry_cb_t cb, void *arg)
538{
539 struct unwind_entry e;
540 struct addr_location al;
541
542 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
543 MAP__FUNCTION, ip, &al);
544
545 e.ip = al.addr;
546 e.map = al.map;
547 e.sym = al.sym;
548
549 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
550 al.sym ? al.sym->name : "''",
551 ip,
552 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
553
554 return cb(&e, arg);
555}
556
557static void display_error(int err)
558{
559 switch (err) {
560 case UNW_EINVAL:
561 pr_err("unwind: Only supports local.\n");
562 break;
563 case UNW_EUNSPEC:
564 pr_err("unwind: Unspecified error.\n");
565 break;
566 case UNW_EBADREG:
567 pr_err("unwind: Register unavailable.\n");
568 break;
569 default:
570 break;
571 }
572}
573
574static unw_accessors_t accessors = {
575 .find_proc_info = find_proc_info,
576 .put_unwind_info = put_unwind_info,
577 .get_dyn_info_list_addr = get_dyn_info_list_addr,
578 .access_mem = access_mem,
579 .access_reg = access_reg,
580 .access_fpreg = access_fpreg,
581 .resume = resume,
582 .get_proc_name = get_proc_name,
583};
584
585static int _unwind__prepare_access(struct thread *thread)
586{
587 if (callchain_param.record_mode != CALLCHAIN_DWARF)
588 return 0;
589
590 thread->addr_space = unw_create_addr_space(&accessors, 0);
591 if (!thread->addr_space) {
592 pr_err("unwind: Can't create unwind address space.\n");
593 return -ENOMEM;
594 }
595
596 unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL);
597 return 0;
598}
599
600static void _unwind__flush_access(struct thread *thread)
601{
602 if (callchain_param.record_mode != CALLCHAIN_DWARF)
603 return;
604
605 unw_flush_cache(thread->addr_space, 0, 0);
606}
607
608static void _unwind__finish_access(struct thread *thread)
609{
610 if (callchain_param.record_mode != CALLCHAIN_DWARF)
611 return;
612
613 unw_destroy_addr_space(thread->addr_space);
614}
615
616static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
617 void *arg, int max_stack)
618{
619 u64 val;
620 unw_word_t ips[max_stack];
621 unw_addr_space_t addr_space;
622 unw_cursor_t c;
623 int ret, i = 0;
624
625 ret = perf_reg_value(&val, &ui->sample->user_regs,
626 LIBUNWIND__ARCH_REG_IP);
627 if (ret)
628 return ret;
629
630 ips[i++] = (unw_word_t) val;
631
632 /*
633 * If we need more than one entry, do the DWARF
634 * unwind itself.
635 */
636 if (max_stack - 1 > 0) {
637 WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
638 addr_space = ui->thread->addr_space;
639
640 if (addr_space == NULL)
641 return -1;
642
643 ret = unw_init_remote(&c, addr_space, ui);
644 if (ret)
645 display_error(ret);
646
647 while (!ret && (unw_step(&c) > 0) && i < max_stack) {
648 unw_get_reg(&c, UNW_REG_IP, &ips[i]);
649 ++i;
650 }
651
652 max_stack = i;
653 }
654
655 /*
656 * Display what we got based on the order setup.
657 */
658 for (i = 0; i < max_stack && !ret; i++) {
659 int j = i;
660
661 if (callchain_param.order == ORDER_CALLER)
662 j = max_stack - i - 1;
663 ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;
664 }
665
666 return ret;
667}
668
669static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
670 struct thread *thread,
671 struct perf_sample *data, int max_stack)
672{
673 struct unwind_info ui = {
674 .sample = data,
675 .thread = thread,
676 .machine = thread->mg->machine,
677 };
678
679 if (!data->user_regs.regs)
680 return -EINVAL;
681
682 if (max_stack <= 0)
683 return -EINVAL;
684
685 return get_entries(&ui, cb, arg, max_stack);
686}
687
688static struct unwind_libunwind_ops
689_unwind_libunwind_ops = {
690 .prepare_access = _unwind__prepare_access,
691 .flush_access = _unwind__flush_access,
692 .finish_access = _unwind__finish_access,
693 .get_entries = _unwind__get_entries,
694};
695
696#ifndef REMOTE_UNWIND_LIBUNWIND
697struct unwind_libunwind_ops *
698local_unwind_libunwind_ops = &_unwind_libunwind_ops;
699#endif
diff --git a/tools/perf/util/unwind-libunwind.c b/tools/perf/util/unwind-libunwind.c
index ee7e372297e5..6d542a4e0648 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -1,689 +1,83 @@
1/* 1#include "unwind.h"
2 * Post mortem Dwarf CFI based unwinding on top of regs and stack dumps.
3 *
4 * Lots of this code have been borrowed or heavily inspired from parts of
5 * the libunwind 0.99 code which are (amongst other contributors I may have
6 * forgotten):
7 *
8 * Copyright (C) 2002-2007 Hewlett-Packard Co
9 * Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
10 *
11 * And the bugs have been added by:
12 *
13 * Copyright (C) 2010, Frederic Weisbecker <fweisbec@gmail.com>
14 * Copyright (C) 2012, Jiri Olsa <jolsa@redhat.com>
15 *
16 */
17
18#include <elf.h>
19#include <gelf.h>
20#include <fcntl.h>
21#include <string.h>
22#include <unistd.h>
23#include <sys/mman.h>
24#include <linux/list.h>
25#include <libunwind.h>
26#include <libunwind-ptrace.h>
27#include "callchain.h"
28#include "thread.h" 2#include "thread.h"
29#include "session.h" 3#include "session.h"
30#include "perf_regs.h"
31#include "unwind.h"
32#include "symbol.h"
33#include "util.h"
34#include "debug.h" 4#include "debug.h"
5#include "arch/common.h"
35 6
36extern int 7struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
37UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as, 8struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops;
38 unw_word_t ip, 9struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops;
39 unw_dyn_info_t *di,
40 unw_proc_info_t *pi,
41 int need_unwind_info, void *arg);
42
43#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
44
45extern int
46UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
47 unw_word_t ip,
48 unw_word_t segbase,
49 const char *obj_name, unw_word_t start,
50 unw_word_t end);
51
52#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
53
54#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
55#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
56
57/* Pointer-encoding formats: */
58#define DW_EH_PE_omit 0xff
59#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
60#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
61#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
62#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
63#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
64
65/* Pointer-encoding application: */
66#define DW_EH_PE_absptr 0x00 /* absolute value */
67#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
68
69/*
70 * The following are not documented by LSB v1.3, yet they are used by
71 * GCC, presumably they aren't documented by LSB since they aren't
72 * used on Linux:
73 */
74#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
75#define DW_EH_PE_aligned 0x50 /* aligned pointer */
76
77/* Flags intentionaly not handled, since they're not needed:
78 * #define DW_EH_PE_indirect 0x80
79 * #define DW_EH_PE_uleb128 0x01
80 * #define DW_EH_PE_udata2 0x02
81 * #define DW_EH_PE_sleb128 0x09
82 * #define DW_EH_PE_sdata2 0x0a
83 * #define DW_EH_PE_textrel 0x20
84 * #define DW_EH_PE_datarel 0x30
85 */
86
87struct unwind_info {
88 struct perf_sample *sample;
89 struct machine *machine;
90 struct thread *thread;
91};
92
93#define dw_read(ptr, type, end) ({ \
94 type *__p = (type *) ptr; \
95 type __v; \
96 if ((__p + 1) > (type *) end) \
97 return -EINVAL; \
98 __v = *__p++; \
99 ptr = (typeof(ptr)) __p; \
100 __v; \
101 })
102
103static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
104 u8 encoding)
105{
106 u8 *cur = *p;
107 *val = 0;
108
109 switch (encoding) {
110 case DW_EH_PE_omit:
111 *val = 0;
112 goto out;
113 case DW_EH_PE_ptr:
114 *val = dw_read(cur, unsigned long, end);
115 goto out;
116 default:
117 break;
118 }
119
120 switch (encoding & DW_EH_PE_APPL_MASK) {
121 case DW_EH_PE_absptr:
122 break;
123 case DW_EH_PE_pcrel:
124 *val = (unsigned long) cur;
125 break;
126 default:
127 return -EINVAL;
128 }
129
130 if ((encoding & 0x07) == 0x00)
131 encoding |= DW_EH_PE_udata4;
132
133 switch (encoding & DW_EH_PE_FORMAT_MASK) {
134 case DW_EH_PE_sdata4:
135 *val += dw_read(cur, s32, end);
136 break;
137 case DW_EH_PE_udata4:
138 *val += dw_read(cur, u32, end);
139 break;
140 case DW_EH_PE_sdata8:
141 *val += dw_read(cur, s64, end);
142 break;
143 case DW_EH_PE_udata8:
144 *val += dw_read(cur, u64, end);
145 break;
146 default:
147 return -EINVAL;
148 }
149
150 out:
151 *p = cur;
152 return 0;
153}
154
155#define dw_read_encoded_value(ptr, end, enc) ({ \
156 u64 __v; \
157 if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
158 return -EINVAL; \
159 } \
160 __v; \
161 })
162 10
163static u64 elf_section_offset(int fd, const char *name) 11static void unwind__register_ops(struct thread *thread,
12 struct unwind_libunwind_ops *ops)
164{ 13{
165 Elf *elf; 14 thread->unwind_libunwind_ops = ops;
166 GElf_Ehdr ehdr;
167 GElf_Shdr shdr;
168 u64 offset = 0;
169
170 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
171 if (elf == NULL)
172 return 0;
173
174 do {
175 if (gelf_getehdr(elf, &ehdr) == NULL)
176 break;
177
178 if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
179 break;
180
181 offset = shdr.sh_offset;
182 } while (0);
183
184 elf_end(elf);
185 return offset;
186} 15}
187 16
188#ifndef NO_LIBUNWIND_DEBUG_FRAME 17int unwind__prepare_access(struct thread *thread, struct map *map,
189static int elf_is_exec(int fd, const char *name) 18 bool *initialized)
190{ 19{
191 Elf *elf; 20 const char *arch;
192 GElf_Ehdr ehdr; 21 enum dso_type dso_type;
193 int retval = 0; 22 struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops;
23 int err;
194 24
195 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 25 if (thread->addr_space) {
196 if (elf == NULL) 26 pr_debug("unwind: thread map already set, dso=%s\n",
27 map->dso->name);
28 if (initialized)
29 *initialized = true;
197 return 0; 30 return 0;
198 if (gelf_getehdr(elf, &ehdr) == NULL)
199 goto out;
200
201 retval = (ehdr.e_type == ET_EXEC);
202
203out:
204 elf_end(elf);
205 pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
206 return retval;
207}
208#endif
209
210struct table_entry {
211 u32 start_ip_offset;
212 u32 fde_offset;
213};
214
215struct eh_frame_hdr {
216 unsigned char version;
217 unsigned char eh_frame_ptr_enc;
218 unsigned char fde_count_enc;
219 unsigned char table_enc;
220
221 /*
222 * The rest of the header is variable-length and consists of the
223 * following members:
224 *
225 * encoded_t eh_frame_ptr;
226 * encoded_t fde_count;
227 */
228
229 /* A single encoded pointer should not be more than 8 bytes. */
230 u64 enc[2];
231
232 /*
233 * struct {
234 * encoded_t start_ip;
235 * encoded_t fde_addr;
236 * } binary_search_table[fde_count];
237 */
238 char data[0];
239} __packed;
240
241static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
242 u64 offset, u64 *table_data, u64 *segbase,
243 u64 *fde_count)
244{
245 struct eh_frame_hdr hdr;
246 u8 *enc = (u8 *) &hdr.enc;
247 u8 *end = (u8 *) &hdr.data;
248 ssize_t r;
249
250 r = dso__data_read_offset(dso, machine, offset,
251 (u8 *) &hdr, sizeof(hdr));
252 if (r != sizeof(hdr))
253 return -EINVAL;
254
255 /* We dont need eh_frame_ptr, just skip it. */
256 dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
257
258 *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
259 *segbase = offset;
260 *table_data = (enc - (u8 *) &hdr) + offset;
261 return 0;
262}
263
264static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
265 u64 *table_data, u64 *segbase,
266 u64 *fde_count)
267{
268 int ret = -EINVAL, fd;
269 u64 offset = dso->data.eh_frame_hdr_offset;
270
271 if (offset == 0) {
272 fd = dso__data_get_fd(dso, machine);
273 if (fd < 0)
274 return -EINVAL;
275
276 /* Check the .eh_frame section for unwinding info */
277 offset = elf_section_offset(fd, ".eh_frame_hdr");
278 dso->data.eh_frame_hdr_offset = offset;
279 dso__data_put_fd(dso);
280 } 31 }
281 32
282 if (offset) 33 /* env->arch is NULL for live-mode (i.e. perf top) */
283 ret = unwind_spec_ehframe(dso, machine, offset, 34 if (!thread->mg->machine->env || !thread->mg->machine->env->arch)
284 table_data, segbase, 35 goto out_register;
285 fde_count);
286
287 return ret;
288}
289 36
290#ifndef NO_LIBUNWIND_DEBUG_FRAME 37 dso_type = dso__type(map->dso, thread->mg->machine);
291static int read_unwind_spec_debug_frame(struct dso *dso, 38 if (dso_type == DSO__TYPE_UNKNOWN)
292 struct machine *machine, u64 *offset)
293{
294 int fd;
295 u64 ofs = dso->data.debug_frame_offset;
296
297 if (ofs == 0) {
298 fd = dso__data_get_fd(dso, machine);
299 if (fd < 0)
300 return -EINVAL;
301
302 /* Check the .debug_frame section for unwinding info */
303 ofs = elf_section_offset(fd, ".debug_frame");
304 dso->data.debug_frame_offset = ofs;
305 dso__data_put_fd(dso);
306 }
307
308 *offset = ofs;
309 if (*offset)
310 return 0; 39 return 0;
311 40
312 return -EINVAL; 41 arch = normalize_arch(thread->mg->machine->env->arch);
313}
314#endif
315
316static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
317{
318 struct addr_location al;
319
320 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
321 MAP__FUNCTION, ip, &al);
322 if (!al.map) {
323 /*
324 * We've seen cases (softice) where DWARF unwinder went
325 * through non executable mmaps, which we need to lookup
326 * in MAP__VARIABLE tree.
327 */
328 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
329 MAP__VARIABLE, ip, &al);
330 }
331 return al.map;
332}
333
334static int
335find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
336 int need_unwind_info, void *arg)
337{
338 struct unwind_info *ui = arg;
339 struct map *map;
340 unw_dyn_info_t di;
341 u64 table_data, segbase, fde_count;
342 int ret = -EINVAL;
343
344 map = find_map(ip, ui);
345 if (!map || !map->dso)
346 return -EINVAL;
347
348 pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
349 42
350 /* Check the .eh_frame section for unwinding info */ 43 if (!strcmp(arch, "x86")) {
351 if (!read_unwind_spec_eh_frame(map->dso, ui->machine, 44 if (dso_type != DSO__TYPE_64BIT)
352 &table_data, &segbase, &fde_count)) { 45 ops = x86_32_unwind_libunwind_ops;
353 memset(&di, 0, sizeof(di)); 46 } else if (!strcmp(arch, "arm64") || !strcmp(arch, "arm")) {
354 di.format = UNW_INFO_FORMAT_REMOTE_TABLE; 47 if (dso_type == DSO__TYPE_64BIT)
355 di.start_ip = map->start; 48 ops = arm64_unwind_libunwind_ops;
356 di.end_ip = map->end;
357 di.u.rti.segbase = map->start + segbase;
358 di.u.rti.table_data = map->start + table_data;
359 di.u.rti.table_len = fde_count * sizeof(struct table_entry)
360 / sizeof(unw_word_t);
361 ret = dwarf_search_unwind_table(as, ip, &di, pi,
362 need_unwind_info, arg);
363 } 49 }
364 50
365#ifndef NO_LIBUNWIND_DEBUG_FRAME 51 if (!ops) {
366 /* Check the .debug_frame section for unwinding info */ 52 pr_err("unwind: target platform=%s is not supported\n", arch);
367 if (ret < 0 &&
368 !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
369 int fd = dso__data_get_fd(map->dso, ui->machine);
370 int is_exec = elf_is_exec(fd, map->dso->name);
371 unw_word_t base = is_exec ? 0 : map->start;
372 const char *symfile;
373
374 if (fd >= 0)
375 dso__data_put_fd(map->dso);
376
377 symfile = map->dso->symsrc_filename ?: map->dso->name;
378
379 memset(&di, 0, sizeof(di));
380 if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
381 map->start, map->end))
382 return dwarf_search_unwind_table(as, ip, &di, pi,
383 need_unwind_info, arg);
384 }
385#endif
386
387 return ret;
388}
389
390static int access_fpreg(unw_addr_space_t __maybe_unused as,
391 unw_regnum_t __maybe_unused num,
392 unw_fpreg_t __maybe_unused *val,
393 int __maybe_unused __write,
394 void __maybe_unused *arg)
395{
396 pr_err("unwind: access_fpreg unsupported\n");
397 return -UNW_EINVAL;
398}
399
400static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
401 unw_word_t __maybe_unused *dil_addr,
402 void __maybe_unused *arg)
403{
404 return -UNW_ENOINFO;
405}
406
407static int resume(unw_addr_space_t __maybe_unused as,
408 unw_cursor_t __maybe_unused *cu,
409 void __maybe_unused *arg)
410{
411 pr_err("unwind: resume unsupported\n");
412 return -UNW_EINVAL;
413}
414
415static int
416get_proc_name(unw_addr_space_t __maybe_unused as,
417 unw_word_t __maybe_unused addr,
418 char __maybe_unused *bufp, size_t __maybe_unused buf_len,
419 unw_word_t __maybe_unused *offp, void __maybe_unused *arg)
420{
421 pr_err("unwind: get_proc_name unsupported\n");
422 return -UNW_EINVAL;
423}
424
425static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
426 unw_word_t *data)
427{
428 struct map *map;
429 ssize_t size;
430
431 map = find_map(addr, ui);
432 if (!map) {
433 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
434 return -1; 53 return -1;
435 } 54 }
55out_register:
56 unwind__register_ops(thread, ops);
436 57
437 if (!map->dso) 58 err = thread->unwind_libunwind_ops->prepare_access(thread);
438 return -1; 59 if (initialized)
439 60 *initialized = err ? false : true;
440 size = dso__data_read_addr(map->dso, map, ui->machine, 61 return err;
441 addr, (u8 *) data, sizeof(*data));
442
443 return !(size == sizeof(*data));
444}
445
446static int access_mem(unw_addr_space_t __maybe_unused as,
447 unw_word_t addr, unw_word_t *valp,
448 int __write, void *arg)
449{
450 struct unwind_info *ui = arg;
451 struct stack_dump *stack = &ui->sample->user_stack;
452 u64 start, end;
453 int offset;
454 int ret;
455
456 /* Don't support write, probably not needed. */
457 if (__write || !stack || !ui->sample->user_regs.regs) {
458 *valp = 0;
459 return 0;
460 }
461
462 ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
463 if (ret)
464 return ret;
465
466 end = start + stack->size;
467
468 /* Check overflow. */
469 if (addr + sizeof(unw_word_t) < addr)
470 return -EINVAL;
471
472 if (addr < start || addr + sizeof(unw_word_t) >= end) {
473 ret = access_dso_mem(ui, addr, valp);
474 if (ret) {
475 pr_debug("unwind: access_mem %p not inside range"
476 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
477 (void *) (uintptr_t) addr, start, end);
478 *valp = 0;
479 return ret;
480 }
481 return 0;
482 }
483
484 offset = addr - start;
485 *valp = *(unw_word_t *)&stack->data[offset];
486 pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
487 (void *) (uintptr_t) addr, (unsigned long)*valp, offset);
488 return 0;
489}
490
491static int access_reg(unw_addr_space_t __maybe_unused as,
492 unw_regnum_t regnum, unw_word_t *valp,
493 int __write, void *arg)
494{
495 struct unwind_info *ui = arg;
496 int id, ret;
497 u64 val;
498
499 /* Don't support write, I suspect we don't need it. */
500 if (__write) {
501 pr_err("unwind: access_reg w %d\n", regnum);
502 return 0;
503 }
504
505 if (!ui->sample->user_regs.regs) {
506 *valp = 0;
507 return 0;
508 }
509
510 id = libunwind__arch_reg_id(regnum);
511 if (id < 0)
512 return -EINVAL;
513
514 ret = perf_reg_value(&val, &ui->sample->user_regs, id);
515 if (ret) {
516 pr_err("unwind: can't read reg %d\n", regnum);
517 return ret;
518 }
519
520 *valp = (unw_word_t) val;
521 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
522 return 0;
523}
524
525static void put_unwind_info(unw_addr_space_t __maybe_unused as,
526 unw_proc_info_t *pi __maybe_unused,
527 void *arg __maybe_unused)
528{
529 pr_debug("unwind: put_unwind_info called\n");
530}
531
532static int entry(u64 ip, struct thread *thread,
533 unwind_entry_cb_t cb, void *arg)
534{
535 struct unwind_entry e;
536 struct addr_location al;
537
538 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
539 MAP__FUNCTION, ip, &al);
540
541 e.ip = ip;
542 e.map = al.map;
543 e.sym = al.sym;
544
545 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
546 al.sym ? al.sym->name : "''",
547 ip,
548 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
549
550 return cb(&e, arg);
551}
552
553static void display_error(int err)
554{
555 switch (err) {
556 case UNW_EINVAL:
557 pr_err("unwind: Only supports local.\n");
558 break;
559 case UNW_EUNSPEC:
560 pr_err("unwind: Unspecified error.\n");
561 break;
562 case UNW_EBADREG:
563 pr_err("unwind: Register unavailable.\n");
564 break;
565 default:
566 break;
567 }
568}
569
570static unw_accessors_t accessors = {
571 .find_proc_info = find_proc_info,
572 .put_unwind_info = put_unwind_info,
573 .get_dyn_info_list_addr = get_dyn_info_list_addr,
574 .access_mem = access_mem,
575 .access_reg = access_reg,
576 .access_fpreg = access_fpreg,
577 .resume = resume,
578 .get_proc_name = get_proc_name,
579};
580
581int unwind__prepare_access(struct thread *thread)
582{
583 unw_addr_space_t addr_space;
584
585 if (callchain_param.record_mode != CALLCHAIN_DWARF)
586 return 0;
587
588 addr_space = unw_create_addr_space(&accessors, 0);
589 if (!addr_space) {
590 pr_err("unwind: Can't create unwind address space.\n");
591 return -ENOMEM;
592 }
593
594 unw_set_caching_policy(addr_space, UNW_CACHE_GLOBAL);
595 thread__set_priv(thread, addr_space);
596
597 return 0;
598} 62}
599 63
600void unwind__flush_access(struct thread *thread) 64void unwind__flush_access(struct thread *thread)
601{ 65{
602 unw_addr_space_t addr_space; 66 if (thread->unwind_libunwind_ops)
603 67 thread->unwind_libunwind_ops->flush_access(thread);
604 if (callchain_param.record_mode != CALLCHAIN_DWARF)
605 return;
606
607 addr_space = thread__priv(thread);
608 unw_flush_cache(addr_space, 0, 0);
609} 68}
610 69
611void unwind__finish_access(struct thread *thread) 70void unwind__finish_access(struct thread *thread)
612{ 71{
613 unw_addr_space_t addr_space; 72 if (thread->unwind_libunwind_ops)
614 73 thread->unwind_libunwind_ops->finish_access(thread);
615 if (callchain_param.record_mode != CALLCHAIN_DWARF)
616 return;
617
618 addr_space = thread__priv(thread);
619 unw_destroy_addr_space(addr_space);
620}
621
622static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
623 void *arg, int max_stack)
624{
625 u64 val;
626 unw_word_t ips[max_stack];
627 unw_addr_space_t addr_space;
628 unw_cursor_t c;
629 int ret, i = 0;
630
631 ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP);
632 if (ret)
633 return ret;
634
635 ips[i++] = (unw_word_t) val;
636
637 /*
638 * If we need more than one entry, do the DWARF
639 * unwind itself.
640 */
641 if (max_stack - 1 > 0) {
642 addr_space = thread__priv(ui->thread);
643 if (addr_space == NULL)
644 return -1;
645
646 ret = unw_init_remote(&c, addr_space, ui);
647 if (ret)
648 display_error(ret);
649
650 while (!ret && (unw_step(&c) > 0) && i < max_stack) {
651 unw_get_reg(&c, UNW_REG_IP, &ips[i]);
652 ++i;
653 }
654
655 max_stack = i;
656 }
657
658 /*
659 * Display what we got based on the order setup.
660 */
661 for (i = 0; i < max_stack && !ret; i++) {
662 int j = i;
663
664 if (callchain_param.order == ORDER_CALLER)
665 j = max_stack - i - 1;
666 ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;
667 }
668
669 return ret;
670} 74}
671 75
672int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 76int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
673 struct thread *thread, 77 struct thread *thread,
674 struct perf_sample *data, int max_stack) 78 struct perf_sample *data, int max_stack)
675{ 79{
676 struct unwind_info ui = { 80 if (thread->unwind_libunwind_ops)
677 .sample = data, 81 return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
678 .thread = thread, 82 return 0;
679 .machine = thread->mg->machine,
680 };
681
682 if (!data->user_regs.regs)
683 return -EINVAL;
684
685 if (max_stack <= 0)
686 return -EINVAL;
687
688 return get_entries(&ui, cb, arg, max_stack);
689} 83}
diff --git a/tools/perf/util/unwind.h b/tools/perf/util/unwind.h
index 12790cf94618..61fb1e90ff51 100644
--- a/tools/perf/util/unwind.h
+++ b/tools/perf/util/unwind.h
@@ -14,18 +14,42 @@ struct unwind_entry {
14 14
15typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg); 15typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
16 16
17struct unwind_libunwind_ops {
18 int (*prepare_access)(struct thread *thread);
19 void (*flush_access)(struct thread *thread);
20 void (*finish_access)(struct thread *thread);
21 int (*get_entries)(unwind_entry_cb_t cb, void *arg,
22 struct thread *thread,
23 struct perf_sample *data, int max_stack);
24};
25
17#ifdef HAVE_DWARF_UNWIND_SUPPORT 26#ifdef HAVE_DWARF_UNWIND_SUPPORT
18int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 27int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
19 struct thread *thread, 28 struct thread *thread,
20 struct perf_sample *data, int max_stack); 29 struct perf_sample *data, int max_stack);
21/* libunwind specific */ 30/* libunwind specific */
22#ifdef HAVE_LIBUNWIND_SUPPORT 31#ifdef HAVE_LIBUNWIND_SUPPORT
23int libunwind__arch_reg_id(int regnum); 32#ifndef LIBUNWIND__ARCH_REG_ID
24int unwind__prepare_access(struct thread *thread); 33#define LIBUNWIND__ARCH_REG_ID(regnum) libunwind__arch_reg_id(regnum)
34#endif
35
36#ifndef LIBUNWIND__ARCH_REG_SP
37#define LIBUNWIND__ARCH_REG_SP PERF_REG_SP
38#endif
39
40#ifndef LIBUNWIND__ARCH_REG_IP
41#define LIBUNWIND__ARCH_REG_IP PERF_REG_IP
42#endif
43
44int LIBUNWIND__ARCH_REG_ID(int regnum);
45int unwind__prepare_access(struct thread *thread, struct map *map,
46 bool *initialized);
25void unwind__flush_access(struct thread *thread); 47void unwind__flush_access(struct thread *thread);
26void unwind__finish_access(struct thread *thread); 48void unwind__finish_access(struct thread *thread);
27#else 49#else
28static inline int unwind__prepare_access(struct thread *thread __maybe_unused) 50static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
51 struct map *map __maybe_unused,
52 bool *initialized __maybe_unused)
29{ 53{
30 return 0; 54 return 0;
31} 55}
@@ -44,7 +68,9 @@ unwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
44 return 0; 68 return 0;
45} 69}
46 70
47static inline int unwind__prepare_access(struct thread *thread __maybe_unused) 71static inline int unwind__prepare_access(struct thread *thread __maybe_unused,
72 struct map *map __maybe_unused,
73 bool *initialized __maybe_unused)
48{ 74{
49 return 0; 75 return 0;
50} 76}
diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c
index b7766c577b01..cee559d8c9e8 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -19,12 +19,19 @@
19#include "callchain.h" 19#include "callchain.h"
20#include "strlist.h" 20#include "strlist.h"
21 21
22struct callchain_param callchain_param = { 22#define CALLCHAIN_PARAM_DEFAULT \
23 .mode = CHAIN_GRAPH_ABS, 23 .mode = CHAIN_GRAPH_ABS, \
24 .min_percent = 0.5, 24 .min_percent = 0.5, \
25 .order = ORDER_CALLEE, 25 .order = ORDER_CALLEE, \
26 .key = CCKEY_FUNCTION, 26 .key = CCKEY_FUNCTION, \
27 .value = CCVAL_PERCENT, 27 .value = CCVAL_PERCENT, \
28
29struct callchain_param callchain_param = {
30 CALLCHAIN_PARAM_DEFAULT
31};
32
33struct callchain_param callchain_param_default = {
34 CALLCHAIN_PARAM_DEFAULT
28}; 35};
29 36
30/* 37/*
@@ -33,6 +40,9 @@ struct callchain_param callchain_param = {
33unsigned int page_size; 40unsigned int page_size;
34int cacheline_size; 41int cacheline_size;
35 42
43int sysctl_perf_event_max_stack = PERF_MAX_STACK_DEPTH;
44int sysctl_perf_event_max_contexts_per_stack = PERF_MAX_CONTEXTS_PER_STACK;
45
36bool test_attr__enabled; 46bool test_attr__enabled;
37 47
38bool perf_host = true; 48bool perf_host = true;
@@ -94,20 +104,17 @@ int rm_rf(char *path)
94 scnprintf(namebuf, sizeof(namebuf), "%s/%s", 104 scnprintf(namebuf, sizeof(namebuf), "%s/%s",
95 path, d->d_name); 105 path, d->d_name);
96 106
97 ret = stat(namebuf, &statbuf); 107 /* We have to check symbolic link itself */
108 ret = lstat(namebuf, &statbuf);
98 if (ret < 0) { 109 if (ret < 0) {
99 pr_debug("stat failed: %s\n", namebuf); 110 pr_debug("stat failed: %s\n", namebuf);
100 break; 111 break;
101 } 112 }
102 113
103 if (S_ISREG(statbuf.st_mode)) 114 if (S_ISDIR(statbuf.st_mode))
104 ret = unlink(namebuf);
105 else if (S_ISDIR(statbuf.st_mode))
106 ret = rm_rf(namebuf); 115 ret = rm_rf(namebuf);
107 else { 116 else
108 pr_debug("unknown file: %s\n", namebuf); 117 ret = unlink(namebuf);
109 ret = -1;
110 }
111 } 118 }
112 closedir(dir); 119 closedir(dir);
113 120
@@ -117,6 +124,40 @@ int rm_rf(char *path)
117 return rmdir(path); 124 return rmdir(path);
118} 125}
119 126
127/* A filter which removes dot files */
128bool lsdir_no_dot_filter(const char *name __maybe_unused, struct dirent *d)
129{
130 return d->d_name[0] != '.';
131}
132
133/* lsdir reads a directory and store it in strlist */
134struct strlist *lsdir(const char *name,
135 bool (*filter)(const char *, struct dirent *))
136{
137 struct strlist *list = NULL;
138 DIR *dir;
139 struct dirent *d;
140
141 dir = opendir(name);
142 if (!dir)
143 return NULL;
144
145 list = strlist__new(NULL, NULL);
146 if (!list) {
147 errno = ENOMEM;
148 goto out;
149 }
150
151 while ((d = readdir(dir)) != NULL) {
152 if (!filter || filter(name, d))
153 strlist__add(list, d->d_name);
154 }
155
156out:
157 closedir(dir);
158 return list;
159}
160
120static int slow_copyfile(const char *from, const char *to) 161static int slow_copyfile(const char *from, const char *to)
121{ 162{
122 int err = -1; 163 int err = -1;
@@ -471,7 +512,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
471 "needed for --call-graph fp\n"); 512 "needed for --call-graph fp\n");
472 break; 513 break;
473 514
474#ifdef HAVE_DWARF_UNWIND_SUPPORT
475 /* Dwarf style */ 515 /* Dwarf style */
476 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) { 516 } else if (!strncmp(name, "dwarf", sizeof("dwarf"))) {
477 const unsigned long default_stack_dump_size = 8192; 517 const unsigned long default_stack_dump_size = 8192;
@@ -487,7 +527,6 @@ int parse_callchain_record(const char *arg, struct callchain_param *param)
487 ret = get_stack_size(tok, &size); 527 ret = get_stack_size(tok, &size);
488 param->dump_size = size; 528 param->dump_size = size;
489 } 529 }
490#endif /* HAVE_DWARF_UNWIND_SUPPORT */
491 } else if (!strncmp(name, "lbr", sizeof("lbr"))) { 530 } else if (!strncmp(name, "lbr", sizeof("lbr"))) {
492 if (!strtok_r(NULL, ",", &saveptr)) { 531 if (!strtok_r(NULL, ",", &saveptr)) {
493 param->record_mode = CALLCHAIN_LBR; 532 param->record_mode = CALLCHAIN_LBR;
@@ -707,3 +746,19 @@ void print_binary(unsigned char *data, size_t len,
707 } 746 }
708 printer(BINARY_PRINT_DATA_END, -1, extra); 747 printer(BINARY_PRINT_DATA_END, -1, extra);
709} 748}
749
750int is_printable_array(char *p, unsigned int len)
751{
752 unsigned int i;
753
754 if (!p || !len || p[len - 1] != 0)
755 return 0;
756
757 len--;
758
759 for (i = 0; i < len; i++) {
760 if (!isprint(p[i]) && !isspace(p[i]))
761 return 0;
762 }
763 return 1;
764}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 8298d607c738..e5f55477491d 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -72,13 +72,13 @@
72#include <sys/ioctl.h> 72#include <sys/ioctl.h>
73#include <inttypes.h> 73#include <inttypes.h>
74#include <linux/kernel.h> 74#include <linux/kernel.h>
75#include <linux/magic.h>
76#include <linux/types.h> 75#include <linux/types.h>
77#include <sys/ttydefaults.h> 76#include <sys/ttydefaults.h>
78#include <api/fs/tracing_path.h> 77#include <api/fs/tracing_path.h>
79#include <termios.h> 78#include <termios.h>
80#include <linux/bitops.h> 79#include <linux/bitops.h>
81#include <termios.h> 80#include <termios.h>
81#include "strlist.h"
82 82
83extern const char *graph_line; 83extern const char *graph_line;
84extern const char *graph_dotted_line; 84extern const char *graph_dotted_line;
@@ -159,12 +159,6 @@ static inline char *gitstrchrnul(const char *s, int c)
159} 159}
160#endif 160#endif
161 161
162/*
163 * Wrappers:
164 */
165void *xrealloc(void *ptr, size_t size) __attribute__((weak));
166
167
168static inline void *zalloc(size_t size) 162static inline void *zalloc(size_t size)
169{ 163{
170 return calloc(1, size); 164 return calloc(1, size);
@@ -222,6 +216,8 @@ static inline int sane_case(int x, int high)
222 216
223int mkdir_p(char *path, mode_t mode); 217int mkdir_p(char *path, mode_t mode);
224int rm_rf(char *path); 218int rm_rf(char *path);
219struct strlist *lsdir(const char *name, bool (*filter)(const char *, struct dirent *));
220bool lsdir_no_dot_filter(const char *name, struct dirent *d);
225int copyfile(const char *from, const char *to); 221int copyfile(const char *from, const char *to);
226int copyfile_mode(const char *from, const char *to, mode_t mode); 222int 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); 223int copyfile_offset(int fromfd, loff_t from_ofs, int tofd, loff_t to_ofs, u64 size);
@@ -254,11 +250,18 @@ int hex2u64(const char *ptr, u64 *val);
254char *ltrim(char *s); 250char *ltrim(char *s);
255char *rtrim(char *s); 251char *rtrim(char *s);
256 252
253static inline char *trim(char *s)
254{
255 return ltrim(rtrim(s));
256}
257
257void dump_stack(void); 258void dump_stack(void);
258void sighandler_dump_stack(int sig); 259void sighandler_dump_stack(int sig);
259 260
260extern unsigned int page_size; 261extern unsigned int page_size;
261extern int cacheline_size; 262extern int cacheline_size;
263extern int sysctl_perf_event_max_stack;
264extern int sysctl_perf_event_max_contexts_per_stack;
262 265
263struct parse_tag { 266struct parse_tag {
264 char tag; 267 char tag;
@@ -356,4 +359,10 @@ typedef void (*print_binary_t)(enum binary_printer_ops,
356void print_binary(unsigned char *data, size_t len, 359void print_binary(unsigned char *data, size_t len,
357 size_t bytes_per_line, print_binary_t printer, 360 size_t bytes_per_line, print_binary_t printer,
358 void *extra); 361 void *extra);
362
363#if !defined(__GLIBC__) && !defined(__ANDROID__)
364extern int sched_getcpu(void);
365#endif
366
367int is_printable_array(char *p, unsigned int len);
359#endif /* GIT_COMPAT_UTIL_H */ 368#endif /* GIT_COMPAT_UTIL_H */
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 44d440da15dc..7bdcad484225 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -134,8 +134,6 @@ static struct dso *__machine__addnew_vdso(struct machine *machine, const char *s
134 return dso; 134 return dso;
135} 135}
136 136
137#if BITS_PER_LONG == 64
138
139static enum dso_type machine__thread_dso_type(struct machine *machine, 137static enum dso_type machine__thread_dso_type(struct machine *machine,
140 struct thread *thread) 138 struct thread *thread)
141{ 139{
@@ -156,6 +154,8 @@ static enum dso_type machine__thread_dso_type(struct machine *machine,
156 return dso_type; 154 return dso_type;
157} 155}
158 156
157#if BITS_PER_LONG == 64
158
159static int vdso__do_copy_compat(FILE *f, int fd) 159static int vdso__do_copy_compat(FILE *f, int fd)
160{ 160{
161 char buf[4096]; 161 char buf[4096];
@@ -283,8 +283,38 @@ static int __machine__findnew_vdso_compat(struct machine *machine,
283 283
284#endif 284#endif
285 285
286static struct dso *machine__find_vdso(struct machine *machine,
287 struct thread *thread)
288{
289 struct dso *dso = NULL;
290 enum dso_type dso_type;
291
292 dso_type = machine__thread_dso_type(machine, thread);
293 switch (dso_type) {
294 case DSO__TYPE_32BIT:
295 dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO32, true);
296 if (!dso) {
297 dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO,
298 true);
299 if (dso && dso_type != dso__type(dso, machine))
300 dso = NULL;
301 }
302 break;
303 case DSO__TYPE_X32BIT:
304 dso = __dsos__find(&machine->dsos, DSO__NAME_VDSOX32, true);
305 break;
306 case DSO__TYPE_64BIT:
307 case DSO__TYPE_UNKNOWN:
308 default:
309 dso = __dsos__find(&machine->dsos, DSO__NAME_VDSO, true);
310 break;
311 }
312
313 return dso;
314}
315
286struct dso *machine__findnew_vdso(struct machine *machine, 316struct dso *machine__findnew_vdso(struct machine *machine,
287 struct thread *thread __maybe_unused) 317 struct thread *thread)
288{ 318{
289 struct vdso_info *vdso_info; 319 struct vdso_info *vdso_info;
290 struct dso *dso = NULL; 320 struct dso *dso = NULL;
@@ -297,6 +327,10 @@ struct dso *machine__findnew_vdso(struct machine *machine,
297 if (!vdso_info) 327 if (!vdso_info)
298 goto out_unlock; 328 goto out_unlock;
299 329
330 dso = machine__find_vdso(machine, thread);
331 if (dso)
332 goto out_unlock;
333
300#if BITS_PER_LONG == 64 334#if BITS_PER_LONG == 64
301 if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso)) 335 if (__machine__findnew_vdso_compat(machine, thread, vdso_info, &dso))
302 goto out_unlock; 336 goto out_unlock;
diff --git a/tools/perf/util/wrapper.c b/tools/perf/util/wrapper.c
deleted file mode 100644
index 5f1a07c4b87b..000000000000
--- a/tools/perf/util/wrapper.c
+++ /dev/null
@@ -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}