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/perf-annotate.txt7
-rw-r--r--tools/perf/Documentation/perf-buildid-cache.txt3
-rw-r--r--tools/perf/Documentation/perf-config.txt12
-rw-r--r--tools/perf/Documentation/perf-data.txt4
-rw-r--r--tools/perf/Documentation/perf-list.txt12
-rw-r--r--tools/perf/Documentation/perf-mem.txt3
-rw-r--r--tools/perf/Documentation/perf-probe.txt52
-rw-r--r--tools/perf/Documentation/perf-record.txt105
-rw-r--r--tools/perf/Documentation/perf-report.txt7
-rw-r--r--tools/perf/Documentation/perf-script.txt35
-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.data-file-format.txt446
-rw-r--r--tools/perf/Documentation/perfconfig.example9
-rw-r--r--tools/perf/Documentation/tips.txt4
-rw-r--r--tools/perf/MANIFEST60
-rw-r--r--tools/perf/Makefile.config (renamed from tools/perf/config/Makefile)100
-rw-r--r--tools/perf/Makefile.perf141
-rw-r--r--tools/perf/arch/arm/include/dwarf-regs-table.h9
-rw-r--r--tools/perf/arch/arm/util/Build4
-rw-r--r--tools/perf/arch/arm/util/auxtrace.c54
-rw-r--r--tools/perf/arch/arm/util/cs-etm.c617
-rw-r--r--tools/perf/arch/arm/util/cs-etm.h26
-rw-r--r--tools/perf/arch/arm/util/pmu.c36
-rw-r--r--tools/perf/arch/arm64/include/dwarf-regs-table.h13
-rw-r--r--tools/perf/arch/arm64/util/Build6
-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/Build1
-rw-r--r--tools/perf/arch/powerpc/include/arch-tests.h13
-rw-r--r--tools/perf/arch/powerpc/include/dwarf-regs-table.h27
-rw-r--r--tools/perf/arch/powerpc/include/perf_regs.h2
-rw-r--r--tools/perf/arch/powerpc/tests/Build4
-rw-r--r--tools/perf/arch/powerpc/tests/arch-tests.c15
-rw-r--r--tools/perf/arch/powerpc/tests/dwarf-unwind.c62
-rw-r--r--tools/perf/arch/powerpc/tests/regs_load.S94
-rw-r--r--tools/perf/arch/powerpc/util/header.c11
-rw-r--r--tools/perf/arch/powerpc/util/sym-handling.c32
-rw-r--r--tools/perf/arch/s390/include/dwarf-regs-table.h8
-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/sh/include/dwarf-regs-table.h25
-rw-r--r--tools/perf/arch/sparc/include/dwarf-regs-table.h18
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl2
-rw-r--r--tools/perf/arch/x86/include/dwarf-regs-table.h14
-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.c6
-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/header.c24
-rw-r--r--tools/perf/arch/x86/util/intel-bts.c8
-rw-r--r--tools/perf/arch/x86/util/intel-pt.c73
-rw-r--r--tools/perf/arch/x86/util/tsc.c2
-rw-r--r--tools/perf/arch/x86/util/unwind-libunwind.c6
-rw-r--r--tools/perf/arch/xtensa/include/dwarf-regs-table.h8
-rw-r--r--tools/perf/bench/futex-hash.c15
-rw-r--r--tools/perf/bench/futex-lock-pi.c11
-rw-r--r--tools/perf/bench/futex-requeue.c16
-rw-r--r--tools/perf/bench/futex-wake-parallel.c16
-rw-r--r--tools/perf/bench/futex-wake.c16
-rw-r--r--tools/perf/bench/mem-functions.c3
-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.c57
-rw-r--r--tools/perf/bench/sched-messaging.c5
-rw-r--r--tools/perf/bench/sched-pipe.c9
-rw-r--r--tools/perf/builtin-annotate.c118
-rw-r--r--tools/perf/builtin-buildid-cache.c21
-rw-r--r--tools/perf/builtin-config.c21
-rw-r--r--tools/perf/builtin-data.c11
-rw-r--r--tools/perf/builtin-diff.c31
-rw-r--r--tools/perf/builtin-evlist.c2
-rw-r--r--tools/perf/builtin-help.c10
-rw-r--r--tools/perf/builtin-inject.c10
-rw-r--r--tools/perf/builtin-kmem.c15
-rw-r--r--tools/perf/builtin-kvm.c23
-rw-r--r--tools/perf/builtin-list.c24
-rw-r--r--tools/perf/builtin-mem.c4
-rw-r--r--tools/perf/builtin-probe.c73
-rw-r--r--tools/perf/builtin-record.c258
-rw-r--r--tools/perf/builtin-report.c29
-rw-r--r--tools/perf/builtin-sched.c39
-rw-r--r--tools/perf/builtin-script.c160
-rw-r--r--tools/perf/builtin-stat.c258
-rw-r--r--tools/perf/builtin-timechart.c13
-rw-r--r--tools/perf/builtin-top.c76
-rw-r--r--tools/perf/builtin-trace.c30
-rw-r--r--tools/perf/jvmti/jvmti_agent.c10
-rw-r--r--tools/perf/perf-sys.h20
-rw-r--r--tools/perf/perf.c58
-rw-r--r--tools/perf/perf.h10
-rw-r--r--tools/perf/pmu-events/Build13
-rw-r--r--tools/perf/pmu-events/README147
-rw-r--r--tools/perf/pmu-events/jevents.c814
-rw-r--r--tools/perf/pmu-events/jevents.h18
-rw-r--r--tools/perf/pmu-events/jsmn.c313
-rw-r--r--tools/perf/pmu-events/jsmn.h67
-rw-r--r--tools/perf/pmu-events/json.c162
-rw-r--r--tools/perf/pmu-events/json.h38
-rw-r--r--tools/perf/pmu-events/pmu-events.h37
-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/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.c20
-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.c73
-rw-r--r--tools/perf/tests/code-reading.c104
-rw-r--r--tools/perf/tests/cpumap.c31
-rw-r--r--tools/perf/tests/dso-data.c6
-rw-r--r--tools/perf/tests/dwarf-unwind.c2
-rw-r--r--tools/perf/tests/event-times.c5
-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_cumulate.c4
-rw-r--r--tools/perf/tests/hists_filter.c4
-rw-r--r--tools/perf/tests/hists_link.c8
-rw-r--r--tools/perf/tests/is_printable_array.c36
-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.c7
-rw-r--r--tools/perf/tests/openat-syscall-tp-fields.c11
-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.c11
-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.c2
-rw-r--r--tools/perf/tests/task-exit.c4
-rw-r--r--tools/perf/tests/tests.h4
-rw-r--r--tools/perf/tests/thread-map.c16
-rw-r--r--tools/perf/tests/vmlinux-kallsyms.c61
-rw-r--r--tools/perf/trace/beauty/eventfd.c2
-rw-r--r--tools/perf/trace/beauty/flock.c17
-rw-r--r--tools/perf/trace/beauty/futex_op.c16
-rw-r--r--tools/perf/trace/beauty/mmap.c41
-rw-r--r--tools/perf/trace/beauty/msg_flags.c1
-rw-r--r--tools/perf/trace/beauty/open_flags.c15
-rw-r--r--tools/perf/trace/beauty/sched_policy.c3
-rw-r--r--tools/perf/trace/beauty/seccomp.c2
-rw-r--r--tools/perf/ui/browser.c2
-rw-r--r--tools/perf/ui/browsers/annotate.c32
-rw-r--r--tools/perf/ui/browsers/hists.c185
-rw-r--r--tools/perf/ui/browsers/hists.h32
-rw-r--r--tools/perf/ui/browsers/map.c4
-rw-r--r--tools/perf/ui/gtk/annotate.c8
-rw-r--r--tools/perf/ui/gtk/hists.c4
-rw-r--r--tools/perf/ui/gtk/util.c1
-rw-r--r--tools/perf/ui/helpline.c1
-rw-r--r--tools/perf/ui/hist.c32
-rw-r--r--tools/perf/ui/setup.c7
-rw-r--r--tools/perf/ui/stdio/hist.c155
-rw-r--r--tools/perf/ui/tui/setup.c2
-rw-r--r--tools/perf/ui/ui.h4
-rw-r--r--tools/perf/util/Build12
-rw-r--r--tools/perf/util/alias.c2
-rw-r--r--tools/perf/util/annotate.c347
-rw-r--r--tools/perf/util/annotate.h27
-rw-r--r--tools/perf/util/auxtrace.c738
-rw-r--r--tools/perf/util/auxtrace.h57
-rw-r--r--tools/perf/util/block-range.c328
-rw-r--r--tools/perf/util/block-range.h71
-rw-r--r--tools/perf/util/bpf-loader.c205
-rw-r--r--tools/perf/util/bpf-loader.h12
-rw-r--r--tools/perf/util/build-id.c320
-rw-r--r--tools/perf/util/build-id.h8
-rw-r--r--tools/perf/util/cache.h23
-rw-r--r--tools/perf/util/callchain.h2
-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.c160
-rw-r--r--tools/perf/util/config.h40
-rw-r--r--tools/perf/util/cpumap.c68
-rw-r--r--tools/perf/util/cpumap.h3
-rw-r--r--tools/perf/util/cs-etm.h74
-rw-r--r--tools/perf/util/data-convert-bt.c243
-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.c4
-rw-r--r--tools/perf/util/db-export.c13
-rw-r--r--tools/perf/util/debug.c10
-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/drv_configs.c77
-rw-r--r--tools/perf/util/drv_configs.h26
-rw-r--r--tools/perf/util/dso.c31
-rw-r--r--tools/perf/util/dso.h8
-rw-r--r--tools/perf/util/dwarf-aux.c207
-rw-r--r--tools/perf/util/dwarf-aux.h11
-rw-r--r--tools/perf/util/dwarf-regs.c59
-rw-r--r--tools/perf/util/env.c5
-rw-r--r--tools/perf/util/env.h10
-rw-r--r--tools/perf/util/event.c25
-rw-r--r--tools/perf/util/evlist.c394
-rw-r--r--tools/perf/util/evlist.h92
-rw-r--r--tools/perf/util/evsel.c155
-rw-r--r--tools/perf/util/evsel.h36
-rw-r--r--tools/perf/util/evsel_fprintf.c7
-rw-r--r--tools/perf/util/group.h7
-rw-r--r--tools/perf/util/header.c97
-rw-r--r--tools/perf/util/header.h1
-rw-r--r--tools/perf/util/help-unknown-cmd.c2
-rw-r--r--tools/perf/util/hist.c397
-rw-r--r--tools/perf/util/hist.h43
-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/dwarf-regs.h6
-rw-r--r--tools/perf/util/include/linux/const.h1
-rw-r--r--tools/perf/util/intel-bts.c26
-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.c112
-rw-r--r--tools/perf/util/intel-pt-decoder/intel-pt-decoder.h1
-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.c202
-rw-r--r--tools/perf/util/intel-pt.h4
-rw-r--r--tools/perf/util/intlist.h8
-rw-r--r--tools/perf/util/jitdump.c3
-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/lzma.c15
-rw-r--r--tools/perf/util/machine.c72
-rw-r--r--tools/perf/util/machine.h35
-rw-r--r--tools/perf/util/map.c51
-rw-r--r--tools/perf/util/map.h34
-rw-r--r--tools/perf/util/mem-events.c17
-rw-r--r--tools/perf/util/mem-events.h1
-rw-r--r--tools/perf/util/parse-events.c198
-rw-r--r--tools/perf/util/parse-events.h11
-rw-r--r--tools/perf/util/parse-events.l26
-rw-r--r--tools/perf/util/parse-events.y11
-rw-r--r--tools/perf/util/path.c67
-rw-r--r--tools/perf/util/pmu.c191
-rw-r--r--tools/perf/util/pmu.h8
-rw-r--r--tools/perf/util/probe-event.c698
-rw-r--r--tools/perf/util/probe-event.h15
-rw-r--r--tools/perf/util/probe-file.c639
-rw-r--r--tools/perf/util/probe-file.h52
-rw-r--r--tools/perf/util/probe-finder.c101
-rw-r--r--tools/perf/util/probe-finder.h1
-rw-r--r--tools/perf/util/python-ext-sources1
-rw-r--r--tools/perf/util/python.c152
-rw-r--r--tools/perf/util/quote.c4
-rw-r--r--tools/perf/util/quote.h3
-rw-r--r--tools/perf/util/rb_resort.h4
-rw-r--r--tools/perf/util/record.c8
-rw-r--r--tools/perf/util/scripting-engines/trace-event-perl.c5
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c34
-rw-r--r--tools/perf/util/session.c36
-rw-r--r--tools/perf/util/sort.c63
-rw-r--r--tools/perf/util/sort.h20
-rw-r--r--tools/perf/util/stat-shadow.c162
-rw-r--r--tools/perf/util/stat.c11
-rw-r--r--tools/perf/util/stat.h5
-rw-r--r--tools/perf/util/strbuf.c2
-rw-r--r--tools/perf/util/strbuf.h6
-rw-r--r--tools/perf/util/strlist.h4
-rw-r--r--tools/perf/util/svghelper.c11
-rw-r--r--tools/perf/util/symbol-elf.c380
-rw-r--r--tools/perf/util/symbol-minimal.c4
-rw-r--r--tools/perf/util/symbol.c270
-rw-r--r--tools/perf/util/symbol.h48
-rw-r--r--tools/perf/util/target.c7
-rw-r--r--tools/perf/util/thread-stack.c7
-rw-r--r--tools/perf/util/thread-stack.h1
-rw-r--r--tools/perf/util/thread.c70
-rw-r--r--tools/perf/util/thread.h11
-rw-r--r--tools/perf/util/thread_map.c4
-rw-r--r--tools/perf/util/trace-event.c8
-rw-r--r--tools/perf/util/trace-event.h2
-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.c695
-rw-r--r--tools/perf/util/unwind.h34
-rw-r--r--tools/perf/util/util.c49
-rw-r--r--tools/perf/util/util.h11
-rw-r--r--tools/perf/util/vdso.c40
303 files changed, 18145 insertions, 3225 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/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index 778f54d4d0bd..8ffbd272952d 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -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-config.txt b/tools/perf/Documentation/perf-config.txt
index 15949e2a7805..cb081ac59fd1 100644
--- a/tools/perf/Documentation/perf-config.txt
+++ b/tools/perf/Documentation/perf-config.txt
@@ -110,6 +110,14 @@ Given a $HOME/.perfconfig like this:
110 order = caller 110 order = caller
111 sort-key = function 111 sort-key = function
112 112
113 [report]
114 # Defaults
115 sort-order = comm,dso,symbol
116 percent-limit = 0
117 queue-size = 0
118 children = true
119 group = true
120
113Variables 121Variables
114~~~~~~~~~ 122~~~~~~~~~
115 123
@@ -382,6 +390,10 @@ call-graph.*::
382 histogram entry. Default is 0 which means no limitation. 390 histogram entry. Default is 0 which means no limitation.
383 391
384report.*:: 392report.*::
393 report.sort_order::
394 Allows changing the default sort order from "comm,dso,symbol" to
395 some other default, for instance "sym,dso" may be more fitting for
396 kernel developers.
385 report.percent-limit:: 397 report.percent-limit::
386 This one is mostly the same as call-graph.threshold but works for 398 This one is mostly the same as call-graph.threshold but works for
387 histogram entries. Entries having an overhead lower than this 399 histogram entries. Entries having an overhead lower than this
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-list.txt b/tools/perf/Documentation/perf-list.txt
index a126e97a8114..41857cce5e86 100644
--- a/tools/perf/Documentation/perf-list.txt
+++ b/tools/perf/Documentation/perf-list.txt
@@ -8,13 +8,23 @@ perf-list - List all symbolic event types
8SYNOPSIS 8SYNOPSIS
9-------- 9--------
10[verse] 10[verse]
11'perf list' [hw|sw|cache|tracepoint|pmu|event_glob] 11'perf list' [--no-desc] [--long-desc] [hw|sw|cache|tracepoint|pmu|event_glob]
12 12
13DESCRIPTION 13DESCRIPTION
14----------- 14-----------
15This command displays the symbolic event types which can be selected in the 15This command displays the symbolic event types which can be selected in the
16various perf commands with the -e option. 16various perf commands with the -e option.
17 17
18OPTIONS
19-------
20--no-desc::
21Don't print descriptions.
22
23-v::
24--long-desc::
25Print longer event descriptions.
26
27
18[[EVENT_MODIFIERS]] 28[[EVENT_MODIFIERS]]
19EVENT MODIFIERS 29EVENT MODIFIERS
20--------------- 30---------------
diff --git a/tools/perf/Documentation/perf-mem.txt b/tools/perf/Documentation/perf-mem.txt
index 1d6092c460dd..73496320fca3 100644
--- a/tools/perf/Documentation/perf-mem.txt
+++ b/tools/perf/Documentation/perf-mem.txt
@@ -56,6 +56,9 @@ OPTIONS
56--all-user:: 56--all-user::
57 Configure all used events to run in user space. 57 Configure all used events to run in user space.
58 58
59--ldload::
60 Specify desired latency for loads event.
61
59SEE ALSO 62SEE ALSO
60-------- 63--------
61linkperf: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..e6c9902c6d82 100644
--- a/tools/perf/Documentation/perf-probe.txt
+++ b/tools/perf/Documentation/perf-probe.txt
@@ -21,6 +21,8 @@ or
21'perf probe' [options] --vars='PROBEPOINT' 21'perf probe' [options] --vars='PROBEPOINT'
22or 22or
23'perf probe' [options] --funcs 23'perf probe' [options] --funcs
24or
25'perf probe' [options] --definition='PROBE' [...]
24 26
25DESCRIPTION 27DESCRIPTION
26----------- 28-----------
@@ -34,6 +36,8 @@ OPTIONS
34-k:: 36-k::
35--vmlinux=PATH:: 37--vmlinux=PATH::
36 Specify vmlinux path which has debuginfo (Dwarf binary). 38 Specify vmlinux path which has debuginfo (Dwarf binary).
39 Only when using this with --definition, you can give an offline
40 vmlinux file.
37 41
38-m:: 42-m::
39--module=MODNAME|PATH:: 43--module=MODNAME|PATH::
@@ -67,7 +71,10 @@ OPTIONS
67 71
68-l:: 72-l::
69--list[=[GROUP:]EVENT]:: 73--list[=[GROUP:]EVENT]::
70 List up current probe events. This can also accept filtering patterns of event names. 74 List up current probe events. This can also accept filtering patterns of
75 event names.
76 When this is used with --cache, perf shows all cached probes instead of
77 the live probes.
71 78
72-L:: 79-L::
73--line=:: 80--line=::
@@ -93,6 +100,11 @@ OPTIONS
93 can also list functions in a user space executable / shared library. 100 can also list functions in a user space executable / shared library.
94 This also can accept a FILTER rule argument. 101 This also can accept a FILTER rule argument.
95 102
103-D::
104--definition=::
105 Show trace-event definition converted from given probe-event instead
106 of write it into tracing/[k,u]probe_events.
107
96--filter=FILTER:: 108--filter=FILTER::
97 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob 109 (Only for --vars and --funcs) Set filter. FILTER is a combination of glob
98 pattern, see FILTER PATTERN for detail. 110 pattern, see FILTER PATTERN for detail.
@@ -109,6 +121,12 @@ OPTIONS
109 Dry run. With this option, --add and --del doesn't execute actual 121 Dry run. With this option, --add and --del doesn't execute actual
110 adding and removal operations. 122 adding and removal operations.
111 123
124--cache::
125 (With --add) Cache the probes. Any events which successfully added
126 are also stored in the cache file.
127 (With --list) Show cached probes.
128 (With --del) Remove cached probes.
129
112--max-probes=NUM:: 130--max-probes=NUM::
113 Set the maximum number of probe points for an event. Default is 128. 131 Set the maximum number of probe points for an event. Default is 128.
114 132
@@ -134,19 +152,30 @@ PROBE SYNTAX
134Probe points are defined by following syntax. 152Probe points are defined by following syntax.
135 153
136 1) Define event based on function name 154 1) Define event based on function name
137 [EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...] 155 [[GROUP:]EVENT=]FUNC[@SRC][:RLN|+OFFS|%return|;PTN] [ARG ...]
138 156
139 2) Define event based on source file with line number 157 2) Define event based on source file with line number
140 [EVENT=]SRC:ALN [ARG ...] 158 [[GROUP:]EVENT=]SRC:ALN [ARG ...]
141 159
142 3) Define event based on source file with lazy pattern 160 3) Define event based on source file with lazy pattern
143 [EVENT=]SRC;PTN [ARG ...] 161 [[GROUP:]EVENT=]SRC;PTN [ARG ...]
144 162
163 4) Pre-defined SDT events or cached event with name
164 %[sdt_PROVIDER:]SDTEVENT
165 or,
166 sdt_PROVIDER:SDTEVENT
145 167
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'. 168'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.
169Note 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
170modules.
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. 171'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. 172It 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). 173'ARG' specifies the arguments of this probe point, (see PROBE ARGUMENT).
174'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.
175Note 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.
176
177For details of the SDT, see below.
178https://sourceware.org/gdb/onlinedocs/gdb/Static-Probe-Points.html
150 179
151PROBE ARGUMENT 180PROBE ARGUMENT
152-------------- 181--------------
@@ -156,10 +185,17 @@ Each probe argument follows below syntax.
156 185
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'.) 186'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. 187'$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. 188'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), hexadecimal integers (x/x8/x16/x32/x64), signedness casting (u/s), "string" and bitfield are supported. (see TYPES for detail)
160
161On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid. 189On x86 systems %REG is always the short form of the register: for example %AX. %RAX or %EAX is not valid.
162 190
191TYPES
192-----
193Basic types (u8/u16/u32/u64/s8/s16/s32/s64) and hexadecimal integers (x8/x16/x32/x64) are integer types. Prefix 's' and 'u' means those types are signed and unsigned respectively, and 'x' means that is shown in hexadecimal format. Traced arguments are shown in decimal (sNN/uNN) or hex (xNN). You can also use 's' or 'u' to specify only signedness and leave its size auto-detected by perf probe. Moreover, you can use 'x' to explicitly specify to be shown in hexadecimal (the size is also auto-detected).
194String 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.
195Bitfield is another special type, which takes 3 parameters, bit-width, bit-offset, and container-size (usually 32). The syntax is;
196
197 b<bit-width>@<bit-offset>/<container-size>
198
163LINE SYNTAX 199LINE SYNTAX
164----------- 200-----------
165Line range is described by following syntax. 201Line range is described by following syntax.
@@ -226,4 +262,4 @@ Add probes at malloc() function on libc
226 262
227SEE ALSO 263SEE ALSO
228-------- 264--------
229linkperf:perf-trace[1], linkperf:perf-record[1] 265linkperf: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 8dbee832abd9..92335193dc33 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -35,15 +35,15 @@ OPTIONS
35 35
36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where 36 - a symbolically formed PMU event like 'pmu/param1=0x3,param2/' where
37 'param1', 'param2', etc are defined as formats for the PMU in 37 'param1', 'param2', etc are defined as formats for the PMU in
38 /sys/bus/event_sources/devices/<pmu>/format/*. 38 /sys/bus/event_source/devices/<pmu>/format/*.
39 39
40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/' 40 - a symbolically formed event like 'pmu/config=M,config1=N,config3=K/'
41 41
42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable 42 where M, N, K are numbers (in decimal, hex, octal format). Acceptable
43 values for each of 'config', 'config1' and 'config2' are defined by 43 values for each of 'config', 'config1' and 'config2' are defined by
44 corresponding entries in /sys/bus/event_sources/devices/<pmu>/format/* 44 corresponding entries in /sys/bus/event_source/devices/<pmu>/format/*
45 param1 and param2 are defined as formats for the PMU in: 45 param1 and param2 are defined as formats for the PMU in:
46 /sys/bus/event_sources/devices/<pmu>/format/* 46 /sys/bus/event_source/devices/<pmu>/format/*
47 47
48 There are also some params which are not defined in .../<pmu>/format/*. 48 There are also some params which are not defined in .../<pmu>/format/*.
49 These params can be used to overload default config values per event. 49 These params can be used to overload default config values per event.
@@ -60,6 +60,18 @@ OPTIONS
60 Note: If user explicitly sets options which conflict with the params, 60 Note: If user explicitly sets options which conflict with the params,
61 the value set by the params will be overridden. 61 the value set by the params will be overridden.
62 62
63 Also not defined in .../<pmu>/format/* are PMU driver specific
64 configuration parameters. Any configuration parameter preceded by
65 the letter '@' is not interpreted in user space and sent down directly
66 to the PMU driver. For example:
67
68 perf record -e some_event/@cfg1,@cfg2=config/ ...
69
70 will see 'cfg1' and 'cfg2=config' pushed to the PMU driver associated
71 with the event for further processing. There is no restriction on
72 what the configuration parameters are, as long as their semantic is
73 understood and supported by the PMU driver.
74
63 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]' 75 - a hardware breakpoint event in the form of '\mem:addr[/len][:access]'
64 where addr is the address in memory you want to break in. 76 where addr is the address in memory you want to break in.
65 Access is the memory access type (read, write, execute) it can 77 Access is the memory access type (read, write, execute) it can
@@ -77,9 +89,62 @@ OPTIONS
77 89
78--filter=<filter>:: 90--filter=<filter>::
79 Event filter. This option should follow a event selector (-e) which 91 Event filter. This option should follow a event selector (-e) which
80 selects tracepoint event(s). Multiple '--filter' options are combined 92 selects either tracepoint event(s) or a hardware trace PMU
93 (e.g. Intel PT or CoreSight).
94
95 - tracepoint filters
96
97 In the case of tracepoints, multiple '--filter' options are combined
81 using '&&'. 98 using '&&'.
82 99
100 - address filters
101
102 A hardware trace PMU advertises its ability to accept a number of
103 address filters by specifying a non-zero value in
104 /sys/bus/event_source/devices/<pmu>/nr_addr_filters.
105
106 Address filters have the format:
107
108 filter|start|stop|tracestop <start> [/ <size>] [@<file name>]
109
110 Where:
111 - 'filter': defines a region that will be traced.
112 - 'start': defines an address at which tracing will begin.
113 - 'stop': defines an address at which tracing will stop.
114 - 'tracestop': defines a region in which tracing will stop.
115
116 <file name> is the name of the object file, <start> is the offset to the
117 code to trace in that file, and <size> is the size of the region to
118 trace. 'start' and 'stop' filters need not specify a <size>.
119
120 If no object file is specified then the kernel is assumed, in which case
121 the start address must be a current kernel memory address.
122
123 <start> can also be specified by providing the name of a symbol. If the
124 symbol name is not unique, it can be disambiguated by inserting #n where
125 'n' selects the n'th symbol in address order. Alternately #0, #g or #G
126 select only a global symbol. <size> can also be specified by providing
127 the name of a symbol, in which case the size is calculated to the end
128 of that symbol. For 'filter' and 'tracestop' filters, if <size> is
129 omitted and <start> is a symbol, then the size is calculated to the end
130 of that symbol.
131
132 If <size> is omitted and <start> is '*', then the start and size will
133 be calculated from the first and last symbols, i.e. to trace the whole
134 file.
135
136 If symbol names (or '*') are provided, they must be surrounded by white
137 space.
138
139 The filter passed to the kernel is not necessarily the same as entered.
140 To see the filter that is passed, use the -v option.
141
142 The kernel may not be able to configure a trace region if it is not
143 within a single mapping. MMAP events (or /proc/<pid>/maps) can be
144 examined to determine if that is a possibility.
145
146 Multiple filters can be separated with space or comma.
147
83--exclude-perf:: 148--exclude-perf::
84 Don't record events issued by perf itself. This option should follow 149 Don't record events issued by perf itself. This option should follow
85 a event selector (-e) which selects tracepoint event(s). It adds a 150 a event selector (-e) which selects tracepoint event(s). It adds a
@@ -192,6 +257,9 @@ OPTIONS
192--period:: 257--period::
193 Record the sample period. 258 Record the sample period.
194 259
260--sample-cpu::
261 Record the sample cpu.
262
195-n:: 263-n::
196--no-samples:: 264--no-samples::
197 Don't sample. 265 Don't sample.
@@ -360,6 +428,35 @@ particular perf.data snapshot should be kept or not.
360 428
361Implies --timestamp-filename, --no-buildid and --no-buildid-cache. 429Implies --timestamp-filename, --no-buildid and --no-buildid-cache.
362 430
431--dry-run::
432Parse options then exit. --dry-run can be used to detect errors in cmdline
433options.
434
435'perf record --dry-run -e' can act as a BPF script compiler if llvm.dump-obj
436in config file is set to true.
437
438--tail-synthesize::
439Instead of collecting non-sample events (for example, fork, comm, mmap) at
440the beginning of record, collect them during finalizing an output file.
441The collected non-sample events reflects the status of the system when
442record is finished.
443
444--overwrite::
445Makes all events use an overwritable ring buffer. An overwritable ring
446buffer works like a flight recorder: when it gets full, the kernel will
447overwrite the oldest records, that thus will never make it to the
448perf.data file.
449
450When '--overwrite' and '--switch-output' are used perf records and drops
451events until it receives a signal, meaning that something unusual was
452detected that warrants taking a snapshot of the most current events,
453those fitting in the ring buffer at that moment.
454
455'overwrite' attribute can also be set or canceled for an event using
456config terms. For example: 'cycles/overwrite/' and 'instructions/no-overwrite/'.
457
458Implies --tail-synthesize.
459
363SEE ALSO 460SEE ALSO
364-------- 461--------
365linkperf:perf-stat[1], linkperf:perf-list[1] 462linkperf:perf-stat[1], linkperf:perf-list[1]
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
index 9cbddc290aff..2d1746295abf 100644
--- a/tools/perf/Documentation/perf-report.txt
+++ b/tools/perf/Documentation/perf-report.txt
@@ -265,6 +265,13 @@ OPTIONS
265 265
266--stdio:: Use the stdio interface. 266--stdio:: Use the stdio interface.
267 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
268--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
269 zooming into DSOs or threads, among other features. Use of --tui 276 zooming into DSOs or threads, among other features. Use of --tui
270 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
diff --git a/tools/perf/Documentation/perf-script.txt b/tools/perf/Documentation/perf-script.txt
index 4fc44c75263f..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:
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.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
new file mode 100644
index 000000000000..b664b18d3991
--- /dev/null
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -0,0 +1,446 @@
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/platform2
441
442It is under the chromiumos-wide-profiling/ subdirectory. This library can
443convert a perf data file to a protobuf and vice versa.
444
445Unfortunately this parser tends to be many versions behind and may not be able
446to parse data files generated by recent perf.
diff --git a/tools/perf/Documentation/perfconfig.example b/tools/perf/Documentation/perfconfig.example
index 1d8d5bc4cd2d..2b477c1d1efe 100644
--- a/tools/perf/Documentation/perfconfig.example
+++ b/tools/perf/Documentation/perfconfig.example
@@ -27,3 +27,12 @@
27 use_offset = true 27 use_offset = true
28 jump_arrows = true 28 jump_arrows = true
29 show_nr_jumps = false 29 show_nr_jumps = false
30
31[report]
32
33 # Defaults
34 sort-order = comm,dso,symbol
35 percent-limit = 0
36 queue-size = 0
37 children = true
38 group = true
diff --git a/tools/perf/Documentation/tips.txt b/tools/perf/Documentation/tips.txt
index 5950b5a24efd..8a6479c0eac9 100644
--- a/tools/perf/Documentation/tips.txt
+++ b/tools/perf/Documentation/tips.txt
@@ -28,3 +28,7 @@ To change sampling frequency to 100 Hz: perf record -F 100
28See assembly instructions with percentage: perf annotate <symbol> 28See assembly instructions with percentage: perf annotate <symbol>
29If you prefer Intel style assembly, try: perf annotate -M intel 29If you prefer Intel style assembly, try: perf annotate -M intel
30For hierarchical output, try: perf report --hierarchy 30For hierarchical output, try: perf report --hierarchy
31Order by the overhead of source file name and line number: perf report -s srcline
32System-wide collection from all CPUs: perf record -a
33Show current config key-value pairs: perf config --list
34Show user configuration overrides: perf config --user --list
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 8c8c6b9ce915..0bda2cca2b3a 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
@@ -47,48 +60,27 @@ tools/include/asm-generic/bitops.h
47tools/include/linux/atomic.h 60tools/include/linux/atomic.h
48tools/include/linux/bitops.h 61tools/include/linux/bitops.h
49tools/include/linux/compiler.h 62tools/include/linux/compiler.h
63tools/include/linux/coresight-pmu.h
50tools/include/linux/filter.h 64tools/include/linux/filter.h
51tools/include/linux/hash.h 65tools/include/linux/hash.h
52tools/include/linux/kernel.h 66tools/include/linux/kernel.h
53tools/include/linux/list.h 67tools/include/linux/list.h
54tools/include/linux/log2.h 68tools/include/linux/log2.h
69tools/include/uapi/asm-generic/mman-common.h
70tools/include/uapi/asm-generic/mman.h
71tools/include/uapi/linux/bpf.h
72tools/include/uapi/linux/bpf_common.h
73tools/include/uapi/linux/hw_breakpoint.h
74tools/include/uapi/linux/mman.h
75tools/include/uapi/linux/perf_event.h
55tools/include/linux/poison.h 76tools/include/linux/poison.h
56tools/include/linux/rbtree.h 77tools/include/linux/rbtree.h
57tools/include/linux/rbtree_augmented.h 78tools/include/linux/rbtree_augmented.h
58tools/include/linux/string.h 79tools/include/linux/string.h
80tools/include/linux/stringify.h
59tools/include/linux/types.h 81tools/include/linux/types.h
60tools/include/linux/err.h 82tools/include/linux/err.h
61tools/include/linux/bitmap.h 83tools/include/linux/bitmap.h
62include/asm-generic/bitops/arch_hweight.h 84tools/include/linux/time64.h
63include/asm-generic/bitops/const_hweight.h 85tools/arch/*/include/uapi/asm/mman.h
64include/asm-generic/bitops/fls64.h 86tools/arch/*/include/uapi/asm/perf_regs.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 5ad0255f8756..72edf83d76b7 100644
--- a/tools/perf/config/Makefile
+++ b/tools/perf/Makefile.config
@@ -73,17 +73,25 @@ endif
73# 73#
74# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/ 74# make DEBUG=1 LIBUNWIND_DIR=/opt/libunwind/
75# 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
76ifdef LIBUNWIND_DIR 83ifdef LIBUNWIND_DIR
77 LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include 84 LIBUNWIND_CFLAGS = -I$(LIBUNWIND_DIR)/include
78 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)))
79endif 88endif
80LIBUNWIND_LDFLAGS += $(LIBUNWIND_LIBS)
81 89
82# Set per-feature check compilation flags 90# Set per-feature check compilation flags
83FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS) 91FEATURE_CHECK_CFLAGS-libunwind = $(LIBUNWIND_CFLAGS)
84FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) 92FEATURE_CHECK_LDFLAGS-libunwind = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
85FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS) 93FEATURE_CHECK_CFLAGS-libunwind-debug-frame = $(LIBUNWIND_CFLAGS)
86FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) 94FEATURE_CHECK_LDFLAGS-libunwind-debug-frame = $(LIBUNWIND_LDFLAGS) $(LIBUNWIND_LIBS)
87 95
88ifeq ($(NO_PERF_REGS),0) 96ifeq ($(NO_PERF_REGS),0)
89 CFLAGS += -DHAVE_PERF_REGS_SUPPORT 97 CFLAGS += -DHAVE_PERF_REGS_SUPPORT
@@ -107,7 +115,7 @@ endif
107FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS) 115FEATURE_CHECK_CFLAGS-libbabeltrace := $(LIBBABELTRACE_CFLAGS)
108FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf 116FEATURE_CHECK_LDFLAGS-libbabeltrace := $(LIBBABELTRACE_LDFLAGS) -lbabeltrace-ctf
109 117
110FEATURE_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
111# include ARCH specific config 119# include ARCH specific config
112-include $(src-perf)/arch/$(ARCH)/Makefile 120-include $(src-perf)/arch/$(ARCH)/Makefile
113 121
@@ -198,11 +206,11 @@ endif
198 206
199CFLAGS += -I$(src-perf)/util/include 207CFLAGS += -I$(src-perf)/util/include
200CFLAGS += -I$(src-perf)/arch/$(ARCH)/include 208CFLAGS += -I$(src-perf)/arch/$(ARCH)/include
209CFLAGS += -I$(srctree)/tools/include/uapi
201CFLAGS += -I$(srctree)/tools/include/ 210CFLAGS += -I$(srctree)/tools/include/
202CFLAGS += -I$(srctree)/arch/$(ARCH)/include/uapi 211CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/uapi
203CFLAGS += -I$(srctree)/arch/$(ARCH)/include 212CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/include/
204CFLAGS += -I$(srctree)/include/uapi 213CFLAGS += -I$(srctree)/tools/arch/$(ARCH)/
205CFLAGS += -I$(srctree)/include
206 214
207# $(obj-perf) for generated common-cmds.h 215# $(obj-perf) for generated common-cmds.h
208# $(obj-perf)/util for generated bison/flex headers 216# $(obj-perf)/util for generated bison/flex headers
@@ -249,7 +257,7 @@ else
249 LIBC_SUPPORT := 1 257 LIBC_SUPPORT := 1
250 endif 258 endif
251 ifeq ($(LIBC_SUPPORT),1) 259 ifeq ($(LIBC_SUPPORT),1)
252 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);
253 261
254 NO_LIBELF := 1 262 NO_LIBELF := 1
255 NO_DWARF := 1 263 NO_DWARF := 1
@@ -301,6 +309,16 @@ ifndef NO_LIBELF
301 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT 309 CFLAGS += -DHAVE_ELF_GETPHDRNUM_SUPPORT
302 endif 310 endif
303 311
312 ifeq ($(feature-libelf-gelf_getnote), 1)
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
321
304 ifndef NO_DWARF 322 ifndef NO_DWARF
305 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined) 323 ifeq ($(origin PERF_HAVE_DWARF_REGS), undefined)
306 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled); 324 msg := $(warning DWARF register mappings have not been defined for architecture $(ARCH), DWARF support disabled);
@@ -337,6 +355,16 @@ ifndef NO_LIBELF
337 endif # NO_LIBBPF 355 endif # NO_LIBBPF
338endif # NO_LIBELF 356endif # NO_LIBELF
339 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
340ifdef PERF_HAVE_JITDUMP 368ifdef PERF_HAVE_JITDUMP
341 ifndef NO_DWARF 369 ifndef NO_DWARF
342 $(call detected,CONFIG_JITDUMP) 370 $(call detected,CONFIG_JITDUMP)
@@ -351,10 +379,42 @@ ifeq ($(ARCH),powerpc)
351endif 379endif
352 380
353ifndef 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
354 ifneq ($(feature-libunwind), 1) 405 ifneq ($(feature-libunwind), 1)
355 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)
356 NO_LIBUNWIND := 1 414 NO_LIBUNWIND := 1
357 endif 415 endif
416else
417 NO_LOCAL_LIBUNWIND := 1
358endif 418endif
359 419
360ifndef NO_LIBBPF 420ifndef NO_LIBBPF
@@ -392,7 +452,7 @@ else
392 NO_DWARF_UNWIND := 1 452 NO_DWARF_UNWIND := 1
393endif 453endif
394 454
395ifndef NO_LIBUNWIND 455ifndef NO_LOCAL_LIBUNWIND
396 ifeq ($(ARCH),$(filter $(ARCH),arm arm64)) 456 ifeq ($(ARCH),$(filter $(ARCH),arm arm64))
397 $(call feature_check,libunwind-debug-frame) 457 $(call feature_check,libunwind-debug-frame)
398 ifneq ($(feature-libunwind-debug-frame), 1) 458 ifneq ($(feature-libunwind-debug-frame), 1)
@@ -403,10 +463,15 @@ ifndef NO_LIBUNWIND
403 # non-ARM has no dwarf_find_debug_frame() function: 463 # non-ARM has no dwarf_find_debug_frame() function:
404 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME 464 CFLAGS += -DNO_LIBUNWIND_DEBUG_FRAME
405 endif 465 endif
406 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
407 EXTLIBS += $(LIBUNWIND_LIBS) 466 EXTLIBS += $(LIBUNWIND_LIBS)
467 LDFLAGS += $(LIBUNWIND_LIBS)
468endif
469
470ifndef NO_LIBUNWIND
471 CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
408 CFLAGS += $(LIBUNWIND_CFLAGS) 472 CFLAGS += $(LIBUNWIND_CFLAGS)
409 LDFLAGS += $(LIBUNWIND_LDFLAGS) 473 LDFLAGS += $(LIBUNWIND_LDFLAGS)
474 EXTLIBS += $(EXTLIBS_LIBUNWIND)
410endif 475endif
411 476
412ifndef NO_LIBAUDIT 477ifndef NO_LIBAUDIT
@@ -437,7 +502,7 @@ endif
437 502
438ifndef NO_SLANG 503ifndef NO_SLANG
439 ifneq ($(feature-libslang), 1) 504 ifneq ($(feature-libslang), 1)
440 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);
441 NO_SLANG := 1 506 NO_SLANG := 1
442 else 507 else
443 # 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
@@ -681,10 +746,13 @@ ifdef LIBBABELTRACE
681endif 746endif
682 747
683ifndef NO_AUXTRACE 748ifndef NO_AUXTRACE
684 ifeq ($(feature-get_cpuid), 0) 749 ifeq ($(ARCH),x86)
685 msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); 750 ifeq ($(feature-get_cpuid), 0)
686 NO_AUXTRACE := 1 751 msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc);
687 else 752 NO_AUXTRACE := 1
753 endif
754 endif
755 ifndef NO_AUXTRACE
688 $(call detected,CONFIG_AUXTRACE) 756 $(call detected,CONFIG_AUXTRACE)
689 CFLAGS += -DHAVE_AUXTRACE_SUPPORT 757 CFLAGS += -DHAVE_AUXTRACE_SUPPORT
690 endif 758 endif
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index bde8cbae7dd9..982d6439bb07 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
@@ -141,6 +144,10 @@ $(call allow-override,LD,$(CROSS_COMPILE)ld)
141 144
142LD += $(EXTRA_LDFLAGS) 145LD += $(EXTRA_LDFLAGS)
143 146
147HOSTCC ?= gcc
148HOSTLD ?= ld
149HOSTAR ?= ar
150
144PKG_CONFIG = $(CROSS_COMPILE)pkg-config 151PKG_CONFIG = $(CROSS_COMPILE)pkg-config
145 152
146RM = rm -f 153RM = rm -f
@@ -158,11 +165,11 @@ TRACE_EVENT_DIR = $(srctree)/tools/lib/traceevent/
158BPF_DIR = $(srctree)/tools/lib/bpf/ 165BPF_DIR = $(srctree)/tools/lib/bpf/
159SUBCMD_DIR = $(srctree)/tools/lib/subcmd/ 166SUBCMD_DIR = $(srctree)/tools/lib/subcmd/
160 167
161# include config/Makefile by default and rule out 168# include Makefile.config by default and rule out
162# non-config cases 169# non-config cases
163config := 1 170config := 1
164 171
165NON_CONFIG_TARGETS := clean TAGS tags cscope help 172NON_CONFIG_TARGETS := clean TAGS tags cscope help install-doc
166 173
167ifdef MAKECMDGOALS 174ifdef MAKECMDGOALS
168ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),) 175ifeq ($(filter-out $(NON_CONFIG_TARGETS),$(MAKECMDGOALS)),)
@@ -180,7 +187,7 @@ ifeq ($(filter feature-dump,$(MAKECMDGOALS)),feature-dump)
180FEATURE_TESTS := all 187FEATURE_TESTS := all
181endif 188endif
182endif 189endif
183include config/Makefile 190include Makefile.config
184endif 191endif
185 192
186ifeq ($(config),0) 193ifeq ($(config),0)
@@ -254,7 +261,8 @@ PYTHON_EXT_SRCS := $(shell grep -v ^\# util/python-ext-sources)
254PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI) 261PYTHON_EXT_DEPS := util/python-ext-sources util/setup.py $(LIBTRACEEVENT) $(LIBAPI)
255 262
256$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST) 263$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
257 $(QUIET_GEN)CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \ 264 $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
265 CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
258 $(PYTHON_WORD) util/setup.py \ 266 $(PYTHON_WORD) util/setup.py \
259 --quiet build_ext; \ 267 --quiet build_ext; \
260 mkdir -p $(OUTPUT)python && \ 268 mkdir -p $(OUTPUT)python && \
@@ -341,14 +349,126 @@ strip: $(PROGRAMS) $(OUTPUT)perf
341PERF_IN := $(OUTPUT)perf-in.o 349PERF_IN := $(OUTPUT)perf-in.o
342 350
343export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK 351export srctree OUTPUT RM CC LD AR CFLAGS V BISON FLEX AWK
352export HOSTCC HOSTLD HOSTAR
344include $(srctree)/tools/build/Makefile.include 353include $(srctree)/tools/build/Makefile.include
345 354
355JEVENTS := $(OUTPUT)pmu-events/jevents
356JEVENTS_IN := $(OUTPUT)pmu-events/jevents-in.o
357
358PMU_EVENTS_IN := $(OUTPUT)pmu-events/pmu-events-in.o
359
360export JEVENTS
361
362build := -f $(srctree)/tools/build/Makefile.build dir=. obj
363
346$(PERF_IN): prepare FORCE 364$(PERF_IN): prepare FORCE
365 @(test -f ../../include/uapi/linux/perf_event.h && ( \
366 (diff -B ../include/uapi/linux/perf_event.h ../../include/uapi/linux/perf_event.h >/dev/null) \
367 || echo "Warning: tools/include/uapi/linux/perf_event.h differs from kernel" >&2 )) || true
368 @(test -f ../../include/linux/hash.h && ( \
369 (diff -B ../include/linux/hash.h ../../include/linux/hash.h >/dev/null) \
370 || echo "Warning: tools/include/linux/hash.h differs from kernel" >&2 )) || true
371 @(test -f ../../include/uapi/linux/hw_breakpoint.h && ( \
372 (diff -B ../include/uapi/linux/hw_breakpoint.h ../../include/uapi/linux/hw_breakpoint.h >/dev/null) \
373 || echo "Warning: tools/include/uapi/linux/hw_breakpoint.h differs from kernel" >&2 )) || true
374 @(test -f ../../arch/x86/include/asm/disabled-features.h && ( \
375 (diff -B ../arch/x86/include/asm/disabled-features.h ../../arch/x86/include/asm/disabled-features.h >/dev/null) \
376 || echo "Warning: tools/arch/x86/include/asm/disabled-features.h differs from kernel" >&2 )) || true
377 @(test -f ../../arch/x86/include/asm/required-features.h && ( \
378 (diff -B ../arch/x86/include/asm/required-features.h ../../arch/x86/include/asm/required-features.h >/dev/null) \
379 || echo "Warning: tools/arch/x86/include/asm/required-features.h differs from kernel" >&2 )) || true
380 @(test -f ../../arch/x86/include/asm/cpufeatures.h && ( \
381 (diff -B ../arch/x86/include/asm/cpufeatures.h ../../arch/x86/include/asm/cpufeatures.h >/dev/null) \
382 || echo "Warning: tools/arch/x86/include/asm/cpufeatures.h differs from kernel" >&2 )) || true
383 @(test -f ../../arch/x86/lib/memcpy_64.S && ( \
384 (diff -B ../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memcpy_64.S >/dev/null) \
385 || echo "Warning: tools/arch/x86/lib/memcpy_64.S differs from kernel" >&2 )) || true
386 @(test -f ../../arch/x86/lib/memset_64.S && ( \
387 (diff -B ../arch/x86/lib/memset_64.S ../../arch/x86/lib/memset_64.S >/dev/null) \
388 || echo "Warning: tools/arch/x86/lib/memset_64.S differs from kernel" >&2 )) || true
389 @(test -f ../../arch/arm/include/uapi/asm/perf_regs.h && ( \
390 (diff -B ../arch/arm/include/uapi/asm/perf_regs.h ../../arch/arm/include/uapi/asm/perf_regs.h >/dev/null) \
391 || echo "Warning: tools/arch/arm/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
392 @(test -f ../../arch/arm64/include/uapi/asm/perf_regs.h && ( \
393 (diff -B ../arch/arm64/include/uapi/asm/perf_regs.h ../../arch/arm64/include/uapi/asm/perf_regs.h >/dev/null) \
394 || echo "Warning: tools/arch/arm64/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
395 @(test -f ../../arch/powerpc/include/uapi/asm/perf_regs.h && ( \
396 (diff -B ../arch/powerpc/include/uapi/asm/perf_regs.h ../../arch/powerpc/include/uapi/asm/perf_regs.h >/dev/null) \
397 || echo "Warning: tools/arch/powerpc/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
398 @(test -f ../../arch/x86/include/uapi/asm/perf_regs.h && ( \
399 (diff -B ../arch/x86/include/uapi/asm/perf_regs.h ../../arch/x86/include/uapi/asm/perf_regs.h >/dev/null) \
400 || echo "Warning: tools/arch/x86/include/uapi/asm/perf_regs.h differs from kernel" >&2 )) || true
401 @(test -f ../../arch/x86/include/uapi/asm/kvm.h && ( \
402 (diff -B ../arch/x86/include/uapi/asm/kvm.h ../../arch/x86/include/uapi/asm/kvm.h >/dev/null) \
403 || echo "Warning: tools/arch/x86/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
404 @(test -f ../../arch/x86/include/uapi/asm/kvm_perf.h && ( \
405 (diff -B ../arch/x86/include/uapi/asm/kvm_perf.h ../../arch/x86/include/uapi/asm/kvm_perf.h >/dev/null) \
406 || echo "Warning: tools/arch/x86/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true
407 @(test -f ../../arch/x86/include/uapi/asm/svm.h && ( \
408 (diff -B ../arch/x86/include/uapi/asm/svm.h ../../arch/x86/include/uapi/asm/svm.h >/dev/null) \
409 || echo "Warning: tools/arch/x86/include/uapi/asm/svm.h differs from kernel" >&2 )) || true
410 @(test -f ../../arch/x86/include/uapi/asm/vmx.h && ( \
411 (diff -B ../arch/x86/include/uapi/asm/vmx.h ../../arch/x86/include/uapi/asm/vmx.h >/dev/null) \
412 || echo "Warning: tools/arch/x86/include/uapi/asm/vmx.h differs from kernel" >&2 )) || true
413 @(test -f ../../arch/powerpc/include/uapi/asm/kvm.h && ( \
414 (diff -B ../arch/powerpc/include/uapi/asm/kvm.h ../../arch/powerpc/include/uapi/asm/kvm.h >/dev/null) \
415 || echo "Warning: tools/arch/powerpc/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
416 @(test -f ../../arch/s390/include/uapi/asm/kvm.h && ( \
417 (diff -B ../arch/s390/include/uapi/asm/kvm.h ../../arch/s390/include/uapi/asm/kvm.h >/dev/null) \
418 || echo "Warning: tools/arch/s390/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
419 @(test -f ../../arch/s390/include/uapi/asm/kvm_perf.h && ( \
420 (diff -B ../arch/s390/include/uapi/asm/kvm_perf.h ../../arch/s390/include/uapi/asm/kvm_perf.h >/dev/null) \
421 || echo "Warning: tools/arch/s390/include/uapi/asm/kvm_perf.h differs from kernel" >&2 )) || true
422 @(test -f ../../arch/s390/include/uapi/asm/sie.h && ( \
423 (diff -B ../arch/s390/include/uapi/asm/sie.h ../../arch/s390/include/uapi/asm/sie.h >/dev/null) \
424 || echo "Warning: tools/arch/s390/include/uapi/asm/sie.h differs from kernel" >&2 )) || true
425 @(test -f ../../arch/arm/include/uapi/asm/kvm.h && ( \
426 (diff -B ../arch/arm/include/uapi/asm/kvm.h ../../arch/arm/include/uapi/asm/kvm.h >/dev/null) \
427 || echo "Warning: tools/arch/arm/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
428 @(test -f ../../arch/arm64/include/uapi/asm/kvm.h && ( \
429 (diff -B ../arch/arm64/include/uapi/asm/kvm.h ../../arch/arm64/include/uapi/asm/kvm.h >/dev/null) \
430 || echo "Warning: tools/arch/arm64/include/uapi/asm/kvm.h differs from kernel" >&2 )) || true
431 @(test -f ../../include/asm-generic/bitops/arch_hweight.h && ( \
432 (diff -B ../include/asm-generic/bitops/arch_hweight.h ../../include/asm-generic/bitops/arch_hweight.h >/dev/null) \
433 || echo "Warning: tools/include/asm-generic/bitops/arch_hweight.h differs from kernel" >&2 )) || true
434 @(test -f ../../include/asm-generic/bitops/const_hweight.h && ( \
435 (diff -B ../include/asm-generic/bitops/const_hweight.h ../../include/asm-generic/bitops/const_hweight.h >/dev/null) \
436 || echo "Warning: tools/include/asm-generic/bitops/const_hweight.h differs from kernel" >&2 )) || true
437 @(test -f ../../include/asm-generic/bitops/__fls.h && ( \
438 (diff -B ../include/asm-generic/bitops/__fls.h ../../include/asm-generic/bitops/__fls.h >/dev/null) \
439 || echo "Warning: tools/include/asm-generic/bitops/__fls.h differs from kernel" >&2 )) || true
440 @(test -f ../../include/asm-generic/bitops/fls.h && ( \
441 (diff -B ../include/asm-generic/bitops/fls.h ../../include/asm-generic/bitops/fls.h >/dev/null) \
442 || echo "Warning: tools/include/asm-generic/bitops/fls.h differs from kernel" >&2 )) || true
443 @(test -f ../../include/asm-generic/bitops/fls64.h && ( \
444 (diff -B ../include/asm-generic/bitops/fls64.h ../../include/asm-generic/bitops/fls64.h >/dev/null) \
445 || echo "Warning: tools/include/asm-generic/bitops/fls64.h differs from kernel" >&2 )) || true
446 @(test -f ../../include/linux/coresight-pmu.h && ( \
447 (diff -B ../include/linux/coresight-pmu.h ../../include/linux/coresight-pmu.h >/dev/null) \
448 || echo "Warning: tools/include/linux/coresight-pmu.h differs from kernel" >&2 )) || true
449 @(test -f ../../include/uapi/asm-generic/mman-common.h && ( \
450 (diff -B ../include/uapi/asm-generic/mman-common.h ../../include/uapi/asm-generic/mman-common.h >/dev/null) \
451 || echo "Warning: tools/include/uapi/asm-generic/mman-common.h differs from kernel" >&2 )) || true
452 @(test -f ../../include/uapi/asm-generic/mman.h && ( \
453 (diff -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>$$" ../include/uapi/asm-generic/mman.h ../../include/uapi/asm-generic/mman.h >/dev/null) \
454 || echo "Warning: tools/include/uapi/asm-generic/mman.h differs from kernel" >&2 )) || true
455 @(test -f ../../include/uapi/linux/mman.h && ( \
456 (diff -B -I "^#include <\(uapi/\)*asm/mman.h>$$" ../include/uapi/linux/mman.h ../../include/uapi/linux/mman.h >/dev/null) \
457 || echo "Warning: tools/include/uapi/linux/mman.h differs from kernel" >&2 )) || true
347 $(Q)$(MAKE) $(build)=perf 458 $(Q)$(MAKE) $(build)=perf
348 459
349$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(LIBTRACEEVENT_DYNAMIC_LIST) 460$(JEVENTS_IN): FORCE
461 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=jevents
462
463$(JEVENTS): $(JEVENTS_IN)
464 $(QUIET_LINK)$(HOSTCC) $(JEVENTS_IN) -o $@
465
466$(PMU_EVENTS_IN): $(JEVENTS) FORCE
467 $(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=pmu-events obj=pmu-events
468
469$(OUTPUT)perf: $(PERFLIBS) $(PERF_IN) $(PMU_EVENTS_IN) $(LIBTRACEEVENT_DYNAMIC_LIST)
350 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \ 470 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS) \
351 $(PERF_IN) $(LIBS) -o $@ 471 $(PERF_IN) $(PMU_EVENTS_IN) $(LIBS) -o $@
352 472
353$(GTK_IN): fixdep FORCE 473$(GTK_IN): fixdep FORCE
354 $(Q)$(MAKE) $(build)=gtk 474 $(Q)$(MAKE) $(build)=gtk
@@ -377,6 +497,8 @@ perf.spec $(SCRIPTS) \
377ifneq ($(OUTPUT),) 497ifneq ($(OUTPUT),)
378%.o: $(OUTPUT)%.o 498%.o: $(OUTPUT)%.o
379 @echo " # Redirected target $@ => $(OUTPUT)$@" 499 @echo " # Redirected target $@ => $(OUTPUT)$@"
500pmu-events/%.o: $(OUTPUT)pmu-events/%.o
501 @echo " # Redirected target $@ => $(OUTPUT)$@"
380util/%.o: $(OUTPUT)util/%.o 502util/%.o: $(OUTPUT)util/%.o
381 @echo " # Redirected target $@ => $(OUTPUT)$@" 503 @echo " # Redirected target $@ => $(OUTPUT)$@"
382bench/%.o: $(OUTPUT)bench/%.o 504bench/%.o: $(OUTPUT)bench/%.o
@@ -621,7 +743,7 @@ $(INSTALL_DOC_TARGETS):
621### Cleaning rules 743### Cleaning rules
622 744
623# 745#
624# This is here, not in config/Makefile, because config/Makefile does 746# This is here, not in Makefile.config, because Makefile.config does
625# not get included for the clean target: 747# not get included for the clean target:
626# 748#
627config-clean: 749config-clean:
@@ -632,10 +754,11 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
632 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS) 754 $(call QUIET_CLEAN, core-objs) $(RM) $(LIB_FILE) $(OUTPUT)perf-archive $(OUTPUT)perf-with-kcore $(LANG_BINDINGS)
633 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete 755 $(Q)find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.cmd' -delete -o -name '\.*.d' -delete
634 $(Q)$(RM) $(OUTPUT).config-detected 756 $(Q)$(RM) $(OUTPUT).config-detected
635 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 757 $(call QUIET_CLEAN, core-progs) $(RM) $(ALL_PROGRAMS) perf perf-read-vdso32 perf-read-vdsox32 $(OUTPUT)pmu-events/jevents
636 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \ 758 $(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
637 $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \ 759 $(OUTPUT)util/intel-pt-decoder/inat-tables.c $(OUTPUT)fixdep \
638 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c 760 $(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
761 $(OUTPUT)pmu-events/pmu-events.c
639 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean 762 $(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
640 $(python-clean) 763 $(python-clean)
641 764
diff --git a/tools/perf/arch/arm/include/dwarf-regs-table.h b/tools/perf/arch/arm/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..f298d034c37b
--- /dev/null
+++ b/tools/perf/arch/arm/include/dwarf-regs-table.h
@@ -0,0 +1,9 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const arm_regstr_tbl[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4",
6 "%r5", "%r6", "%r7", "%r8", "%r9", "%r10",
7 "%fp", "%ip", "%sp", "%lr", "%pc",
8};
9#endif
diff --git a/tools/perf/arch/arm/util/Build b/tools/perf/arch/arm/util/Build
index d22e3d07de3d..e64c5f216448 100644
--- a/tools/perf/arch/arm/util/Build
+++ b/tools/perf/arch/arm/util/Build
@@ -1,4 +1,6 @@
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
5
6libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs-etm.o
diff --git a/tools/perf/arch/arm/util/auxtrace.c b/tools/perf/arch/arm/util/auxtrace.c
new file mode 100644
index 000000000000..8edf2cb71564
--- /dev/null
+++ b/tools/perf/arch/arm/util/auxtrace.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <stdbool.h>
19#include <linux/coresight-pmu.h>
20
21#include "../../util/auxtrace.h"
22#include "../../util/evlist.h"
23#include "../../util/pmu.h"
24#include "cs-etm.h"
25
26struct auxtrace_record
27*auxtrace_record__init(struct perf_evlist *evlist, int *err)
28{
29 struct perf_pmu *cs_etm_pmu;
30 struct perf_evsel *evsel;
31 bool found_etm = false;
32
33 cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
34
35 if (evlist) {
36 evlist__for_each_entry(evlist, evsel) {
37 if (cs_etm_pmu &&
38 evsel->attr.type == cs_etm_pmu->type)
39 found_etm = true;
40 }
41 }
42
43 if (found_etm)
44 return cs_etm_record_init(err);
45
46 /*
47 * Clear 'err' even if we haven't found a cs_etm event - that way perf
48 * record can still be used even if tracers aren't present. The NULL
49 * return value will take care of telling the infrastructure HW tracing
50 * isn't available.
51 */
52 *err = 0;
53 return NULL;
54}
diff --git a/tools/perf/arch/arm/util/cs-etm.c b/tools/perf/arch/arm/util/cs-etm.c
new file mode 100644
index 000000000000..47d584da5819
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.c
@@ -0,0 +1,617 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <api/fs/fs.h>
19#include <linux/bitops.h>
20#include <linux/coresight-pmu.h>
21#include <linux/kernel.h>
22#include <linux/log2.h>
23#include <linux/types.h>
24
25#include "cs-etm.h"
26#include "../../perf.h"
27#include "../../util/auxtrace.h"
28#include "../../util/cpumap.h"
29#include "../../util/evlist.h"
30#include "../../util/evsel.h"
31#include "../../util/pmu.h"
32#include "../../util/thread_map.h"
33#include "../../util/cs-etm.h"
34
35#include <stdlib.h>
36
37#define ENABLE_SINK_MAX 128
38#define CS_BUS_DEVICE_PATH "/bus/coresight/devices/"
39
40struct cs_etm_recording {
41 struct auxtrace_record itr;
42 struct perf_pmu *cs_etm_pmu;
43 struct perf_evlist *evlist;
44 bool snapshot_mode;
45 size_t snapshot_size;
46};
47
48static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
49
50static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
51 struct record_opts *opts,
52 const char *str)
53{
54 struct cs_etm_recording *ptr =
55 container_of(itr, struct cs_etm_recording, itr);
56 unsigned long long snapshot_size = 0;
57 char *endptr;
58
59 if (str) {
60 snapshot_size = strtoull(str, &endptr, 0);
61 if (*endptr || snapshot_size > SIZE_MAX)
62 return -1;
63 }
64
65 opts->auxtrace_snapshot_mode = true;
66 opts->auxtrace_snapshot_size = snapshot_size;
67 ptr->snapshot_size = snapshot_size;
68
69 return 0;
70}
71
72static int cs_etm_recording_options(struct auxtrace_record *itr,
73 struct perf_evlist *evlist,
74 struct record_opts *opts)
75{
76 struct cs_etm_recording *ptr =
77 container_of(itr, struct cs_etm_recording, itr);
78 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
79 struct perf_evsel *evsel, *cs_etm_evsel = NULL;
80 const struct cpu_map *cpus = evlist->cpus;
81 bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0);
82
83 ptr->evlist = evlist;
84 ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
85
86 evlist__for_each_entry(evlist, evsel) {
87 if (evsel->attr.type == cs_etm_pmu->type) {
88 if (cs_etm_evsel) {
89 pr_err("There may be only one %s event\n",
90 CORESIGHT_ETM_PMU_NAME);
91 return -EINVAL;
92 }
93 evsel->attr.freq = 0;
94 evsel->attr.sample_period = 1;
95 cs_etm_evsel = evsel;
96 opts->full_auxtrace = true;
97 }
98 }
99
100 /* no need to continue if at least one event of interest was found */
101 if (!cs_etm_evsel)
102 return 0;
103
104 if (opts->use_clockid) {
105 pr_err("Cannot use clockid (-k option) with %s\n",
106 CORESIGHT_ETM_PMU_NAME);
107 return -EINVAL;
108 }
109
110 /* we are in snapshot mode */
111 if (opts->auxtrace_snapshot_mode) {
112 /*
113 * No size were given to '-S' or '-m,', so go with
114 * the default
115 */
116 if (!opts->auxtrace_snapshot_size &&
117 !opts->auxtrace_mmap_pages) {
118 if (privileged) {
119 opts->auxtrace_mmap_pages = MiB(4) / page_size;
120 } else {
121 opts->auxtrace_mmap_pages =
122 KiB(128) / page_size;
123 if (opts->mmap_pages == UINT_MAX)
124 opts->mmap_pages = KiB(256) / page_size;
125 }
126 } else if (!opts->auxtrace_mmap_pages && !privileged &&
127 opts->mmap_pages == UINT_MAX) {
128 opts->mmap_pages = KiB(256) / page_size;
129 }
130
131 /*
132 * '-m,xyz' was specified but no snapshot size, so make the
133 * snapshot size as big as the auxtrace mmap area.
134 */
135 if (!opts->auxtrace_snapshot_size) {
136 opts->auxtrace_snapshot_size =
137 opts->auxtrace_mmap_pages * (size_t)page_size;
138 }
139
140 /*
141 * -Sxyz was specified but no auxtrace mmap area, so make the
142 * auxtrace mmap area big enough to fit the requested snapshot
143 * size.
144 */
145 if (!opts->auxtrace_mmap_pages) {
146 size_t sz = opts->auxtrace_snapshot_size;
147
148 sz = round_up(sz, page_size) / page_size;
149 opts->auxtrace_mmap_pages = roundup_pow_of_two(sz);
150 }
151
152 /* Snapshost size can't be bigger than the auxtrace area */
153 if (opts->auxtrace_snapshot_size >
154 opts->auxtrace_mmap_pages * (size_t)page_size) {
155 pr_err("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n",
156 opts->auxtrace_snapshot_size,
157 opts->auxtrace_mmap_pages * (size_t)page_size);
158 return -EINVAL;
159 }
160
161 /* Something went wrong somewhere - this shouldn't happen */
162 if (!opts->auxtrace_snapshot_size ||
163 !opts->auxtrace_mmap_pages) {
164 pr_err("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n");
165 return -EINVAL;
166 }
167 }
168
169 /* We are in full trace mode but '-m,xyz' wasn't specified */
170 if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) {
171 if (privileged) {
172 opts->auxtrace_mmap_pages = MiB(4) / page_size;
173 } else {
174 opts->auxtrace_mmap_pages = KiB(128) / page_size;
175 if (opts->mmap_pages == UINT_MAX)
176 opts->mmap_pages = KiB(256) / page_size;
177 }
178
179 }
180
181 /* Validate auxtrace_mmap_pages provided by user */
182 if (opts->auxtrace_mmap_pages) {
183 unsigned int max_page = (KiB(128) / page_size);
184 size_t sz = opts->auxtrace_mmap_pages * (size_t)page_size;
185
186 if (!privileged &&
187 opts->auxtrace_mmap_pages > max_page) {
188 opts->auxtrace_mmap_pages = max_page;
189 pr_err("auxtrace too big, truncating to %d\n",
190 max_page);
191 }
192
193 if (!is_power_of_2(sz)) {
194 pr_err("Invalid mmap size for %s: must be a power of 2\n",
195 CORESIGHT_ETM_PMU_NAME);
196 return -EINVAL;
197 }
198 }
199
200 if (opts->auxtrace_snapshot_mode)
201 pr_debug2("%s snapshot size: %zu\n", CORESIGHT_ETM_PMU_NAME,
202 opts->auxtrace_snapshot_size);
203
204 if (cs_etm_evsel) {
205 /*
206 * To obtain the auxtrace buffer file descriptor, the auxtrace
207 * event must come first.
208 */
209 perf_evlist__to_front(evlist, cs_etm_evsel);
210 /*
211 * In the case of per-cpu mmaps, we need the CPU on the
212 * AUX event.
213 */
214 if (!cpu_map__empty(cpus))
215 perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
216 }
217
218 /* Add dummy event to keep tracking */
219 if (opts->full_auxtrace) {
220 struct perf_evsel *tracking_evsel;
221 int err;
222
223 err = parse_events(evlist, "dummy:u", NULL);
224 if (err)
225 return err;
226
227 tracking_evsel = perf_evlist__last(evlist);
228 perf_evlist__set_tracking_event(evlist, tracking_evsel);
229
230 tracking_evsel->attr.freq = 0;
231 tracking_evsel->attr.sample_period = 1;
232
233 /* In per-cpu case, always need the time of mmap events etc */
234 if (!cpu_map__empty(cpus))
235 perf_evsel__set_sample_bit(tracking_evsel, TIME);
236 }
237
238 return 0;
239}
240
241static u64 cs_etm_get_config(struct auxtrace_record *itr)
242{
243 u64 config = 0;
244 struct cs_etm_recording *ptr =
245 container_of(itr, struct cs_etm_recording, itr);
246 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
247 struct perf_evlist *evlist = ptr->evlist;
248 struct perf_evsel *evsel;
249
250 evlist__for_each_entry(evlist, evsel) {
251 if (evsel->attr.type == cs_etm_pmu->type) {
252 /*
253 * Variable perf_event_attr::config is assigned to
254 * ETMv3/PTM. The bit fields have been made to match
255 * the ETMv3.5 ETRMCR register specification. See the
256 * PMU_FORMAT_ATTR() declarations in
257 * drivers/hwtracing/coresight/coresight-perf.c for
258 * details.
259 */
260 config = evsel->attr.config;
261 break;
262 }
263 }
264
265 return config;
266}
267
268static size_t
269cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
270 struct perf_evlist *evlist __maybe_unused)
271{
272 int i;
273 int etmv3 = 0, etmv4 = 0;
274 const struct cpu_map *cpus = evlist->cpus;
275
276 /* cpu map is not empty, we have specific CPUs to work with */
277 if (!cpu_map__empty(cpus)) {
278 for (i = 0; i < cpu_map__nr(cpus); i++) {
279 if (cs_etm_is_etmv4(itr, cpus->map[i]))
280 etmv4++;
281 else
282 etmv3++;
283 }
284 } else {
285 /* get configuration for all CPUs in the system */
286 for (i = 0; i < cpu__max_cpu(); i++) {
287 if (cs_etm_is_etmv4(itr, i))
288 etmv4++;
289 else
290 etmv3++;
291 }
292 }
293
294 return (CS_ETM_HEADER_SIZE +
295 (etmv4 * CS_ETMV4_PRIV_SIZE) +
296 (etmv3 * CS_ETMV3_PRIV_SIZE));
297}
298
299static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
300 [CS_ETM_ETMCCER] = "mgmt/etmccer",
301 [CS_ETM_ETMIDR] = "mgmt/etmidr",
302};
303
304static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
305 [CS_ETMV4_TRCIDR0] = "trcidr/trcidr0",
306 [CS_ETMV4_TRCIDR1] = "trcidr/trcidr1",
307 [CS_ETMV4_TRCIDR2] = "trcidr/trcidr2",
308 [CS_ETMV4_TRCIDR8] = "trcidr/trcidr8",
309 [CS_ETMV4_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
310};
311
312static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
313{
314 bool ret = false;
315 char path[PATH_MAX];
316 int scan;
317 unsigned int val;
318 struct cs_etm_recording *ptr =
319 container_of(itr, struct cs_etm_recording, itr);
320 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
321
322 /* Take any of the RO files for ETMv4 and see if it present */
323 snprintf(path, PATH_MAX, "cpu%d/%s",
324 cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
325 scan = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
326
327 /* The file was read successfully, we have a winner */
328 if (scan == 1)
329 ret = true;
330
331 return ret;
332}
333
334static int cs_etm_get_ro(struct perf_pmu *pmu, int cpu, const char *path)
335{
336 char pmu_path[PATH_MAX];
337 int scan;
338 unsigned int val = 0;
339
340 /* Get RO metadata from sysfs */
341 snprintf(pmu_path, PATH_MAX, "cpu%d/%s", cpu, path);
342
343 scan = perf_pmu__scan_file(pmu, pmu_path, "%x", &val);
344 if (scan != 1)
345 pr_err("%s: error reading: %s\n", __func__, pmu_path);
346
347 return val;
348}
349
350static void cs_etm_get_metadata(int cpu, u32 *offset,
351 struct auxtrace_record *itr,
352 struct auxtrace_info_event *info)
353{
354 u32 increment;
355 u64 magic;
356 struct cs_etm_recording *ptr =
357 container_of(itr, struct cs_etm_recording, itr);
358 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
359
360 /* first see what kind of tracer this cpu is affined to */
361 if (cs_etm_is_etmv4(itr, cpu)) {
362 magic = __perf_cs_etmv4_magic;
363 /* Get trace configuration register */
364 info->priv[*offset + CS_ETMV4_TRCCONFIGR] =
365 cs_etm_get_config(itr);
366 /* Get traceID from the framework */
367 info->priv[*offset + CS_ETMV4_TRCTRACEIDR] =
368 coresight_get_trace_id(cpu);
369 /* Get read-only information from sysFS */
370 info->priv[*offset + CS_ETMV4_TRCIDR0] =
371 cs_etm_get_ro(cs_etm_pmu, cpu,
372 metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
373 info->priv[*offset + CS_ETMV4_TRCIDR1] =
374 cs_etm_get_ro(cs_etm_pmu, cpu,
375 metadata_etmv4_ro[CS_ETMV4_TRCIDR1]);
376 info->priv[*offset + CS_ETMV4_TRCIDR2] =
377 cs_etm_get_ro(cs_etm_pmu, cpu,
378 metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
379 info->priv[*offset + CS_ETMV4_TRCIDR8] =
380 cs_etm_get_ro(cs_etm_pmu, cpu,
381 metadata_etmv4_ro[CS_ETMV4_TRCIDR8]);
382 info->priv[*offset + CS_ETMV4_TRCAUTHSTATUS] =
383 cs_etm_get_ro(cs_etm_pmu, cpu,
384 metadata_etmv4_ro
385 [CS_ETMV4_TRCAUTHSTATUS]);
386
387 /* How much space was used */
388 increment = CS_ETMV4_PRIV_MAX;
389 } else {
390 magic = __perf_cs_etmv3_magic;
391 /* Get configuration register */
392 info->priv[*offset + CS_ETM_ETMCR] = cs_etm_get_config(itr);
393 /* Get traceID from the framework */
394 info->priv[*offset + CS_ETM_ETMTRACEIDR] =
395 coresight_get_trace_id(cpu);
396 /* Get read-only information from sysFS */
397 info->priv[*offset + CS_ETM_ETMCCER] =
398 cs_etm_get_ro(cs_etm_pmu, cpu,
399 metadata_etmv3_ro[CS_ETM_ETMCCER]);
400 info->priv[*offset + CS_ETM_ETMIDR] =
401 cs_etm_get_ro(cs_etm_pmu, cpu,
402 metadata_etmv3_ro[CS_ETM_ETMIDR]);
403
404 /* How much space was used */
405 increment = CS_ETM_PRIV_MAX;
406 }
407
408 /* Build generic header portion */
409 info->priv[*offset + CS_ETM_MAGIC] = magic;
410 info->priv[*offset + CS_ETM_CPU] = cpu;
411 /* Where the next CPU entry should start from */
412 *offset += increment;
413}
414
415static int cs_etm_info_fill(struct auxtrace_record *itr,
416 struct perf_session *session,
417 struct auxtrace_info_event *info,
418 size_t priv_size)
419{
420 int i;
421 u32 offset;
422 u64 nr_cpu, type;
423 const struct cpu_map *cpus = session->evlist->cpus;
424 struct cs_etm_recording *ptr =
425 container_of(itr, struct cs_etm_recording, itr);
426 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
427
428 if (priv_size != cs_etm_info_priv_size(itr, session->evlist))
429 return -EINVAL;
430
431 if (!session->evlist->nr_mmaps)
432 return -EINVAL;
433
434 /* If the cpu_map is empty all CPUs are involved */
435 nr_cpu = cpu_map__empty(cpus) ? cpu__max_cpu() : cpu_map__nr(cpus);
436 /* Get PMU type as dynamically assigned by the core */
437 type = cs_etm_pmu->type;
438
439 /* First fill out the session header */
440 info->type = PERF_AUXTRACE_CS_ETM;
441 info->priv[CS_HEADER_VERSION_0] = 0;
442 info->priv[CS_PMU_TYPE_CPUS] = type << 32;
443 info->priv[CS_PMU_TYPE_CPUS] |= nr_cpu;
444 info->priv[CS_ETM_SNAPSHOT] = ptr->snapshot_mode;
445
446 offset = CS_ETM_SNAPSHOT + 1;
447
448 /* cpu map is not empty, we have specific CPUs to work with */
449 if (!cpu_map__empty(cpus)) {
450 for (i = 0; i < cpu_map__nr(cpus) && offset < priv_size; i++)
451 cs_etm_get_metadata(cpus->map[i], &offset, itr, info);
452 } else {
453 /* get configuration for all CPUs in the system */
454 for (i = 0; i < cpu__max_cpu(); i++)
455 cs_etm_get_metadata(i, &offset, itr, info);
456 }
457
458 return 0;
459}
460
461static int cs_etm_find_snapshot(struct auxtrace_record *itr __maybe_unused,
462 int idx, struct auxtrace_mmap *mm,
463 unsigned char *data __maybe_unused,
464 u64 *head, u64 *old)
465{
466 pr_debug3("%s: mmap index %d old head %zu new head %zu size %zu\n",
467 __func__, idx, (size_t)*old, (size_t)*head, mm->len);
468
469 *old = *head;
470 *head += mm->len;
471
472 return 0;
473}
474
475static int cs_etm_snapshot_start(struct auxtrace_record *itr)
476{
477 struct cs_etm_recording *ptr =
478 container_of(itr, struct cs_etm_recording, itr);
479 struct perf_evsel *evsel;
480
481 evlist__for_each_entry(ptr->evlist, evsel) {
482 if (evsel->attr.type == ptr->cs_etm_pmu->type)
483 return perf_evsel__disable(evsel);
484 }
485 return -EINVAL;
486}
487
488static int cs_etm_snapshot_finish(struct auxtrace_record *itr)
489{
490 struct cs_etm_recording *ptr =
491 container_of(itr, struct cs_etm_recording, itr);
492 struct perf_evsel *evsel;
493
494 evlist__for_each_entry(ptr->evlist, evsel) {
495 if (evsel->attr.type == ptr->cs_etm_pmu->type)
496 return perf_evsel__enable(evsel);
497 }
498 return -EINVAL;
499}
500
501static u64 cs_etm_reference(struct auxtrace_record *itr __maybe_unused)
502{
503 return (((u64) rand() << 0) & 0x00000000FFFFFFFFull) |
504 (((u64) rand() << 32) & 0xFFFFFFFF00000000ull);
505}
506
507static void cs_etm_recording_free(struct auxtrace_record *itr)
508{
509 struct cs_etm_recording *ptr =
510 container_of(itr, struct cs_etm_recording, itr);
511 free(ptr);
512}
513
514static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
515{
516 struct cs_etm_recording *ptr =
517 container_of(itr, struct cs_etm_recording, itr);
518 struct perf_evsel *evsel;
519
520 evlist__for_each_entry(ptr->evlist, evsel) {
521 if (evsel->attr.type == ptr->cs_etm_pmu->type)
522 return perf_evlist__enable_event_idx(ptr->evlist,
523 evsel, idx);
524 }
525
526 return -EINVAL;
527}
528
529struct auxtrace_record *cs_etm_record_init(int *err)
530{
531 struct perf_pmu *cs_etm_pmu;
532 struct cs_etm_recording *ptr;
533
534 cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
535
536 if (!cs_etm_pmu) {
537 *err = -EINVAL;
538 goto out;
539 }
540
541 ptr = zalloc(sizeof(struct cs_etm_recording));
542 if (!ptr) {
543 *err = -ENOMEM;
544 goto out;
545 }
546
547 ptr->cs_etm_pmu = cs_etm_pmu;
548 ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options;
549 ptr->itr.recording_options = cs_etm_recording_options;
550 ptr->itr.info_priv_size = cs_etm_info_priv_size;
551 ptr->itr.info_fill = cs_etm_info_fill;
552 ptr->itr.find_snapshot = cs_etm_find_snapshot;
553 ptr->itr.snapshot_start = cs_etm_snapshot_start;
554 ptr->itr.snapshot_finish = cs_etm_snapshot_finish;
555 ptr->itr.reference = cs_etm_reference;
556 ptr->itr.free = cs_etm_recording_free;
557 ptr->itr.read_finish = cs_etm_read_finish;
558
559 *err = 0;
560 return &ptr->itr;
561out:
562 return NULL;
563}
564
565static FILE *cs_device__open_file(const char *name)
566{
567 struct stat st;
568 char path[PATH_MAX];
569 const char *sysfs;
570
571 sysfs = sysfs__mountpoint();
572 if (!sysfs)
573 return NULL;
574
575 snprintf(path, PATH_MAX,
576 "%s" CS_BUS_DEVICE_PATH "%s", sysfs, name);
577
578 printf("path: %s\n", path);
579
580 if (stat(path, &st) < 0)
581 return NULL;
582
583 return fopen(path, "w");
584
585}
586
587static __attribute__((format(printf, 2, 3)))
588int cs_device__print_file(const char *name, const char *fmt, ...)
589{
590 va_list args;
591 FILE *file;
592 int ret = -EINVAL;
593
594 va_start(args, fmt);
595 file = cs_device__open_file(name);
596 if (file) {
597 ret = vfprintf(file, fmt, args);
598 fclose(file);
599 }
600 va_end(args);
601 return ret;
602}
603
604int cs_etm_set_drv_config(struct perf_evsel_config_term *term)
605{
606 int ret;
607 char enable_sink[ENABLE_SINK_MAX];
608
609 snprintf(enable_sink, ENABLE_SINK_MAX, "%s/%s",
610 term->val.drv_cfg, "enable_sink");
611
612 ret = cs_device__print_file(enable_sink, "%d", 1);
613 if (ret < 0)
614 return ret;
615
616 return 0;
617}
diff --git a/tools/perf/arch/arm/util/cs-etm.h b/tools/perf/arch/arm/util/cs-etm.h
new file mode 100644
index 000000000000..5256741be549
--- /dev/null
+++ b/tools/perf/arch/arm/util/cs-etm.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDE__PERF_CS_ETM_H__
19#define INCLUDE__PERF_CS_ETM_H__
20
21#include "../../util/evsel.h"
22
23struct auxtrace_record *cs_etm_record_init(int *err);
24int cs_etm_set_drv_config(struct perf_evsel_config_term *term);
25
26#endif
diff --git a/tools/perf/arch/arm/util/pmu.c b/tools/perf/arch/arm/util/pmu.c
new file mode 100644
index 000000000000..98d67399a0d6
--- /dev/null
+++ b/tools/perf/arch/arm/util/pmu.c
@@ -0,0 +1,36 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <string.h>
19#include <linux/coresight-pmu.h>
20#include <linux/perf_event.h>
21
22#include "cs-etm.h"
23#include "../../util/pmu.h"
24
25struct perf_event_attr
26*perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
27{
28#ifdef HAVE_AUXTRACE_SUPPORT
29 if (!strcmp(pmu->name, CORESIGHT_ETM_PMU_NAME)) {
30 /* add ETM default config here */
31 pmu->selectable = true;
32 pmu->set_drv_config = cs_etm_set_drv_config;
33 }
34#endif
35 return NULL;
36}
diff --git a/tools/perf/arch/arm64/include/dwarf-regs-table.h b/tools/perf/arch/arm64/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..26759363f921
--- /dev/null
+++ b/tools/perf/arch/arm64/include/dwarf-regs-table.h
@@ -0,0 +1,13 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const aarch64_regstr_tbl[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4",
6 "%r5", "%r6", "%r7", "%r8", "%r9",
7 "%r10", "%r11", "%r12", "%r13", "%r14",
8 "%r15", "%r16", "%r17", "%r18", "%r19",
9 "%r20", "%r21", "%r22", "%r23", "%r24",
10 "%r25", "%r26", "%r27", "%r28", "%r29",
11 "%lr", "%sp",
12};
13#endif
diff --git a/tools/perf/arch/arm64/util/Build b/tools/perf/arch/arm64/util/Build
index e58123a8912b..cef6fb38d17e 100644
--- a/tools/perf/arch/arm64/util/Build
+++ b/tools/perf/arch/arm64/util/Build
@@ -1,2 +1,6 @@
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
3
4libperf-$(CONFIG_AUXTRACE) += ../../arm/util/pmu.o \
5 ../../arm/util/auxtrace.o \
6 ../../arm/util/cs-etm.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/Build b/tools/perf/arch/powerpc/Build
index 54afe4a467e7..db52fa22d3a1 100644
--- a/tools/perf/arch/powerpc/Build
+++ b/tools/perf/arch/powerpc/Build
@@ -1 +1,2 @@
1libperf-y += util/ 1libperf-y += util/
2libperf-y += tests/
diff --git a/tools/perf/arch/powerpc/include/arch-tests.h b/tools/perf/arch/powerpc/include/arch-tests.h
new file mode 100644
index 000000000000..84d8dedef2ed
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/arch-tests.h
@@ -0,0 +1,13 @@
1#ifndef ARCH_TESTS_H
2#define ARCH_TESTS_H
3
4#ifdef HAVE_DWARF_UNWIND_SUPPORT
5struct thread;
6struct perf_sample;
7int test__arch_unwind_sample(struct perf_sample *sample,
8 struct thread *thread);
9#endif
10
11extern struct test arch_tests[];
12
13#endif
diff --git a/tools/perf/arch/powerpc/include/dwarf-regs-table.h b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..db4730f5585c
--- /dev/null
+++ b/tools/perf/arch/powerpc/include/dwarf-regs-table.h
@@ -0,0 +1,27 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4/*
5 * Reference:
6 * http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html
7 * http://refspecs.linux-foundation.org/elf/elfspec_ppc.pdf
8 */
9#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
10
11static const char * const powerpc_regstr_tbl[] = {
12 "%gpr0", "%gpr1", "%gpr2", "%gpr3", "%gpr4",
13 "%gpr5", "%gpr6", "%gpr7", "%gpr8", "%gpr9",
14 "%gpr10", "%gpr11", "%gpr12", "%gpr13", "%gpr14",
15 "%gpr15", "%gpr16", "%gpr17", "%gpr18", "%gpr19",
16 "%gpr20", "%gpr21", "%gpr22", "%gpr23", "%gpr24",
17 "%gpr25", "%gpr26", "%gpr27", "%gpr28", "%gpr29",
18 "%gpr30", "%gpr31",
19 REG_DWARFNUM_NAME(msr, 66),
20 REG_DWARFNUM_NAME(ctr, 109),
21 REG_DWARFNUM_NAME(link, 108),
22 REG_DWARFNUM_NAME(xer, 101),
23 REG_DWARFNUM_NAME(dar, 119),
24 REG_DWARFNUM_NAME(dsisr, 118),
25};
26
27#endif
diff --git a/tools/perf/arch/powerpc/include/perf_regs.h b/tools/perf/arch/powerpc/include/perf_regs.h
index 75de0e92e71e..c12f4e804f66 100644
--- a/tools/perf/arch/powerpc/include/perf_regs.h
+++ b/tools/perf/arch/powerpc/include/perf_regs.h
@@ -5,6 +5,8 @@
5#include <linux/types.h> 5#include <linux/types.h>
6#include <asm/perf_regs.h> 6#include <asm/perf_regs.h>
7 7
8void perf_regs_load(u64 *regs);
9
8#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1) 10#define PERF_REGS_MASK ((1ULL << PERF_REG_POWERPC_MAX) - 1)
9#define PERF_REGS_MAX PERF_REG_POWERPC_MAX 11#define PERF_REGS_MAX PERF_REG_POWERPC_MAX
10#ifdef __powerpc64__ 12#ifdef __powerpc64__
diff --git a/tools/perf/arch/powerpc/tests/Build b/tools/perf/arch/powerpc/tests/Build
new file mode 100644
index 000000000000..d827ef384b33
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/Build
@@ -0,0 +1,4 @@
1libperf-$(CONFIG_DWARF_UNWIND) += regs_load.o
2libperf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
3
4libperf-y += arch-tests.o
diff --git a/tools/perf/arch/powerpc/tests/arch-tests.c b/tools/perf/arch/powerpc/tests/arch-tests.c
new file mode 100644
index 000000000000..e24f46241f40
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/arch-tests.c
@@ -0,0 +1,15 @@
1#include <string.h>
2#include "tests/tests.h"
3#include "arch-tests.h"
4
5struct test arch_tests[] = {
6#ifdef HAVE_DWARF_UNWIND_SUPPORT
7 {
8 .desc = "Test dwarf unwind",
9 .func = test__dwarf_unwind,
10 },
11#endif
12 {
13 .func = NULL,
14 },
15};
diff --git a/tools/perf/arch/powerpc/tests/dwarf-unwind.c b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
new file mode 100644
index 000000000000..0bac3137ccbd
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/dwarf-unwind.c
@@ -0,0 +1,62 @@
1#include <string.h>
2#include "perf_regs.h"
3#include "thread.h"
4#include "map.h"
5#include "event.h"
6#include "debug.h"
7#include "tests/tests.h"
8#include "arch-tests.h"
9
10#define STACK_SIZE 8192
11
12static int sample_ustack(struct perf_sample *sample,
13 struct thread *thread, u64 *regs)
14{
15 struct stack_dump *stack = &sample->user_stack;
16 struct map *map;
17 unsigned long sp;
18 u64 stack_size, *buf;
19
20 buf = malloc(STACK_SIZE);
21 if (!buf) {
22 pr_debug("failed to allocate sample uregs data\n");
23 return -1;
24 }
25
26 sp = (unsigned long) regs[PERF_REG_POWERPC_R1];
27
28 map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp);
29 if (!map) {
30 pr_debug("failed to get stack map\n");
31 free(buf);
32 return -1;
33 }
34
35 stack_size = map->end - sp;
36 stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
37
38 memcpy(buf, (void *) sp, stack_size);
39 stack->data = (char *) buf;
40 stack->size = stack_size;
41 return 0;
42}
43
44int test__arch_unwind_sample(struct perf_sample *sample,
45 struct thread *thread)
46{
47 struct regs_dump *regs = &sample->user_regs;
48 u64 *buf;
49
50 buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
51 if (!buf) {
52 pr_debug("failed to allocate sample uregs data\n");
53 return -1;
54 }
55
56 perf_regs_load(buf);
57 regs->abi = PERF_SAMPLE_REGS_ABI;
58 regs->regs = buf;
59 regs->mask = PERF_REGS_MASK;
60
61 return sample_ustack(sample, thread, buf);
62}
diff --git a/tools/perf/arch/powerpc/tests/regs_load.S b/tools/perf/arch/powerpc/tests/regs_load.S
new file mode 100644
index 000000000000..d76c9a32f327
--- /dev/null
+++ b/tools/perf/arch/powerpc/tests/regs_load.S
@@ -0,0 +1,94 @@
1#include <linux/linkage.h>
2
3/* Offset is based on macros from arch/powerpc/include/uapi/asm/ptrace.h. */
4#define R0 0
5#define R1 1 * 8
6#define R2 2 * 8
7#define R3 3 * 8
8#define R4 4 * 8
9#define R5 5 * 8
10#define R6 6 * 8
11#define R7 7 * 8
12#define R8 8 * 8
13#define R9 9 * 8
14#define R10 10 * 8
15#define R11 11 * 8
16#define R12 12 * 8
17#define R13 13 * 8
18#define R14 14 * 8
19#define R15 15 * 8
20#define R16 16 * 8
21#define R17 17 * 8
22#define R18 18 * 8
23#define R19 19 * 8
24#define R20 20 * 8
25#define R21 21 * 8
26#define R22 22 * 8
27#define R23 23 * 8
28#define R24 24 * 8
29#define R25 25 * 8
30#define R26 26 * 8
31#define R27 27 * 8
32#define R28 28 * 8
33#define R29 29 * 8
34#define R30 30 * 8
35#define R31 31 * 8
36#define NIP 32 * 8
37#define CTR 35 * 8
38#define LINK 36 * 8
39#define XER 37 * 8
40
41.globl perf_regs_load
42perf_regs_load:
43 std 0, R0(3)
44 std 1, R1(3)
45 std 2, R2(3)
46 std 3, R3(3)
47 std 4, R4(3)
48 std 5, R5(3)
49 std 6, R6(3)
50 std 7, R7(3)
51 std 8, R8(3)
52 std 9, R9(3)
53 std 10, R10(3)
54 std 11, R11(3)
55 std 12, R12(3)
56 std 13, R13(3)
57 std 14, R14(3)
58 std 15, R15(3)
59 std 16, R16(3)
60 std 17, R17(3)
61 std 18, R18(3)
62 std 19, R19(3)
63 std 20, R20(3)
64 std 21, R21(3)
65 std 22, R22(3)
66 std 23, R23(3)
67 std 24, R24(3)
68 std 25, R25(3)
69 std 26, R26(3)
70 std 27, R27(3)
71 std 28, R28(3)
72 std 29, R29(3)
73 std 30, R30(3)
74 std 31, R31(3)
75
76 /* store NIP */
77 mflr 4
78 std 4, NIP(3)
79
80 /* Store LR */
81 std 4, LINK(3)
82
83 /* Store XER */
84 mfxer 4
85 std 4, XER(3)
86
87 /* Store CTR */
88 mfctr 4
89 std 4, CTR(3)
90
91 /* Restore original value of r4 */
92 ld 4, R4(3)
93
94 blr
diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index f8ccee132867..9aaa6f5a9347 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -32,3 +32,14 @@ get_cpuid(char *buffer, size_t sz)
32 } 32 }
33 return -1; 33 return -1;
34} 34}
35
36char *
37get_cpuid_str(void)
38{
39 char *bufp;
40
41 if (asprintf(&bufp, "%.8lx", mfspr(SPRN_PVR)) < 0)
42 bufp = NULL;
43
44 return bufp;
45}
diff --git a/tools/perf/arch/powerpc/util/sym-handling.c b/tools/perf/arch/powerpc/util/sym-handling.c
index c6d0f91731a1..1030a6e504bb 100644
--- a/tools/perf/arch/powerpc/util/sym-handling.c
+++ b/tools/perf/arch/powerpc/util/sym-handling.c
@@ -54,10 +54,6 @@ int arch__compare_symbol_names(const char *namea, const char *nameb)
54#endif 54#endif
55 55
56#if defined(_CALL_ELF) && _CALL_ELF == 2 56#if defined(_CALL_ELF) && _CALL_ELF == 2
57bool arch__prefers_symtab(void)
58{
59 return true;
60}
61 57
62#ifdef HAVE_LIBELF_SUPPORT 58#ifdef HAVE_LIBELF_SUPPORT
63void arch__sym_update(struct symbol *s, GElf_Sym *sym) 59void arch__sym_update(struct symbol *s, GElf_Sym *sym)
@@ -86,7 +82,8 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
86 * 82 *
87 * In addition, we shouldn't specify an offset for kretprobes. 83 * In addition, we shouldn't specify an offset for kretprobes.
88 */ 84 */
89 if (pev->point.offset || pev->point.retprobe || !map || !sym) 85 if (pev->point.offset || (!pev->uprobes && pev->point.retprobe) ||
86 !map || !sym)
90 return; 87 return;
91 88
92 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym); 89 lep_offset = PPC64_LOCAL_ENTRY_OFFSET(sym->arch_sym);
@@ -100,4 +97,29 @@ void arch__fix_tev_from_maps(struct perf_probe_event *pev,
100 tev->point.offset += lep_offset; 97 tev->point.offset += lep_offset;
101 } 98 }
102} 99}
100
101#ifdef HAVE_LIBELF_SUPPORT
102void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
103 int ntevs)
104{
105 struct probe_trace_event *tev;
106 struct map *map;
107 struct symbol *sym = NULL;
108 struct rb_node *tmp;
109 int i = 0;
110
111 map = get_target_map(pev->target, pev->uprobes);
112 if (!map || map__load(map) < 0)
113 return;
114
115 for (i = 0; i < ntevs; i++) {
116 tev = &pev->tevs[i];
117 map__for_each_symbol(map, sym, tmp) {
118 if (map->unmap_ip(map, sym->start) == tev->point.address)
119 arch__fix_tev_from_maps(pev, tev, map, sym);
120 }
121 }
122}
123#endif /* HAVE_LIBELF_SUPPORT */
124
103#endif 125#endif
diff --git a/tools/perf/arch/s390/include/dwarf-regs-table.h b/tools/perf/arch/s390/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..9da74a933bd6
--- /dev/null
+++ b/tools/perf/arch/s390/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const s390_regstr_tbl[] = {
5 "%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
6 "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
7};
8#endif
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/sh/include/dwarf-regs-table.h b/tools/perf/arch/sh/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..3a2deaf3dab4
--- /dev/null
+++ b/tools/perf/arch/sh/include/dwarf-regs-table.h
@@ -0,0 +1,25 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4const char * const sh_regstr_tbl[] = {
5 "r0",
6 "r1",
7 "r2",
8 "r3",
9 "r4",
10 "r5",
11 "r6",
12 "r7",
13 "r8",
14 "r9",
15 "r10",
16 "r11",
17 "r12",
18 "r13",
19 "r14",
20 "r15",
21 "pc",
22 "pr",
23};
24
25#endif
diff --git a/tools/perf/arch/sparc/include/dwarf-regs-table.h b/tools/perf/arch/sparc/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..12c07619002c
--- /dev/null
+++ b/tools/perf/arch/sparc/include/dwarf-regs-table.h
@@ -0,0 +1,18 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const sparc_regstr_tbl[] = {
5 "%g0", "%g1", "%g2", "%g3", "%g4", "%g5", "%g6", "%g7",
6 "%o0", "%o1", "%o2", "%o3", "%o4", "%o5", "%sp", "%o7",
7 "%l0", "%l1", "%l2", "%l3", "%l4", "%l5", "%l6", "%l7",
8 "%i0", "%i1", "%i2", "%i3", "%i4", "%i5", "%fp", "%i7",
9 "%f0", "%f1", "%f2", "%f3", "%f4", "%f5", "%f6", "%f7",
10 "%f8", "%f9", "%f10", "%f11", "%f12", "%f13", "%f14", "%f15",
11 "%f16", "%f17", "%f18", "%f19", "%f20", "%f21", "%f22", "%f23",
12 "%f24", "%f25", "%f26", "%f27", "%f28", "%f29", "%f30", "%f31",
13 "%f32", "%f33", "%f34", "%f35", "%f36", "%f37", "%f38", "%f39",
14 "%f40", "%f41", "%f42", "%f43", "%f44", "%f45", "%f46", "%f47",
15 "%f48", "%f49", "%f50", "%f51", "%f52", "%f53", "%f54", "%f55",
16 "%f56", "%f57", "%f58", "%f59", "%f60", "%f61", "%f62", "%f63",
17};
18#endif
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index cac6d17ce5db..555263e385c9 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -374,3 +374,5 @@
374543 x32 io_setup compat_sys_io_setup 374543 x32 io_setup compat_sys_io_setup
375544 x32 io_submit compat_sys_io_submit 375544 x32 io_submit compat_sys_io_submit
376545 x32 execveat compat_sys_execveat/ptregs 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/include/dwarf-regs-table.h b/tools/perf/arch/x86/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..9b5e5cbb4209
--- /dev/null
+++ b/tools/perf/arch/x86/include/dwarf-regs-table.h
@@ -0,0 +1,14 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const x86_32_regstr_tbl[] = {
5 "%ax", "%cx", "%dx", "%bx", "$stack",/* Stack address instead of %sp */
6 "%bp", "%si", "%di",
7};
8
9static const char * const x86_64_regstr_tbl[] = {
10 "%ax", "%dx", "%cx", "%bx", "%si", "%di",
11 "%bp", "%sp", "%r8", "%r9", "%r10", "%r11",
12 "%r12", "%r13", "%r14", "%r15",
13};
14#endif
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 d4aa567a29c4..5c76cc83186a 100644
--- a/tools/perf/arch/x86/tests/perf-time-to-tsc.c
+++ b/tools/perf/arch/x86/tests/perf-time-to-tsc.c
@@ -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/header.c b/tools/perf/arch/x86/util/header.c
index 146d12a1cec0..a74a48db26f5 100644
--- a/tools/perf/arch/x86/util/header.c
+++ b/tools/perf/arch/x86/util/header.c
@@ -19,8 +19,8 @@ cpuid(unsigned int op, unsigned int *a, unsigned int *b, unsigned int *c,
19 : "a" (op)); 19 : "a" (op));
20} 20}
21 21
22int 22static int
23get_cpuid(char *buffer, size_t sz) 23__get_cpuid(char *buffer, size_t sz, const char *fmt)
24{ 24{
25 unsigned int a, b, c, d, lvl; 25 unsigned int a, b, c, d, lvl;
26 int family = -1, model = -1, step = -1; 26 int family = -1, model = -1, step = -1;
@@ -48,7 +48,7 @@ get_cpuid(char *buffer, size_t sz)
48 if (family >= 0x6) 48 if (family >= 0x6)
49 model += ((a >> 16) & 0xf) << 4; 49 model += ((a >> 16) & 0xf) << 4;
50 } 50 }
51 nb = scnprintf(buffer, sz, "%s,%u,%u,%u$", vendor, family, model, step); 51 nb = scnprintf(buffer, sz, fmt, vendor, family, model, step);
52 52
53 /* look for end marker to ensure the entire data fit */ 53 /* look for end marker to ensure the entire data fit */
54 if (strchr(buffer, '$')) { 54 if (strchr(buffer, '$')) {
@@ -57,3 +57,21 @@ get_cpuid(char *buffer, size_t sz)
57 } 57 }
58 return -1; 58 return -1;
59} 59}
60
61int
62get_cpuid(char *buffer, size_t sz)
63{
64 return __get_cpuid(buffer, sz, "%s,%u,%u,%u$");
65}
66
67char *
68get_cpuid_str(void)
69{
70 char *buf = malloc(128);
71
72 if (__get_cpuid(buf, 128, "%s-%u-%X$") < 0) {
73 free(buf);
74 return NULL;
75 }
76 return buf;
77}
diff --git a/tools/perf/arch/x86/util/intel-bts.c b/tools/perf/arch/x86/util/intel-bts.c
index 7dc30637cf66..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);
diff --git a/tools/perf/arch/x86/util/intel-pt.c b/tools/perf/arch/x86/util/intel-pt.c
index a07b9605e93b..90fa2286edcf 100644
--- a/tools/perf/arch/x86/util/intel-pt.c
+++ b/tools/perf/arch/x86/util/intel-pt.c
@@ -62,6 +62,7 @@ struct intel_pt_recording {
62 size_t snapshot_ref_buf_size; 62 size_t snapshot_ref_buf_size;
63 int snapshot_ref_cnt; 63 int snapshot_ref_cnt;
64 struct intel_pt_snapshot_ref *snapshot_refs; 64 struct intel_pt_snapshot_ref *snapshot_refs;
65 size_t priv_size;
65}; 66};
66 67
67static int intel_pt_parse_terms_with_default(struct list_head *formats, 68static int intel_pt_parse_terms_with_default(struct list_head *formats,
@@ -131,7 +132,7 @@ static int intel_pt_read_config(struct perf_pmu *intel_pt_pmu, const char *str,
131 if (!mask) 132 if (!mask)
132 return -EINVAL; 133 return -EINVAL;
133 134
134 evlist__for_each(evlist, evsel) { 135 evlist__for_each_entry(evlist, evsel) {
135 if (evsel->attr.type == intel_pt_pmu->type) { 136 if (evsel->attr.type == intel_pt_pmu->type) {
136 *res = intel_pt_masked_bits(mask, evsel->attr.config); 137 *res = intel_pt_masked_bits(mask, evsel->attr.config);
137 return 0; 138 return 0;
@@ -273,11 +274,37 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)
273 return attr; 274 return attr;
274} 275}
275 276
277static const char *intel_pt_find_filter(struct perf_evlist *evlist,
278 struct perf_pmu *intel_pt_pmu)
279{
280 struct perf_evsel *evsel;
281
282 evlist__for_each_entry(evlist, evsel) {
283 if (evsel->attr.type == intel_pt_pmu->type)
284 return evsel->filter;
285 }
286
287 return NULL;
288}
289
290static size_t intel_pt_filter_bytes(const char *filter)
291{
292 size_t len = filter ? strlen(filter) : 0;
293
294 return len ? roundup(len + 1, 8) : 0;
295}
296
276static size_t 297static size_t
277intel_pt_info_priv_size(struct auxtrace_record *itr __maybe_unused, 298intel_pt_info_priv_size(struct auxtrace_record *itr, struct perf_evlist *evlist)
278 struct perf_evlist *evlist __maybe_unused)
279{ 299{
280 return INTEL_PT_AUXTRACE_PRIV_SIZE; 300 struct intel_pt_recording *ptr =
301 container_of(itr, struct intel_pt_recording, itr);
302 const char *filter = intel_pt_find_filter(evlist, ptr->intel_pt_pmu);
303
304 ptr->priv_size = (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64)) +
305 intel_pt_filter_bytes(filter);
306
307 return ptr->priv_size;
281} 308}
282 309
283static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d) 310static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
@@ -302,9 +329,13 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
302 bool cap_user_time_zero = false, per_cpu_mmaps; 329 bool cap_user_time_zero = false, per_cpu_mmaps;
303 u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit; 330 u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
304 u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d; 331 u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
332 unsigned long max_non_turbo_ratio;
333 size_t filter_str_len;
334 const char *filter;
335 u64 *info;
305 int err; 336 int err;
306 337
307 if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE) 338 if (priv_size != ptr->priv_size)
308 return -EINVAL; 339 return -EINVAL;
309 340
310 intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit); 341 intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
@@ -317,6 +348,13 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
317 348
318 intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d); 349 intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
319 350
351 if (perf_pmu__scan_file(intel_pt_pmu, "max_nonturbo_ratio",
352 "%lu", &max_non_turbo_ratio) != 1)
353 max_non_turbo_ratio = 0;
354
355 filter = intel_pt_find_filter(session->evlist, ptr->intel_pt_pmu);
356 filter_str_len = filter ? strlen(filter) : 0;
357
320 if (!session->evlist->nr_mmaps) 358 if (!session->evlist->nr_mmaps)
321 return -EINVAL; 359 return -EINVAL;
322 360
@@ -351,6 +389,17 @@ static int intel_pt_info_fill(struct auxtrace_record *itr,
351 auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n; 389 auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
352 auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d; 390 auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
353 auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit; 391 auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
392 auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO] = max_non_turbo_ratio;
393 auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] = filter_str_len;
394
395 info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
396
397 if (filter_str_len) {
398 size_t len = intel_pt_filter_bytes(filter);
399
400 strncpy((char *)info, filter, len);
401 info += len >> 3;
402 }
354 403
355 return 0; 404 return 0;
356} 405}
@@ -501,7 +550,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
501 struct intel_pt_recording *ptr = 550 struct intel_pt_recording *ptr =
502 container_of(itr, struct intel_pt_recording, itr); 551 container_of(itr, struct intel_pt_recording, itr);
503 struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu; 552 struct perf_pmu *intel_pt_pmu = ptr->intel_pt_pmu;
504 bool have_timing_info; 553 bool have_timing_info, need_immediate = false;
505 struct perf_evsel *evsel, *intel_pt_evsel = NULL; 554 struct perf_evsel *evsel, *intel_pt_evsel = NULL;
506 const struct cpu_map *cpus = evlist->cpus; 555 const struct cpu_map *cpus = evlist->cpus;
507 bool privileged = geteuid() == 0 || perf_event_paranoid() < 0; 556 bool privileged = geteuid() == 0 || perf_event_paranoid() < 0;
@@ -511,7 +560,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
511 ptr->evlist = evlist; 560 ptr->evlist = evlist;
512 ptr->snapshot_mode = opts->auxtrace_snapshot_mode; 561 ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
513 562
514 evlist__for_each(evlist, evsel) { 563 evlist__for_each_entry(evlist, evsel) {
515 if (evsel->attr.type == intel_pt_pmu->type) { 564 if (evsel->attr.type == intel_pt_pmu->type) {
516 if (intel_pt_evsel) { 565 if (intel_pt_evsel) {
517 pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n"); 566 pr_err("There may be only one " INTEL_PT_PMU_NAME " event\n");
@@ -655,6 +704,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
655 ptr->have_sched_switch = 3; 704 ptr->have_sched_switch = 3;
656 } else { 705 } else {
657 opts->record_switch_events = true; 706 opts->record_switch_events = true;
707 need_immediate = true;
658 if (cpu_wide) 708 if (cpu_wide)
659 ptr->have_sched_switch = 3; 709 ptr->have_sched_switch = 3;
660 else 710 else
@@ -700,6 +750,9 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
700 tracking_evsel->attr.freq = 0; 750 tracking_evsel->attr.freq = 0;
701 tracking_evsel->attr.sample_period = 1; 751 tracking_evsel->attr.sample_period = 1;
702 752
753 if (need_immediate)
754 tracking_evsel->immediate = true;
755
703 /* In per-cpu case, always need the time of mmap events etc */ 756 /* In per-cpu case, always need the time of mmap events etc */
704 if (!cpu_map__empty(cpus)) { 757 if (!cpu_map__empty(cpus)) {
705 perf_evsel__set_sample_bit(tracking_evsel, TIME); 758 perf_evsel__set_sample_bit(tracking_evsel, TIME);
@@ -725,7 +778,7 @@ static int intel_pt_snapshot_start(struct auxtrace_record *itr)
725 container_of(itr, struct intel_pt_recording, itr); 778 container_of(itr, struct intel_pt_recording, itr);
726 struct perf_evsel *evsel; 779 struct perf_evsel *evsel;
727 780
728 evlist__for_each(ptr->evlist, evsel) { 781 evlist__for_each_entry(ptr->evlist, evsel) {
729 if (evsel->attr.type == ptr->intel_pt_pmu->type) 782 if (evsel->attr.type == ptr->intel_pt_pmu->type)
730 return perf_evsel__disable(evsel); 783 return perf_evsel__disable(evsel);
731 } 784 }
@@ -738,7 +791,7 @@ static int intel_pt_snapshot_finish(struct auxtrace_record *itr)
738 container_of(itr, struct intel_pt_recording, itr); 791 container_of(itr, struct intel_pt_recording, itr);
739 struct perf_evsel *evsel; 792 struct perf_evsel *evsel;
740 793
741 evlist__for_each(ptr->evlist, evsel) { 794 evlist__for_each_entry(ptr->evlist, evsel) {
742 if (evsel->attr.type == ptr->intel_pt_pmu->type) 795 if (evsel->attr.type == ptr->intel_pt_pmu->type)
743 return perf_evsel__enable(evsel); 796 return perf_evsel__enable(evsel);
744 } 797 }
@@ -1011,7 +1064,7 @@ static int intel_pt_read_finish(struct auxtrace_record *itr, int idx)
1011 container_of(itr, struct intel_pt_recording, itr); 1064 container_of(itr, struct intel_pt_recording, itr);
1012 struct perf_evsel *evsel; 1065 struct perf_evsel *evsel;
1013 1066
1014 evlist__for_each(ptr->evlist, evsel) { 1067 evlist__for_each_entry(ptr->evlist, evsel) {
1015 if (evsel->attr.type == ptr->intel_pt_pmu->type) 1068 if (evsel->attr.type == ptr->intel_pt_pmu->type)
1016 return perf_evlist__enable_event_idx(ptr->evlist, evsel, 1069 return perf_evlist__enable_event_idx(ptr->evlist, evsel,
1017 idx); 1070 idx);
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index 357f1b13b5ae..2e5567c94e09 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -62,6 +62,8 @@ int perf_event__synth_time_conv(const struct perf_event_mmap_page *pc,
62 struct perf_tsc_conversion tc; 62 struct perf_tsc_conversion tc;
63 int err; 63 int err;
64 64
65 if (!pc)
66 return 0;
65 err = perf_read_tsc_conversion(pc, &tc); 67 err = perf_read_tsc_conversion(pc, &tc);
66 if (err == -EOPNOTSUPP) 68 if (err == -EOPNOTSUPP)
67 return 0; 69 return 0;
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/arch/xtensa/include/dwarf-regs-table.h b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
new file mode 100644
index 000000000000..aa0444a33fe6
--- /dev/null
+++ b/tools/perf/arch/xtensa/include/dwarf-regs-table.h
@@ -0,0 +1,8 @@
1#ifdef DEFINE_DWARF_REGSTR_TABLE
2/* This is included in perf/util/dwarf-regs.c */
3
4static const char * const xtensa_regstr_tbl[] = {
5 "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7",
6 "a8", "a9", "a10", "a11", "a12", "a13", "a14", "a15",
7};
8#endif
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 6952db65508a..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;
diff --git a/tools/perf/bench/futex-requeue.c b/tools/perf/bench/futex-requeue.c
index 718238683013..2b9705a8734c 100644
--- a/tools/perf/bench/futex-requeue.c
+++ b/tools/perf/bench/futex-requeue.c
@@ -8,18 +8,22 @@
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 <linux/time64.h>
20#include <errno.h>
16#include "bench.h" 21#include "bench.h"
17#include "futex.h" 22#include "futex.h"
18 23
19#include <err.h> 24#include <err.h>
20#include <stdlib.h> 25#include <stdlib.h>
21#include <sys/time.h> 26#include <sys/time.h>
22#include <pthread.h>
23 27
24static u_int32_t futex1 = 0, futex2 = 0; 28static u_int32_t futex1 = 0, futex2 = 0;
25 29
@@ -59,7 +63,7 @@ static void print_summary(void)
59 printf("Requeued %d of %d threads in %.4f ms (+-%.2f%%)\n", 63 printf("Requeued %d of %d threads in %.4f ms (+-%.2f%%)\n",
60 requeued_avg, 64 requeued_avg,
61 nthreads, 65 nthreads,
62 requeuetime_avg/1e3, 66 requeuetime_avg / USEC_PER_MSEC,
63 rel_stddev_stats(requeuetime_stddev, requeuetime_avg)); 67 rel_stddev_stats(requeuetime_stddev, requeuetime_avg));
64} 68}
65 69
@@ -181,7 +185,7 @@ int bench_futex_requeue(int argc, const char **argv,
181 185
182 if (!silent) { 186 if (!silent) {
183 printf("[Run %d]: Requeued %d of %d threads in %.4f ms\n", 187 printf("[Run %d]: Requeued %d of %d threads in %.4f ms\n",
184 j + 1, nrequeued, nthreads, runtime.tv_usec/1e3); 188 j + 1, nrequeued, nthreads, runtime.tv_usec / (double)USEC_PER_MSEC);
185 } 189 }
186 190
187 /* everybody should be blocked on futex2, wake'em up */ 191 /* everybody should be blocked on futex2, wake'em up */
diff --git a/tools/perf/bench/futex-wake-parallel.c b/tools/perf/bench/futex-wake-parallel.c
index 91aaf2a1fa90..2c8fa67ad537 100644
--- a/tools/perf/bench/futex-wake-parallel.c
+++ b/tools/perf/bench/futex-wake-parallel.c
@@ -7,18 +7,22 @@
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 <linux/time64.h>
19#include <errno.h>
15#include "bench.h" 20#include "bench.h"
16#include "futex.h" 21#include "futex.h"
17 22
18#include <err.h> 23#include <err.h>
19#include <stdlib.h> 24#include <stdlib.h>
20#include <sys/time.h> 25#include <sys/time.h>
21#include <pthread.h>
22 26
23struct thread_data { 27struct thread_data {
24 pthread_t worker; 28 pthread_t worker;
@@ -153,7 +157,7 @@ static void print_run(struct thread_data *waking_worker, unsigned int run_num)
153 157
154 printf("[Run %d]: Avg per-thread latency (waking %d/%d threads) " 158 printf("[Run %d]: Avg per-thread latency (waking %d/%d threads) "
155 "in %.4f ms (+-%.2f%%)\n", run_num + 1, wakeup_avg, 159 "in %.4f ms (+-%.2f%%)\n", run_num + 1, wakeup_avg,
156 nblocked_threads, waketime_avg/1e3, 160 nblocked_threads, waketime_avg / USEC_PER_MSEC,
157 rel_stddev_stats(waketime_stddev, waketime_avg)); 161 rel_stddev_stats(waketime_stddev, waketime_avg));
158} 162}
159 163
@@ -169,7 +173,7 @@ static void print_summary(void)
169 printf("Avg per-thread latency (waking %d/%d threads) in %.4f ms (+-%.2f%%)\n", 173 printf("Avg per-thread latency (waking %d/%d threads) in %.4f ms (+-%.2f%%)\n",
170 wakeup_avg, 174 wakeup_avg,
171 nblocked_threads, 175 nblocked_threads,
172 waketime_avg/1e3, 176 waketime_avg / USEC_PER_MSEC,
173 rel_stddev_stats(waketime_stddev, waketime_avg)); 177 rel_stddev_stats(waketime_stddev, waketime_avg));
174} 178}
175 179
diff --git a/tools/perf/bench/futex-wake.c b/tools/perf/bench/futex-wake.c
index f416bd705f66..e246b1b8388a 100644
--- a/tools/perf/bench/futex-wake.c
+++ b/tools/perf/bench/futex-wake.c
@@ -8,18 +8,22 @@
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 <linux/time64.h>
20#include <errno.h>
16#include "bench.h" 21#include "bench.h"
17#include "futex.h" 22#include "futex.h"
18 23
19#include <err.h> 24#include <err.h>
20#include <stdlib.h> 25#include <stdlib.h>
21#include <sys/time.h> 26#include <sys/time.h>
22#include <pthread.h>
23 27
24/* all threads will block on the same futex */ 28/* all threads will block on the same futex */
25static u_int32_t futex1 = 0; 29static u_int32_t futex1 = 0;
@@ -78,7 +82,7 @@ static void print_summary(void)
78 printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n", 82 printf("Wokeup %d of %d threads in %.4f ms (+-%.2f%%)\n",
79 wakeup_avg, 83 wakeup_avg,
80 nthreads, 84 nthreads,
81 waketime_avg/1e3, 85 waketime_avg / USEC_PER_MSEC,
82 rel_stddev_stats(waketime_stddev, waketime_avg)); 86 rel_stddev_stats(waketime_stddev, waketime_avg));
83} 87}
84 88
@@ -179,7 +183,7 @@ int bench_futex_wake(int argc, const char **argv,
179 183
180 if (!silent) { 184 if (!silent) {
181 printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n", 185 printf("[Run %d]: Wokeup %d of %d threads in %.4f ms\n",
182 j + 1, nwoken, nthreads, runtime.tv_usec/1e3); 186 j + 1, nwoken, nthreads, runtime.tv_usec / (double)USEC_PER_MSEC);
183 } 187 }
184 188
185 for (i = 0; i < nthreads; i++) { 189 for (i = 0; i < nthreads; i++) {
diff --git a/tools/perf/bench/mem-functions.c b/tools/perf/bench/mem-functions.c
index 2b54d0f2672a..c684910e5a48 100644
--- a/tools/perf/bench/mem-functions.c
+++ b/tools/perf/bench/mem-functions.c
@@ -21,6 +21,7 @@
21#include <string.h> 21#include <string.h>
22#include <sys/time.h> 22#include <sys/time.h>
23#include <errno.h> 23#include <errno.h>
24#include <linux/time64.h>
24 25
25#define K 1024 26#define K 1024
26 27
@@ -89,7 +90,7 @@ static u64 get_cycles(void)
89 90
90static double timeval2double(struct timeval *ts) 91static double timeval2double(struct timeval *ts)
91{ 92{
92 return (double)ts->tv_sec + (double)ts->tv_usec / (double)1000000; 93 return (double)ts->tv_sec + (double)ts->tv_usec / (double)USEC_PER_SEC;
93} 94}
94 95
95#define print_bps(x) do { \ 96#define print_bps(x) do { \
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..8efe904e486b 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,13 +24,13 @@
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>
28#include <sys/wait.h> 30#include <sys/wait.h>
29#include <sys/prctl.h> 31#include <sys/prctl.h>
30#include <sys/types.h> 32#include <sys/types.h>
33#include <linux/time64.h>
31 34
32#include <numa.h> 35#include <numa.h>
33#include <numaif.h> 36#include <numaif.h>
@@ -1002,7 +1005,7 @@ static void calc_convergence(double runtime_ns_max, double *convergence)
1002 if (strong && process_groups == g->p.nr_proc) { 1005 if (strong && process_groups == g->p.nr_proc) {
1003 if (!*convergence) { 1006 if (!*convergence) {
1004 *convergence = runtime_ns_max; 1007 *convergence = runtime_ns_max;
1005 tprintf(" (%6.1fs converged)\n", *convergence/1e9); 1008 tprintf(" (%6.1fs converged)\n", *convergence / NSEC_PER_SEC);
1006 if (g->p.measure_convergence) { 1009 if (g->p.measure_convergence) {
1007 g->all_converged = true; 1010 g->all_converged = true;
1008 g->stop_work = true; 1011 g->stop_work = true;
@@ -1010,7 +1013,7 @@ static void calc_convergence(double runtime_ns_max, double *convergence)
1010 } 1013 }
1011 } else { 1014 } else {
1012 if (*convergence) { 1015 if (*convergence) {
1013 tprintf(" (%6.1fs de-converged)", runtime_ns_max/1e9); 1016 tprintf(" (%6.1fs de-converged)", runtime_ns_max / NSEC_PER_SEC);
1014 *convergence = 0; 1017 *convergence = 0;
1015 } 1018 }
1016 tprintf("\n"); 1019 tprintf("\n");
@@ -1020,7 +1023,7 @@ static void calc_convergence(double runtime_ns_max, double *convergence)
1020static void show_summary(double runtime_ns_max, int l, double *convergence) 1023static void show_summary(double runtime_ns_max, int l, double *convergence)
1021{ 1024{
1022 tprintf("\r # %5.1f%% [%.1f mins]", 1025 tprintf("\r # %5.1f%% [%.1f mins]",
1023 (double)(l+1)/g->p.nr_loops*100.0, runtime_ns_max/1e9 / 60.0); 1026 (double)(l+1)/g->p.nr_loops*100.0, runtime_ns_max / NSEC_PER_SEC / 60.0);
1024 1027
1025 calc_convergence(runtime_ns_max, convergence); 1028 calc_convergence(runtime_ns_max, convergence);
1026 1029
@@ -1177,8 +1180,8 @@ static void *worker_thread(void *__tdata)
1177 1180
1178 if (details >= 3) { 1181 if (details >= 3) {
1179 timersub(&stop, &start, &diff); 1182 timersub(&stop, &start, &diff);
1180 runtime_ns_max = diff.tv_sec * 1000000000; 1183 runtime_ns_max = diff.tv_sec * NSEC_PER_SEC;
1181 runtime_ns_max += diff.tv_usec * 1000; 1184 runtime_ns_max += diff.tv_usec * NSEC_PER_USEC;
1182 1185
1183 if (details >= 0) { 1186 if (details >= 0) {
1184 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016"PRIx64"]\n", 1187 printf(" #%2d / %2d: %14.2lf nsecs/op [val: %016"PRIx64"]\n",
@@ -1190,23 +1193,23 @@ static void *worker_thread(void *__tdata)
1190 continue; 1193 continue;
1191 1194
1192 timersub(&stop, &start0, &diff); 1195 timersub(&stop, &start0, &diff);
1193 runtime_ns_max = diff.tv_sec * 1000000000ULL; 1196 runtime_ns_max = diff.tv_sec * NSEC_PER_SEC;
1194 runtime_ns_max += diff.tv_usec * 1000ULL; 1197 runtime_ns_max += diff.tv_usec * NSEC_PER_USEC;
1195 1198
1196 show_summary(runtime_ns_max, l, &convergence); 1199 show_summary(runtime_ns_max, l, &convergence);
1197 } 1200 }
1198 1201
1199 gettimeofday(&stop, NULL); 1202 gettimeofday(&stop, NULL);
1200 timersub(&stop, &start0, &diff); 1203 timersub(&stop, &start0, &diff);
1201 td->runtime_ns = diff.tv_sec * 1000000000ULL; 1204 td->runtime_ns = diff.tv_sec * NSEC_PER_SEC;
1202 td->runtime_ns += diff.tv_usec * 1000ULL; 1205 td->runtime_ns += diff.tv_usec * NSEC_PER_USEC;
1203 td->speed_gbs = bytes_done / (td->runtime_ns / 1e9) / 1e9; 1206 td->speed_gbs = bytes_done / (td->runtime_ns / NSEC_PER_SEC) / 1e9;
1204 1207
1205 getrusage(RUSAGE_THREAD, &rusage); 1208 getrusage(RUSAGE_THREAD, &rusage);
1206 td->system_time_ns = rusage.ru_stime.tv_sec * 1000000000ULL; 1209 td->system_time_ns = rusage.ru_stime.tv_sec * NSEC_PER_SEC;
1207 td->system_time_ns += rusage.ru_stime.tv_usec * 1000ULL; 1210 td->system_time_ns += rusage.ru_stime.tv_usec * NSEC_PER_USEC;
1208 td->user_time_ns = rusage.ru_utime.tv_sec * 1000000000ULL; 1211 td->user_time_ns = rusage.ru_utime.tv_sec * NSEC_PER_SEC;
1209 td->user_time_ns += rusage.ru_utime.tv_usec * 1000ULL; 1212 td->user_time_ns += rusage.ru_utime.tv_usec * NSEC_PER_USEC;
1210 1213
1211 free_data(thread_data, g->p.bytes_thread); 1214 free_data(thread_data, g->p.bytes_thread);
1212 1215
@@ -1467,7 +1470,7 @@ static int __bench_numa(const char *name)
1467 } 1470 }
1468 /* Wait for all the threads to start up: */ 1471 /* Wait for all the threads to start up: */
1469 while (g->nr_tasks_started != g->p.nr_tasks) 1472 while (g->nr_tasks_started != g->p.nr_tasks)
1470 usleep(1000); 1473 usleep(USEC_PER_MSEC);
1471 1474
1472 BUG_ON(g->nr_tasks_started != g->p.nr_tasks); 1475 BUG_ON(g->nr_tasks_started != g->p.nr_tasks);
1473 1476
@@ -1486,9 +1489,9 @@ static int __bench_numa(const char *name)
1486 1489
1487 timersub(&stop, &start, &diff); 1490 timersub(&stop, &start, &diff);
1488 1491
1489 startup_sec = diff.tv_sec * 1000000000.0; 1492 startup_sec = diff.tv_sec * NSEC_PER_SEC;
1490 startup_sec += diff.tv_usec * 1000.0; 1493 startup_sec += diff.tv_usec * NSEC_PER_USEC;
1491 startup_sec /= 1e9; 1494 startup_sec /= NSEC_PER_SEC;
1492 1495
1493 tprintf(" threads initialized in %.6f seconds.\n", startup_sec); 1496 tprintf(" threads initialized in %.6f seconds.\n", startup_sec);
1494 tprintf(" #\n"); 1497 tprintf(" #\n");
@@ -1527,14 +1530,14 @@ static int __bench_numa(const char *name)
1527 tprintf("\n ###\n"); 1530 tprintf("\n ###\n");
1528 tprintf("\n"); 1531 tprintf("\n");
1529 1532
1530 runtime_sec_max = diff.tv_sec * 1000000000.0; 1533 runtime_sec_max = diff.tv_sec * NSEC_PER_SEC;
1531 runtime_sec_max += diff.tv_usec * 1000.0; 1534 runtime_sec_max += diff.tv_usec * NSEC_PER_USEC;
1532 runtime_sec_max /= 1e9; 1535 runtime_sec_max /= NSEC_PER_SEC;
1533 1536
1534 runtime_sec_min = runtime_ns_min/1e9; 1537 runtime_sec_min = runtime_ns_min / NSEC_PER_SEC;
1535 1538
1536 bytes = g->bytes_done; 1539 bytes = g->bytes_done;
1537 runtime_avg = (double)runtime_ns_sum / g->p.nr_tasks / 1e9; 1540 runtime_avg = (double)runtime_ns_sum / g->p.nr_tasks / NSEC_PER_SEC;
1538 1541
1539 if (g->p.measure_convergence) { 1542 if (g->p.measure_convergence) {
1540 print_res(name, runtime_sec_max, 1543 print_res(name, runtime_sec_max,
@@ -1560,7 +1563,7 @@ static int __bench_numa(const char *name)
1560 print_res(name, bytes / 1e9, 1563 print_res(name, bytes / 1e9,
1561 "GB,", "data-total", "GB data processed, total"); 1564 "GB,", "data-total", "GB data processed, total");
1562 1565
1563 print_res(name, runtime_sec_max * 1e9 / (bytes / g->p.nr_tasks), 1566 print_res(name, runtime_sec_max * NSEC_PER_SEC / (bytes / g->p.nr_tasks),
1564 "nsecs,", "runtime/byte/thread","nsecs/byte/thread runtime"); 1567 "nsecs,", "runtime/byte/thread","nsecs/byte/thread runtime");
1565 1568
1566 print_res(name, bytes / g->p.nr_tasks / 1e9 / runtime_sec_max, 1569 print_res(name, bytes / g->p.nr_tasks / 1e9 / runtime_sec_max,
@@ -1579,9 +1582,9 @@ static int __bench_numa(const char *name)
1579 snprintf(tname, 32, "process%d:thread%d", p, t); 1582 snprintf(tname, 32, "process%d:thread%d", p, t);
1580 print_res(tname, td->speed_gbs, 1583 print_res(tname, td->speed_gbs,
1581 "GB/sec", "thread-speed", "GB/sec/thread speed"); 1584 "GB/sec", "thread-speed", "GB/sec/thread speed");
1582 print_res(tname, td->system_time_ns / 1e9, 1585 print_res(tname, td->system_time_ns / NSEC_PER_SEC,
1583 "secs", "thread-system-time", "system CPU time/thread"); 1586 "secs", "thread-system-time", "system CPU time/thread");
1584 print_res(tname, td->user_time_ns / 1e9, 1587 print_res(tname, td->user_time_ns / NSEC_PER_SEC,
1585 "secs", "thread-user-time", "user CPU time/thread"); 1588 "secs", "thread-user-time", "user CPU time/thread");
1586 } 1589 }
1587 } 1590 }
diff --git a/tools/perf/bench/sched-messaging.c b/tools/perf/bench/sched-messaging.c
index bfaf9503de8e..6a111e775210 100644
--- a/tools/perf/bench/sched-messaging.c
+++ b/tools/perf/bench/sched-messaging.c
@@ -29,6 +29,7 @@
29#include <poll.h> 29#include <poll.h>
30#include <limits.h> 30#include <limits.h>
31#include <err.h> 31#include <err.h>
32#include <linux/time64.h>
32 33
33#define DATASIZE 100 34#define DATASIZE 100
34 35
@@ -312,11 +313,11 @@ int bench_sched_messaging(int argc, const char **argv,
312 thread_mode ? "threads" : "processes"); 313 thread_mode ? "threads" : "processes");
313 printf(" %14s: %lu.%03lu [sec]\n", "Total time", 314 printf(" %14s: %lu.%03lu [sec]\n", "Total time",
314 diff.tv_sec, 315 diff.tv_sec,
315 (unsigned long) (diff.tv_usec/1000)); 316 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
316 break; 317 break;
317 case BENCH_FORMAT_SIMPLE: 318 case BENCH_FORMAT_SIMPLE:
318 printf("%lu.%03lu\n", diff.tv_sec, 319 printf("%lu.%03lu\n", diff.tv_sec,
319 (unsigned long) (diff.tv_usec/1000)); 320 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
320 break; 321 break;
321 default: 322 default:
322 /* reaching here is something disaster */ 323 /* reaching here is something disaster */
diff --git a/tools/perf/bench/sched-pipe.c b/tools/perf/bench/sched-pipe.c
index 1dc2d13cc272..2243f0150d76 100644
--- a/tools/perf/bench/sched-pipe.c
+++ b/tools/perf/bench/sched-pipe.c
@@ -25,6 +25,7 @@
25#include <sys/time.h> 25#include <sys/time.h>
26#include <sys/types.h> 26#include <sys/types.h>
27#include <sys/syscall.h> 27#include <sys/syscall.h>
28#include <linux/time64.h>
28 29
29#include <pthread.h> 30#include <pthread.h>
30 31
@@ -153,24 +154,24 @@ int bench_sched_pipe(int argc, const char **argv, const char *prefix __maybe_unu
153 printf("# Executed %d pipe operations between two %s\n\n", 154 printf("# Executed %d pipe operations between two %s\n\n",
154 loops, threaded ? "threads" : "processes"); 155 loops, threaded ? "threads" : "processes");
155 156
156 result_usec = diff.tv_sec * 1000000; 157 result_usec = diff.tv_sec * USEC_PER_SEC;
157 result_usec += diff.tv_usec; 158 result_usec += diff.tv_usec;
158 159
159 printf(" %14s: %lu.%03lu [sec]\n\n", "Total time", 160 printf(" %14s: %lu.%03lu [sec]\n\n", "Total time",
160 diff.tv_sec, 161 diff.tv_sec,
161 (unsigned long) (diff.tv_usec/1000)); 162 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
162 163
163 printf(" %14lf usecs/op\n", 164 printf(" %14lf usecs/op\n",
164 (double)result_usec / (double)loops); 165 (double)result_usec / (double)loops);
165 printf(" %14d ops/sec\n", 166 printf(" %14d ops/sec\n",
166 (int)((double)loops / 167 (int)((double)loops /
167 ((double)result_usec / (double)1000000))); 168 ((double)result_usec / (double)USEC_PER_SEC)));
168 break; 169 break;
169 170
170 case BENCH_FORMAT_SIMPLE: 171 case BENCH_FORMAT_SIMPLE:
171 printf("%lu.%03lu\n", 172 printf("%lu.%03lu\n",
172 diff.tv_sec, 173 diff.tv_sec,
173 (unsigned long) (diff.tv_usec / 1000)); 174 (unsigned long) (diff.tv_usec / USEC_PER_MSEC));
174 break; 175 break;
175 176
176 default: 177 default:
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 25c81734a950..ebb628332a6e 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -30,6 +30,7 @@
30#include "util/tool.h" 30#include "util/tool.h"
31#include "util/data.h" 31#include "util/data.h"
32#include "arch/common.h" 32#include "arch/common.h"
33#include "util/block-range.h"
33 34
34#include <dlfcn.h> 35#include <dlfcn.h>
35#include <linux/bitmap.h> 36#include <linux/bitmap.h>
@@ -46,6 +47,103 @@ struct perf_annotate {
46 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS); 47 DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
47}; 48};
48 49
50/*
51 * Given one basic block:
52 *
53 * from to branch_i
54 * * ----> *
55 * |
56 * | block
57 * v
58 * * ----> *
59 * from to branch_i+1
60 *
61 * where the horizontal are the branches and the vertical is the executed
62 * block of instructions.
63 *
64 * We count, for each 'instruction', the number of blocks that covered it as
65 * well as count the ratio each branch is taken.
66 *
67 * We can do this without knowing the actual instruction stream by keeping
68 * track of the address ranges. We break down ranges such that there is no
69 * overlap and iterate from the start until the end.
70 *
71 * @acme: once we parse the objdump output _before_ processing the samples,
72 * we can easily fold the branch.cycles IPC bits in.
73 */
74static void process_basic_block(struct addr_map_symbol *start,
75 struct addr_map_symbol *end,
76 struct branch_flags *flags)
77{
78 struct symbol *sym = start->sym;
79 struct annotation *notes = sym ? symbol__annotation(sym) : NULL;
80 struct block_range_iter iter;
81 struct block_range *entry;
82
83 /*
84 * Sanity; NULL isn't executable and the CPU cannot execute backwards
85 */
86 if (!start->addr || start->addr > end->addr)
87 return;
88
89 iter = block_range__create(start->addr, end->addr);
90 if (!block_range_iter__valid(&iter))
91 return;
92
93 /*
94 * First block in range is a branch target.
95 */
96 entry = block_range_iter(&iter);
97 assert(entry->is_target);
98 entry->entry++;
99
100 do {
101 entry = block_range_iter(&iter);
102
103 entry->coverage++;
104 entry->sym = sym;
105
106 if (notes)
107 notes->max_coverage = max(notes->max_coverage, entry->coverage);
108
109 } while (block_range_iter__next(&iter));
110
111 /*
112 * Last block in rage is a branch.
113 */
114 entry = block_range_iter(&iter);
115 assert(entry->is_branch);
116 entry->taken++;
117 if (flags->predicted)
118 entry->pred++;
119}
120
121static void process_branch_stack(struct branch_stack *bs, struct addr_location *al,
122 struct perf_sample *sample)
123{
124 struct addr_map_symbol *prev = NULL;
125 struct branch_info *bi;
126 int i;
127
128 if (!bs || !bs->nr)
129 return;
130
131 bi = sample__resolve_bstack(sample, al);
132 if (!bi)
133 return;
134
135 for (i = bs->nr - 1; i >= 0; i--) {
136 /*
137 * XXX filter against symbol
138 */
139 if (prev)
140 process_basic_block(prev, &bi[i].from, &bi[i].flags);
141 prev = &bi[i].to;
142 }
143
144 free(bi);
145}
146
49static int perf_evsel__add_sample(struct perf_evsel *evsel, 147static int perf_evsel__add_sample(struct perf_evsel *evsel,
50 struct perf_sample *sample, 148 struct perf_sample *sample,
51 struct addr_location *al, 149 struct addr_location *al,
@@ -72,10 +170,16 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
72 return 0; 170 return 0;
73 } 171 }
74 172
173 /*
174 * XXX filtered samples can still have branch entires pointing into our
175 * symbol and are missed.
176 */
177 process_branch_stack(sample->branch_stack, al, sample);
178
75 sample->period = 1; 179 sample->period = 1;
76 sample->weight = 1; 180 sample->weight = 1;
77 181
78 he = __hists__add_entry(hists, al, NULL, NULL, NULL, sample, true); 182 he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
79 if (he == NULL) 183 if (he == NULL)
80 return -ENOMEM; 184 return -ENOMEM;
81 185
@@ -204,8 +308,6 @@ static int __cmd_annotate(struct perf_annotate *ann)
204 struct perf_evsel *pos; 308 struct perf_evsel *pos;
205 u64 total_nr_samples; 309 u64 total_nr_samples;
206 310
207 machines__set_symbol_filter(&session->machines, symbol__annotate_init);
208
209 if (ann->cpu_list) { 311 if (ann->cpu_list) {
210 ret = perf_session__cpu_bitmap(session, ann->cpu_list, 312 ret = perf_session__cpu_bitmap(session, ann->cpu_list,
211 ann->cpu_bitmap); 313 ann->cpu_bitmap);
@@ -236,7 +338,7 @@ static int __cmd_annotate(struct perf_annotate *ann)
236 perf_session__fprintf_dsos(session, stdout); 338 perf_session__fprintf_dsos(session, stdout);
237 339
238 total_nr_samples = 0; 340 total_nr_samples = 0;
239 evlist__for_each(session->evlist, pos) { 341 evlist__for_each_entry(session->evlist, pos) {
240 struct hists *hists = evsel__hists(pos); 342 struct hists *hists = evsel__hists(pos);
241 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 343 u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE];
242 344
@@ -339,6 +441,9 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
339 "Show event group information together"), 441 "Show event group information together"),
340 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period, 442 OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
341 "Show a column with the sum of periods"), 443 "Show a column with the sum of periods"),
444 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
445 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
446 stdio__config_color, "always"),
342 OPT_END() 447 OPT_END()
343 }; 448 };
344 int ret = hists__init(); 449 int ret = hists__init();
@@ -364,7 +469,10 @@ int cmd_annotate(int argc, const char **argv, const char *prefix __maybe_unused)
364 if (annotate.session == NULL) 469 if (annotate.session == NULL)
365 return -1; 470 return -1;
366 471
367 symbol_conf.priv_size = sizeof(struct annotation); 472 ret = symbol__annotation_init();
473 if (ret < 0)
474 goto out_delete;
475
368 symbol_conf.try_vmlinux_path = true; 476 symbol_conf.try_vmlinux_path = true;
369 477
370 ret = symbol__init(&annotate.session->header.env); 478 ret = symbol__init(&annotate.session->header.env);
diff --git a/tools/perf/builtin-buildid-cache.c b/tools/perf/builtin-buildid-cache.c
index d75bded21fe0..30e2b2cb2421 100644
--- a/tools/perf/builtin-buildid-cache.c
+++ b/tools/perf/builtin-buildid-cache.c
@@ -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 fe1b77fa21f9..e4207a23b52c 100644
--- a/tools/perf/builtin-config.c
+++ b/tools/perf/builtin-config.c
@@ -37,23 +37,16 @@ static int show_config(struct perf_config_set *set)
37{ 37{
38 struct perf_config_section *section; 38 struct perf_config_section *section;
39 struct perf_config_item *item; 39 struct perf_config_item *item;
40 struct list_head *sections;
41 40
42 if (set == NULL) 41 if (set == NULL)
43 return -1; 42 return -1;
44 43
45 sections = &set->sections; 44 perf_config_set__for_each_entry(set, section, item) {
46 if (list_empty(sections)) 45 char *value = item->value;
47 return -1;
48
49 list_for_each_entry(section, sections, node) {
50 list_for_each_entry(item, &section->items, node) {
51 char *value = item->value;
52 46
53 if (value) 47 if (value)
54 printf("%s.%s=%s\n", section->name, 48 printf("%s.%s=%s\n", section->name,
55 item->name, value); 49 item->name, value);
56 }
57 } 50 }
58 51
59 return 0; 52 return 0;
@@ -80,6 +73,10 @@ int cmd_config(int argc, const char **argv, const char *prefix __maybe_unused)
80 else if (use_user_config) 73 else if (use_user_config)
81 config_exclusive_filename = user_config; 74 config_exclusive_filename = user_config;
82 75
76 /*
77 * At only 'config' sub-command, individually use the config set
78 * because of reinitializing with options config file location.
79 */
83 set = perf_config_set__new(); 80 set = perf_config_set__new();
84 if (!set) { 81 if (!set) {
85 ret = -1; 82 ret = -1;
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 f7645a42708e..9ff0db4e2d0c 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);
@@ -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
@@ -1044,7 +1033,9 @@ static int hpp__entry_global(struct perf_hpp_fmt *_fmt, struct perf_hpp *hpp,
1044} 1033}
1045 1034
1046static 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,
1047 struct perf_evsel *evsel __maybe_unused) 1036 struct hists *hists __maybe_unused,
1037 int line __maybe_unused,
1038 int *span __maybe_unused)
1048{ 1039{
1049 struct diff_hpp_fmt *dfmt = 1040 struct diff_hpp_fmt *dfmt =
1050 container_of(fmt, struct diff_hpp_fmt, fmt); 1041 container_of(fmt, struct diff_hpp_fmt, fmt);
@@ -1055,7 +1046,7 @@ static int hpp__header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1055 1046
1056static int hpp__width(struct perf_hpp_fmt *fmt, 1047static int hpp__width(struct perf_hpp_fmt *fmt,
1057 struct perf_hpp *hpp __maybe_unused, 1048 struct perf_hpp *hpp __maybe_unused,
1058 struct perf_evsel *evsel __maybe_unused) 1049 struct hists *hists __maybe_unused)
1059{ 1050{
1060 struct diff_hpp_fmt *dfmt = 1051 struct diff_hpp_fmt *dfmt =
1061 container_of(fmt, struct diff_hpp_fmt, fmt); 1052 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 f9830c902b78..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"
@@ -117,7 +117,7 @@ static void exec_woman_emacs(const char *path, const char *page)
117 free(man_page); 117 free(man_page);
118 } 118 }
119 warning("failed to exec '%s': %s", path, 119 warning("failed to exec '%s': %s", path,
120 strerror_r(errno, sbuf, sizeof(sbuf))); 120 str_error_r(errno, sbuf, sizeof(sbuf)));
121 } 121 }
122} 122}
123 123
@@ -150,7 +150,7 @@ static void exec_man_konqueror(const char *path, const char *page)
150 free(man_page); 150 free(man_page);
151 } 151 }
152 warning("failed to exec '%s': %s", path, 152 warning("failed to exec '%s': %s", path,
153 strerror_r(errno, sbuf, sizeof(sbuf))); 153 str_error_r(errno, sbuf, sizeof(sbuf)));
154 } 154 }
155} 155}
156 156
@@ -162,7 +162,7 @@ static void exec_man_man(const char *path, const char *page)
162 path = "man"; 162 path = "man";
163 execlp(path, "man", page, NULL); 163 execlp(path, "man", page, NULL);
164 warning("failed to exec '%s': %s", path, 164 warning("failed to exec '%s': %s", path,
165 strerror_r(errno, sbuf, sizeof(sbuf))); 165 str_error_r(errno, sbuf, sizeof(sbuf)));
166} 166}
167 167
168static void exec_man_cmd(const char *cmd, const char *page) 168static void exec_man_cmd(const char *cmd, const char *page)
@@ -175,7 +175,7 @@ static void exec_man_cmd(const char *cmd, const char *page)
175 free(shell_cmd); 175 free(shell_cmd);
176 } 176 }
177 warning("failed to exec '%s': %s", cmd, 177 warning("failed to exec '%s': %s", cmd,
178 strerror_r(errno, sbuf, sizeof(sbuf))); 178 str_error_r(errno, sbuf, sizeof(sbuf)));
179} 179}
180 180
181static 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 e5afa8fe1bf1..b9bc7e39833a 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -429,7 +429,7 @@ static int perf_event__inject_buildid(struct perf_tool *tool,
429 if (al.map != NULL) { 429 if (al.map != NULL) {
430 if (!al.map->dso->hit) { 430 if (!al.map->dso->hit) {
431 al.map->dso->hit = 1; 431 al.map->dso->hit = 1;
432 if (map__load(al.map, NULL) >= 0) { 432 if (map__load(al.map) >= 0) {
433 dso__inject_build_id(al.map->dso, tool, machine); 433 dso__inject_build_id(al.map->dso, tool, machine);
434 /* 434 /*
435 * If this fails, too bad, let the other side 435 * If this fails, too bad, let the other side
@@ -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")) {
diff --git a/tools/perf/builtin-kmem.c b/tools/perf/builtin-kmem.c
index 58adfee230de..d426dcb18ce9 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"
@@ -330,7 +330,7 @@ static int build_alloc_func_list(void)
330 } 330 }
331 331
332 kernel_map = machine__kernel_map(machine); 332 kernel_map = machine__kernel_map(machine);
333 if (map__load(kernel_map, NULL) < 0) { 333 if (map__load(kernel_map) < 0) {
334 pr_err("cannot load kernel map\n"); 334 pr_err("cannot load kernel map\n");
335 return -ENOENT; 335 return -ENOENT;
336 } 336 }
@@ -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" },
@@ -978,7 +979,7 @@ static void __print_slab_result(struct rb_root *root,
978 if (is_caller) { 979 if (is_caller) {
979 addr = data->call_site; 980 addr = data->call_site;
980 if (!raw_ip) 981 if (!raw_ip)
981 sym = machine__find_kernel_function(machine, addr, &map, NULL); 982 sym = machine__find_kernel_function(machine, addr, &map);
982 } else 983 } else
983 addr = data->ptr; 984 addr = data->ptr;
984 985
@@ -1042,8 +1043,7 @@ static void __print_page_alloc_result(struct perf_session *session, int n_lines)
1042 char *caller = buf; 1043 char *caller = buf;
1043 1044
1044 data = rb_entry(next, struct page_stat, node); 1045 data = rb_entry(next, struct page_stat, node);
1045 sym = machine__find_kernel_function(machine, data->callsite, 1046 sym = machine__find_kernel_function(machine, data->callsite, &map);
1046 &map, NULL);
1047 if (sym && sym->name) 1047 if (sym && sym->name)
1048 caller = sym->name; 1048 caller = sym->name;
1049 else 1049 else
@@ -1085,8 +1085,7 @@ static void __print_page_caller_result(struct perf_session *session, int n_lines
1085 char *caller = buf; 1085 char *caller = buf;
1086 1086
1087 data = rb_entry(next, struct page_stat, node); 1087 data = rb_entry(next, struct page_stat, node);
1088 sym = machine__find_kernel_function(machine, data->callsite, 1088 sym = machine__find_kernel_function(machine, data->callsite, &map);
1089 &map, NULL);
1090 if (sym && sym->name) 1089 if (sym && sym->name)
1091 caller = sym->name; 1090 caller = sym->name;
1092 else 1091 else
@@ -1354,7 +1353,7 @@ static int __cmd_kmem(struct perf_session *session)
1354 goto out; 1353 goto out;
1355 } 1354 }
1356 1355
1357 evlist__for_each(session->evlist, evsel) { 1356 evlist__for_each_entry(session->evlist, evsel) {
1358 if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") && 1357 if (!strcmp(perf_evsel__name(evsel), "kmem:mm_page_alloc") &&
1359 perf_evsel__field(evsel, "pfn")) { 1358 perf_evsel__field(evsel, "pfn")) {
1360 use_pfn = true; 1359 use_pfn = true;
diff --git a/tools/perf/builtin-kvm.c b/tools/perf/builtin-kvm.c
index 6487c06d2708..08fa88f62a24 100644
--- a/tools/perf/builtin-kvm.c
+++ b/tools/perf/builtin-kvm.c
@@ -24,6 +24,7 @@
24#include <sys/timerfd.h> 24#include <sys/timerfd.h>
25#endif 25#endif
26 26
27#include <linux/time64.h>
27#include <termios.h> 28#include <termios.h>
28#include <semaphore.h> 29#include <semaphore.h>
29#include <pthread.h> 30#include <pthread.h>
@@ -362,7 +363,7 @@ static bool handle_end_event(struct perf_kvm_stat *kvm,
362 if (!skip_event(decode)) { 363 if (!skip_event(decode)) {
363 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n", 364 pr_info("%" PRIu64 " VM %d, vcpu %d: %s event took %" PRIu64 "usec\n",
364 sample->time, sample->pid, vcpu_record->vcpu_id, 365 sample->time, sample->pid, vcpu_record->vcpu_id,
365 decode, time_diff/1000); 366 decode, time_diff / NSEC_PER_USEC);
366 } 367 }
367 } 368 }
368 369
@@ -608,15 +609,15 @@ static void print_result(struct perf_kvm_stat *kvm)
608 pr_info("%10llu ", (unsigned long long)ecount); 609 pr_info("%10llu ", (unsigned long long)ecount);
609 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100); 610 pr_info("%8.2f%% ", (double)ecount / kvm->total_count * 100);
610 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100); 611 pr_info("%8.2f%% ", (double)etime / kvm->total_time * 100);
611 pr_info("%9.2fus ", (double)min / 1e3); 612 pr_info("%9.2fus ", (double)min / NSEC_PER_USEC);
612 pr_info("%9.2fus ", (double)max / 1e3); 613 pr_info("%9.2fus ", (double)max / NSEC_PER_USEC);
613 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount/1e3, 614 pr_info("%9.2fus ( +-%7.2f%% )", (double)etime / ecount / NSEC_PER_USEC,
614 kvm_event_rel_stddev(vcpu, event)); 615 kvm_event_rel_stddev(vcpu, event));
615 pr_info("\n"); 616 pr_info("\n");
616 } 617 }
617 618
618 pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n", 619 pr_info("\nTotal Samples:%" PRIu64 ", Total events handled time:%.2fus.\n\n",
619 kvm->total_count, kvm->total_time / 1e3); 620 kvm->total_count, kvm->total_time / (double)NSEC_PER_USEC);
620 621
621 if (kvm->lost_events) 622 if (kvm->lost_events)
622 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events); 623 pr_info("\nLost events: %" PRIu64 "\n\n", kvm->lost_events);
@@ -988,7 +989,7 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
988 * Note: exclude_{guest,host} do not apply here. 989 * Note: exclude_{guest,host} do not apply here.
989 * This command processes KVM tracepoints from host only 990 * This command processes KVM tracepoints from host only
990 */ 991 */
991 evlist__for_each(evlist, pos) { 992 evlist__for_each_entry(evlist, pos) {
992 struct perf_event_attr *attr = &pos->attr; 993 struct perf_event_attr *attr = &pos->attr;
993 994
994 /* make sure these *are* set */ 995 /* make sure these *are* set */
@@ -1018,13 +1019,13 @@ static int kvm_live_open_events(struct perf_kvm_stat *kvm)
1018 err = perf_evlist__open(evlist); 1019 err = perf_evlist__open(evlist);
1019 if (err < 0) { 1020 if (err < 0) {
1020 printf("Couldn't create the events: %s\n", 1021 printf("Couldn't create the events: %s\n",
1021 strerror_r(errno, sbuf, sizeof(sbuf))); 1022 str_error_r(errno, sbuf, sizeof(sbuf)));
1022 goto out; 1023 goto out;
1023 } 1024 }
1024 1025
1025 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) { 1026 if (perf_evlist__mmap(evlist, kvm->opts.mmap_pages, false) < 0) {
1026 ui__error("Failed to mmap the events: %s\n", 1027 ui__error("Failed to mmap the events: %s\n",
1027 strerror_r(errno, sbuf, sizeof(sbuf))); 1028 str_error_r(errno, sbuf, sizeof(sbuf)));
1028 perf_evlist__close(evlist); 1029 perf_evlist__close(evlist);
1029 goto out; 1030 goto out;
1030 } 1031 }
@@ -1426,11 +1427,9 @@ static int kvm_events_live(struct perf_kvm_stat *kvm,
1426 err = kvm_events_live_report(kvm); 1427 err = kvm_events_live_report(kvm);
1427 1428
1428out: 1429out:
1429 if (kvm->session) 1430 perf_session__delete(kvm->session);
1430 perf_session__delete(kvm->session);
1431 kvm->session = NULL; 1431 kvm->session = NULL;
1432 if (kvm->evlist) 1432 perf_evlist__delete(kvm->evlist);
1433 perf_evlist__delete(kvm->evlist);
1434 1433
1435 return err; 1434 return err;
1436} 1435}
diff --git a/tools/perf/builtin-list.c b/tools/perf/builtin-list.c
index 5e22db4684b8..ba9322ff858b 100644
--- a/tools/perf/builtin-list.c
+++ b/tools/perf/builtin-list.c
@@ -16,16 +16,23 @@
16#include "util/pmu.h" 16#include "util/pmu.h"
17#include <subcmd/parse-options.h> 17#include <subcmd/parse-options.h>
18 18
19static bool desc_flag = true;
20
19int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused) 21int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
20{ 22{
21 int i; 23 int i;
22 bool raw_dump = false; 24 bool raw_dump = false;
25 bool long_desc_flag = false;
23 struct option list_options[] = { 26 struct option list_options[] = {
24 OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"), 27 OPT_BOOLEAN(0, "raw-dump", &raw_dump, "Dump raw events"),
28 OPT_BOOLEAN('d', "desc", &desc_flag,
29 "Print extra event descriptions. --no-desc to not print."),
30 OPT_BOOLEAN('v', "long-desc", &long_desc_flag,
31 "Print longer event descriptions."),
25 OPT_END() 32 OPT_END()
26 }; 33 };
27 const char * const list_usage[] = { 34 const char * const list_usage[] = {
28 "perf list [hw|sw|cache|tracepoint|pmu|event_glob]", 35 "perf list [<options>] [hw|sw|cache|tracepoint|pmu|sdt|event_glob]",
29 NULL 36 NULL
30 }; 37 };
31 38
@@ -40,7 +47,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
40 printf("\nList of pre-defined events (to be used in -e):\n\n"); 47 printf("\nList of pre-defined events (to be used in -e):\n\n");
41 48
42 if (argc == 0) { 49 if (argc == 0) {
43 print_events(NULL, raw_dump); 50 print_events(NULL, raw_dump, !desc_flag, long_desc_flag);
44 return 0; 51 return 0;
45 } 52 }
46 53
@@ -61,12 +68,16 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
61 strcmp(argv[i], "hwcache") == 0) 68 strcmp(argv[i], "hwcache") == 0)
62 print_hwcache_events(NULL, raw_dump); 69 print_hwcache_events(NULL, raw_dump);
63 else if (strcmp(argv[i], "pmu") == 0) 70 else if (strcmp(argv[i], "pmu") == 0)
64 print_pmu_events(NULL, raw_dump); 71 print_pmu_events(NULL, raw_dump, !desc_flag,
72 long_desc_flag);
73 else if (strcmp(argv[i], "sdt") == 0)
74 print_sdt_events(NULL, NULL, raw_dump);
65 else if ((sep = strchr(argv[i], ':')) != NULL) { 75 else if ((sep = strchr(argv[i], ':')) != NULL) {
66 int sep_idx; 76 int sep_idx;
67 77
68 if (sep == NULL) { 78 if (sep == NULL) {
69 print_events(argv[i], raw_dump); 79 print_events(argv[i], raw_dump, !desc_flag,
80 long_desc_flag);
70 continue; 81 continue;
71 } 82 }
72 sep_idx = sep - argv[i]; 83 sep_idx = sep - argv[i];
@@ -76,6 +87,7 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
76 87
77 s[sep_idx] = '\0'; 88 s[sep_idx] = '\0';
78 print_tracepoint_events(s, s + sep_idx + 1, raw_dump); 89 print_tracepoint_events(s, s + sep_idx + 1, raw_dump);
90 print_sdt_events(s, s + sep_idx + 1, raw_dump);
79 free(s); 91 free(s);
80 } else { 92 } else {
81 if (asprintf(&s, "*%s*", argv[i]) < 0) { 93 if (asprintf(&s, "*%s*", argv[i]) < 0) {
@@ -87,8 +99,10 @@ int cmd_list(int argc, const char **argv, const char *prefix __maybe_unused)
87 print_symbol_events(s, PERF_TYPE_SOFTWARE, 99 print_symbol_events(s, PERF_TYPE_SOFTWARE,
88 event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump); 100 event_symbols_sw, PERF_COUNT_SW_MAX, raw_dump);
89 print_hwcache_events(s, raw_dump); 101 print_hwcache_events(s, raw_dump);
90 print_pmu_events(s, raw_dump); 102 print_pmu_events(s, raw_dump, !desc_flag,
103 long_desc_flag);
91 print_tracepoint_events(NULL, s, raw_dump); 104 print_tracepoint_events(NULL, s, raw_dump);
105 print_sdt_events(NULL, s, raw_dump);
92 free(s); 106 free(s);
93 } 107 }
94 } 108 }
diff --git a/tools/perf/builtin-mem.c b/tools/perf/builtin-mem.c
index 1dc140c5481d..d1ce29be560e 100644
--- a/tools/perf/builtin-mem.c
+++ b/tools/perf/builtin-mem.c
@@ -67,6 +67,7 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
67 OPT_CALLBACK('e', "event", &mem, "event", 67 OPT_CALLBACK('e', "event", &mem, "event",
68 "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",
69 parse_record_events), 69 parse_record_events),
70 OPT_UINTEGER(0, "ldlat", &perf_mem_events__loads_ldlat, "mem-loads latency"),
70 OPT_INCR('v', "verbose", &verbose, 71 OPT_INCR('v', "verbose", &verbose,
71 "be more verbose (show counter open errors, etc)"), 72 "be more verbose (show counter open errors, etc)"),
72 OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"), 73 OPT_BOOLEAN('U', "--all-user", &all_user, "collect only user level data"),
@@ -87,6 +88,9 @@ static int __cmd_record(int argc, const char **argv, struct perf_mem *mem)
87 if (mem->operation & MEM_OPERATION_LOAD) 88 if (mem->operation & MEM_OPERATION_LOAD)
88 perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true; 89 perf_mem_events[PERF_MEM_EVENTS__LOAD].record = true;
89 90
91 if (mem->operation & MEM_OPERATION_STORE)
92 perf_mem_events[PERF_MEM_EVENTS__STORE].record = true;
93
90 if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record) 94 if (perf_mem_events[PERF_MEM_EVENTS__LOAD].record)
91 rec_argv[i++] = "-W"; 95 rec_argv[i++] = "-W";
92 96
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 9af859b28b15..f87996b0cb29 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
@@ -326,6 +326,11 @@ static int perf_add_probe_events(struct perf_probe_event *pevs, int npevs)
326 if (ret < 0) 326 if (ret < 0)
327 goto out_cleanup; 327 goto out_cleanup;
328 328
329 if (params.command == 'D') { /* it shows definition */
330 ret = show_probe_trace_events(pevs, npevs);
331 goto out_cleanup;
332 }
333
329 ret = apply_perf_probe_events(pevs, npevs); 334 ret = apply_perf_probe_events(pevs, npevs);
330 if (ret < 0) 335 if (ret < 0)
331 goto out_cleanup; 336 goto out_cleanup;
@@ -363,6 +368,32 @@ out_cleanup:
363 return ret; 368 return ret;
364} 369}
365 370
371static int del_perf_probe_caches(struct strfilter *filter)
372{
373 struct probe_cache *cache;
374 struct strlist *bidlist;
375 struct str_node *nd;
376 int ret;
377
378 bidlist = build_id_cache__list_all(false);
379 if (!bidlist) {
380 ret = -errno;
381 pr_debug("Failed to get buildids: %d\n", ret);
382 return ret ?: -ENOMEM;
383 }
384
385 strlist__for_each_entry(nd, bidlist) {
386 cache = probe_cache__new(nd->s);
387 if (!cache)
388 continue;
389 if (probe_cache__filter_purge(cache, filter) < 0 ||
390 probe_cache__commit(cache) < 0)
391 pr_warning("Failed to remove entries for %s\n", nd->s);
392 probe_cache__delete(cache);
393 }
394 return 0;
395}
396
366static int perf_del_probe_events(struct strfilter *filter) 397static int perf_del_probe_events(struct strfilter *filter)
367{ 398{
368 int ret, ret2, ufd = -1, kfd = -1; 399 int ret, ret2, ufd = -1, kfd = -1;
@@ -375,6 +406,9 @@ static int perf_del_probe_events(struct strfilter *filter)
375 406
376 pr_debug("Delete filter: \'%s\'\n", str); 407 pr_debug("Delete filter: \'%s\'\n", str);
377 408
409 if (probe_conf.cache)
410 return del_perf_probe_caches(filter);
411
378 /* Get current event names */ 412 /* Get current event names */
379 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW); 413 ret = probe_file__open_both(&kfd, &ufd, PF_FL_RW);
380 if (ret < 0) 414 if (ret < 0)
@@ -389,7 +423,7 @@ static int perf_del_probe_events(struct strfilter *filter)
389 423
390 ret = probe_file__get_events(kfd, filter, klist); 424 ret = probe_file__get_events(kfd, filter, klist);
391 if (ret == 0) { 425 if (ret == 0) {
392 strlist__for_each(ent, klist) 426 strlist__for_each_entry(ent, klist)
393 pr_info("Removed event: %s\n", ent->s); 427 pr_info("Removed event: %s\n", ent->s);
394 428
395 ret = probe_file__del_strlist(kfd, klist); 429 ret = probe_file__del_strlist(kfd, klist);
@@ -399,7 +433,7 @@ static int perf_del_probe_events(struct strfilter *filter)
399 433
400 ret2 = probe_file__get_events(ufd, filter, ulist); 434 ret2 = probe_file__get_events(ufd, filter, ulist);
401 if (ret2 == 0) { 435 if (ret2 == 0) {
402 strlist__for_each(ent, ulist) 436 strlist__for_each_entry(ent, ulist)
403 pr_info("Removed event: %s\n", ent->s); 437 pr_info("Removed event: %s\n", ent->s);
404 438
405 ret2 = probe_file__del_strlist(ufd, ulist); 439 ret2 = probe_file__del_strlist(ufd, ulist);
@@ -425,6 +459,14 @@ out:
425 return ret; 459 return ret;
426} 460}
427 461
462#ifdef HAVE_DWARF_SUPPORT
463#define PROBEDEF_STR \
464 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT [[NAME=]ARG ...]"
465#else
466#define PROBEDEF_STR "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]"
467#endif
468
469
428static int 470static int
429__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused) 471__cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
430{ 472{
@@ -450,13 +492,7 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
450 opt_set_filter_with_command, DEFAULT_LIST_FILTER), 492 opt_set_filter_with_command, DEFAULT_LIST_FILTER),
451 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.", 493 OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
452 opt_set_filter_with_command), 494 opt_set_filter_with_command),
453 OPT_CALLBACK('a', "add", NULL, 495 OPT_CALLBACK('a', "add", NULL, PROBEDEF_STR,
454#ifdef HAVE_DWARF_SUPPORT
455 "[EVENT=]FUNC[@SRC][+OFF|%return|:RL|;PT]|SRC:AL|SRC;PT"
456 " [[NAME=]ARG ...]",
457#else
458 "[EVENT=]FUNC[+OFF|%return] [[NAME=]ARG ...]",
459#endif
460 "probe point definition, where\n" 496 "probe point definition, where\n"
461 "\t\tGROUP:\tGroup name (optional)\n" 497 "\t\tGROUP:\tGroup name (optional)\n"
462 "\t\tEVENT:\tEvent name\n" 498 "\t\tEVENT:\tEvent name\n"
@@ -474,6 +510,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
474 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n", 510 "\t\tARG:\tProbe argument (kprobe-tracer argument format.)\n",
475#endif 511#endif
476 opt_add_probe_event), 512 opt_add_probe_event),
513 OPT_CALLBACK('D', "definition", NULL, PROBEDEF_STR,
514 "Show trace event definition of given traceevent for k/uprobe_events.",
515 opt_add_probe_event),
477 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events" 516 OPT_BOOLEAN('f', "force", &probe_conf.force_add, "forcibly add events"
478 " with existing name"), 517 " with existing name"),
479 OPT_CALLBACK('L', "line", NULL, 518 OPT_CALLBACK('L', "line", NULL,
@@ -512,12 +551,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
512 "Enable symbol demangling"), 551 "Enable symbol demangling"),
513 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel, 552 OPT_BOOLEAN(0, "demangle-kernel", &symbol_conf.demangle_kernel,
514 "Enable kernel symbol demangling"), 553 "Enable kernel symbol demangling"),
554 OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
515 OPT_END() 555 OPT_END()
516 }; 556 };
517 int ret; 557 int ret;
518 558
519 set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE); 559 set_option_flag(options, 'a', "add", PARSE_OPT_EXCLUSIVE);
520 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE); 560 set_option_flag(options, 'd', "del", PARSE_OPT_EXCLUSIVE);
561 set_option_flag(options, 'D', "definition", PARSE_OPT_EXCLUSIVE);
521 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE); 562 set_option_flag(options, 'l', "list", PARSE_OPT_EXCLUSIVE);
522#ifdef HAVE_DWARF_SUPPORT 563#ifdef HAVE_DWARF_SUPPORT
523 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE); 564 set_option_flag(options, 'L', "line", PARSE_OPT_EXCLUSIVE);
@@ -570,6 +611,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
570 */ 611 */
571 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 612 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
572 613
614 /*
615 * Except for --list, --del and --add, other command doesn't depend
616 * nor change running kernel. So if user gives offline vmlinux,
617 * ignore its buildid.
618 */
619 if (!strchr("lda", params.command) && symbol_conf.vmlinux_name)
620 symbol_conf.ignore_vmlinux_buildid = true;
621
573 switch (params.command) { 622 switch (params.command) {
574 case 'l': 623 case 'l':
575 if (params.uprobes) { 624 if (params.uprobes) {
@@ -613,7 +662,9 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
613 return ret; 662 return ret;
614 } 663 }
615 break; 664 break;
665 case 'D':
616 case 'a': 666 case 'a':
667
617 /* Ensure the last given target is used */ 668 /* Ensure the last given target is used */
618 if (params.target && !params.target_used) { 669 if (params.target && !params.target_used) {
619 pr_err(" Error: -x/-m must follow the probe definitions.\n"); 670 pr_err(" Error: -x/-m must follow the probe definitions.\n");
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index dc3fcb597e4c..67d2a9003294 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"
@@ -21,6 +22,7 @@
21#include "util/evlist.h" 22#include "util/evlist.h"
22#include "util/evsel.h" 23#include "util/evsel.h"
23#include "util/debug.h" 24#include "util/debug.h"
25#include "util/drv_configs.h"
24#include "util/session.h" 26#include "util/session.h"
25#include "util/tool.h" 27#include "util/tool.h"
26#include "util/symbol.h" 28#include "util/symbol.h"
@@ -41,7 +43,7 @@
41#include <sched.h> 43#include <sched.h>
42#include <sys/mman.h> 44#include <sys/mman.h>
43#include <asm/bug.h> 45#include <asm/bug.h>
44 46#include <linux/time64.h>
45 47
46struct record { 48struct record {
47 struct perf_tool tool; 49 struct perf_tool tool;
@@ -95,7 +97,7 @@ backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
95 *start = head; 97 *start = head;
96 while (true) { 98 while (true) {
97 if (evt_head - head >= (unsigned int)size) { 99 if (evt_head - head >= (unsigned int)size) {
98 pr_debug("Finshed reading backward ring buffer: rewind\n"); 100 pr_debug("Finished reading backward ring buffer: rewind\n");
99 if (evt_head - head > (unsigned int)size) 101 if (evt_head - head > (unsigned int)size)
100 evt_head -= pheader->size; 102 evt_head -= pheader->size;
101 *end = evt_head; 103 *end = evt_head;
@@ -105,7 +107,7 @@ backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
105 pheader = (struct perf_event_header *)(buf + (evt_head & mask)); 107 pheader = (struct perf_event_header *)(buf + (evt_head & mask));
106 108
107 if (pheader->size == 0) { 109 if (pheader->size == 0) {
108 pr_debug("Finshed reading backward ring buffer: get start\n"); 110 pr_debug("Finished reading backward ring buffer: get start\n");
109 *end = evt_head; 111 *end = evt_head;
110 return 0; 112 return 0;
111 } 113 }
@@ -118,11 +120,10 @@ backward_rb_find_range(void *buf, int mask, u64 head, u64 *start, u64 *end)
118} 120}
119 121
120static int 122static int
121rb_find_range(struct perf_evlist *evlist, 123rb_find_range(void *data, int mask, u64 head, u64 old,
122 void *data, int mask, u64 head, u64 old, 124 u64 *start, u64 *end, bool backward)
123 u64 *start, u64 *end)
124{ 125{
125 if (!evlist->backward) { 126 if (!backward) {
126 *start = old; 127 *start = old;
127 *end = head; 128 *end = head;
128 return 0; 129 return 0;
@@ -131,9 +132,10 @@ rb_find_range(struct perf_evlist *evlist,
131 return backward_rb_find_range(data, mask, head, start, end); 132 return backward_rb_find_range(data, mask, head, start, end);
132} 133}
133 134
134static int record__mmap_read(struct record *rec, int idx) 135static int
136record__mmap_read(struct record *rec, struct perf_mmap *md,
137 bool overwrite, bool backward)
135{ 138{
136 struct perf_mmap *md = &rec->evlist->mmap[idx];
137 u64 head = perf_mmap__read_head(md); 139 u64 head = perf_mmap__read_head(md);
138 u64 old = md->prev; 140 u64 old = md->prev;
139 u64 end = head, start = old; 141 u64 end = head, start = old;
@@ -142,8 +144,8 @@ static int record__mmap_read(struct record *rec, int idx)
142 void *buf; 144 void *buf;
143 int rc = 0; 145 int rc = 0;
144 146
145 if (rb_find_range(rec->evlist, data, md->mask, head, 147 if (rb_find_range(data, md->mask, head,
146 old, &start, &end)) 148 old, &start, &end, backward))
147 return -1; 149 return -1;
148 150
149 if (start == end) 151 if (start == end)
@@ -156,7 +158,7 @@ static int record__mmap_read(struct record *rec, int idx)
156 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n"); 158 WARN_ONCE(1, "failed to keep up with mmap data. (warn only once)\n");
157 159
158 md->prev = head; 160 md->prev = head;
159 perf_evlist__mmap_consume(rec->evlist, idx); 161 perf_mmap__consume(md, overwrite || backward);
160 return 0; 162 return 0;
161 } 163 }
162 164
@@ -181,7 +183,7 @@ static int record__mmap_read(struct record *rec, int idx)
181 } 183 }
182 184
183 md->prev = head; 185 md->prev = head;
184 perf_evlist__mmap_consume(rec->evlist, idx); 186 perf_mmap__consume(md, overwrite || backward);
185out: 187out:
186 return rc; 188 return rc;
187} 189}
@@ -341,6 +343,40 @@ int auxtrace_record__snapshot_start(struct auxtrace_record *itr __maybe_unused)
341 343
342#endif 344#endif
343 345
346static int record__mmap_evlist(struct record *rec,
347 struct perf_evlist *evlist)
348{
349 struct record_opts *opts = &rec->opts;
350 char msg[512];
351
352 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false,
353 opts->auxtrace_mmap_pages,
354 opts->auxtrace_snapshot_mode) < 0) {
355 if (errno == EPERM) {
356 pr_err("Permission error mapping pages.\n"
357 "Consider increasing "
358 "/proc/sys/kernel/perf_event_mlock_kb,\n"
359 "or try again with a smaller value of -m/--mmap_pages.\n"
360 "(current value: %u,%u)\n",
361 opts->mmap_pages, opts->auxtrace_mmap_pages);
362 return -errno;
363 } else {
364 pr_err("failed to mmap with %d (%s)\n", errno,
365 str_error_r(errno, msg, sizeof(msg)));
366 if (errno)
367 return -errno;
368 else
369 return -EINVAL;
370 }
371 }
372 return 0;
373}
374
375static int record__mmap(struct record *rec)
376{
377 return record__mmap_evlist(rec, rec->evlist);
378}
379
344static int record__open(struct record *rec) 380static int record__open(struct record *rec)
345{ 381{
346 char msg[512]; 382 char msg[512];
@@ -348,11 +384,12 @@ static int record__open(struct record *rec)
348 struct perf_evlist *evlist = rec->evlist; 384 struct perf_evlist *evlist = rec->evlist;
349 struct perf_session *session = rec->session; 385 struct perf_session *session = rec->session;
350 struct record_opts *opts = &rec->opts; 386 struct record_opts *opts = &rec->opts;
387 struct perf_evsel_config_term *err_term;
351 int rc = 0; 388 int rc = 0;
352 389
353 perf_evlist__config(evlist, opts, &callchain_param); 390 perf_evlist__config(evlist, opts, &callchain_param);
354 391
355 evlist__for_each(evlist, pos) { 392 evlist__for_each_entry(evlist, pos) {
356try_again: 393try_again:
357 if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) { 394 if (perf_evsel__open(pos, pos->cpus, pos->threads) < 0) {
358 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) { 395 if (perf_evsel__fallback(pos, errno, msg, sizeof(msg))) {
@@ -372,33 +409,23 @@ try_again:
372 if (perf_evlist__apply_filters(evlist, &pos)) { 409 if (perf_evlist__apply_filters(evlist, &pos)) {
373 error("failed to set filter \"%s\" on event %s with %d (%s)\n", 410 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
374 pos->filter, perf_evsel__name(pos), errno, 411 pos->filter, perf_evsel__name(pos), errno,
375 strerror_r(errno, msg, sizeof(msg))); 412 str_error_r(errno, msg, sizeof(msg)));
376 rc = -1; 413 rc = -1;
377 goto out; 414 goto out;
378 } 415 }
379 416
380 if (perf_evlist__mmap_ex(evlist, opts->mmap_pages, false, 417 if (perf_evlist__apply_drv_configs(evlist, &pos, &err_term)) {
381 opts->auxtrace_mmap_pages, 418 error("failed to set config \"%s\" on event %s with %d (%s)\n",
382 opts->auxtrace_snapshot_mode) < 0) { 419 err_term->val.drv_cfg, perf_evsel__name(pos), errno,
383 if (errno == EPERM) { 420 str_error_r(errno, msg, sizeof(msg)));
384 pr_err("Permission error mapping pages.\n" 421 rc = -1;
385 "Consider increasing "
386 "/proc/sys/kernel/perf_event_mlock_kb,\n"
387 "or try again with a smaller value of -m/--mmap_pages.\n"
388 "(current value: %u,%u)\n",
389 opts->mmap_pages, opts->auxtrace_mmap_pages);
390 rc = -errno;
391 } else {
392 pr_err("failed to mmap with %d (%s)\n", errno,
393 strerror_r(errno, msg, sizeof(msg)));
394 if (errno)
395 rc = -errno;
396 else
397 rc = -EINVAL;
398 }
399 goto out; 422 goto out;
400 } 423 }
401 424
425 rc = record__mmap(rec);
426 if (rc)
427 goto out;
428
402 session->evlist = evlist; 429 session->evlist = evlist;
403 perf_session__set_id_hdr_size(session); 430 perf_session__set_id_hdr_size(session);
404out: 431out:
@@ -481,17 +508,30 @@ static struct perf_event_header finished_round_event = {
481 .type = PERF_RECORD_FINISHED_ROUND, 508 .type = PERF_RECORD_FINISHED_ROUND,
482}; 509};
483 510
484static int record__mmap_read_all(struct record *rec) 511static int record__mmap_read_evlist(struct record *rec, struct perf_evlist *evlist,
512 bool backward)
485{ 513{
486 u64 bytes_written = rec->bytes_written; 514 u64 bytes_written = rec->bytes_written;
487 int i; 515 int i;
488 int rc = 0; 516 int rc = 0;
517 struct perf_mmap *maps;
489 518
490 for (i = 0; i < rec->evlist->nr_mmaps; i++) { 519 if (!evlist)
491 struct auxtrace_mmap *mm = &rec->evlist->mmap[i].auxtrace_mmap; 520 return 0;
521
522 maps = backward ? evlist->backward_mmap : evlist->mmap;
523 if (!maps)
524 return 0;
492 525
493 if (rec->evlist->mmap[i].base) { 526 if (backward && evlist->bkw_mmap_state != BKW_MMAP_DATA_PENDING)
494 if (record__mmap_read(rec, i) != 0) { 527 return 0;
528
529 for (i = 0; i < evlist->nr_mmaps; i++) {
530 struct auxtrace_mmap *mm = &maps[i].auxtrace_mmap;
531
532 if (maps[i].base) {
533 if (record__mmap_read(rec, &maps[i],
534 evlist->overwrite, backward) != 0) {
495 rc = -1; 535 rc = -1;
496 goto out; 536 goto out;
497 } 537 }
@@ -511,10 +551,23 @@ static int record__mmap_read_all(struct record *rec)
511 if (bytes_written != rec->bytes_written) 551 if (bytes_written != rec->bytes_written)
512 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 552 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
513 553
554 if (backward)
555 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_EMPTY);
514out: 556out:
515 return rc; 557 return rc;
516} 558}
517 559
560static int record__mmap_read_all(struct record *rec)
561{
562 int err;
563
564 err = record__mmap_read_evlist(rec, rec->evlist, false);
565 if (err)
566 return err;
567
568 return record__mmap_read_evlist(rec, rec->evlist, true);
569}
570
518static void record__init_features(struct record *rec) 571static void record__init_features(struct record *rec)
519{ 572{
520 struct perf_session *session = rec->session; 573 struct perf_session *session = rec->session;
@@ -561,13 +614,16 @@ record__finish_output(struct record *rec)
561 return; 614 return;
562} 615}
563 616
564static int record__synthesize_workload(struct record *rec) 617static int record__synthesize_workload(struct record *rec, bool tail)
565{ 618{
566 struct { 619 struct {
567 struct thread_map map; 620 struct thread_map map;
568 struct thread_map_data map_data; 621 struct thread_map_data map_data;
569 } thread_map; 622 } thread_map;
570 623
624 if (rec->opts.tail_synthesize != tail)
625 return 0;
626
571 thread_map.map.nr = 1; 627 thread_map.map.nr = 1;
572 thread_map.map.map[0].pid = rec->evlist->workload.pid; 628 thread_map.map.map[0].pid = rec->evlist->workload.pid;
573 thread_map.map.map[0].comm = NULL; 629 thread_map.map.map[0].comm = NULL;
@@ -578,7 +634,7 @@ static int record__synthesize_workload(struct record *rec)
578 rec->opts.proc_map_timeout); 634 rec->opts.proc_map_timeout);
579} 635}
580 636
581static int record__synthesize(struct record *rec); 637static int record__synthesize(struct record *rec, bool tail);
582 638
583static int 639static int
584record__switch_output(struct record *rec, bool at_exit) 640record__switch_output(struct record *rec, bool at_exit)
@@ -589,6 +645,10 @@ record__switch_output(struct record *rec, bool at_exit)
589 /* Same Size: "2015122520103046"*/ 645 /* Same Size: "2015122520103046"*/
590 char timestamp[] = "InvalidTimestamp"; 646 char timestamp[] = "InvalidTimestamp";
591 647
648 record__synthesize(rec, true);
649 if (target__none(&rec->opts.target))
650 record__synthesize_workload(rec, true);
651
592 rec->samples = 0; 652 rec->samples = 0;
593 record__finish_output(rec); 653 record__finish_output(rec);
594 err = fetch_current_timestamp(timestamp, sizeof(timestamp)); 654 err = fetch_current_timestamp(timestamp, sizeof(timestamp));
@@ -611,7 +671,7 @@ record__switch_output(struct record *rec, bool at_exit)
611 671
612 /* Output tracking events */ 672 /* Output tracking events */
613 if (!at_exit) { 673 if (!at_exit) {
614 record__synthesize(rec); 674 record__synthesize(rec, false);
615 675
616 /* 676 /*
617 * In 'perf record --switch-output' without -a, 677 * In 'perf record --switch-output' without -a,
@@ -623,7 +683,7 @@ record__switch_output(struct record *rec, bool at_exit)
623 * perf_event__synthesize_thread_map() for those events. 683 * perf_event__synthesize_thread_map() for those events.
624 */ 684 */
625 if (target__none(&rec->opts.target)) 685 if (target__none(&rec->opts.target))
626 record__synthesize_workload(rec); 686 record__synthesize_workload(rec, false);
627 } 687 }
628 return fd; 688 return fd;
629} 689}
@@ -655,7 +715,29 @@ perf_event__synth_time_conv(const struct perf_event_mmap_page *pc __maybe_unused
655 return 0; 715 return 0;
656} 716}
657 717
658static int record__synthesize(struct record *rec) 718static const struct perf_event_mmap_page *
719perf_evlist__pick_pc(struct perf_evlist *evlist)
720{
721 if (evlist) {
722 if (evlist->mmap && evlist->mmap[0].base)
723 return evlist->mmap[0].base;
724 if (evlist->backward_mmap && evlist->backward_mmap[0].base)
725 return evlist->backward_mmap[0].base;
726 }
727 return NULL;
728}
729
730static const struct perf_event_mmap_page *record__pick_pc(struct record *rec)
731{
732 const struct perf_event_mmap_page *pc;
733
734 pc = perf_evlist__pick_pc(rec->evlist);
735 if (pc)
736 return pc;
737 return NULL;
738}
739
740static int record__synthesize(struct record *rec, bool tail)
659{ 741{
660 struct perf_session *session = rec->session; 742 struct perf_session *session = rec->session;
661 struct machine *machine = &session->machines.host; 743 struct machine *machine = &session->machines.host;
@@ -665,6 +747,9 @@ static int record__synthesize(struct record *rec)
665 int fd = perf_data_file__fd(file); 747 int fd = perf_data_file__fd(file);
666 int err = 0; 748 int err = 0;
667 749
750 if (rec->opts.tail_synthesize != tail)
751 return 0;
752
668 if (file->is_pipe) { 753 if (file->is_pipe) {
669 err = perf_event__synthesize_attrs(tool, session, 754 err = perf_event__synthesize_attrs(tool, session,
670 process_synthesized_event); 755 process_synthesized_event);
@@ -692,7 +777,7 @@ static int record__synthesize(struct record *rec)
692 } 777 }
693 } 778 }
694 779
695 err = perf_event__synth_time_conv(rec->evlist->mmap[0].base, tool, 780 err = perf_event__synth_time_conv(record__pick_pc(rec), tool,
696 process_synthesized_event, machine); 781 process_synthesized_event, machine);
697 if (err) 782 if (err)
698 goto out; 783 goto out;
@@ -828,7 +913,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
828 913
829 machine = &session->machines.host; 914 machine = &session->machines.host;
830 915
831 err = record__synthesize(rec); 916 err = record__synthesize(rec, false);
832 if (err < 0) 917 if (err < 0)
833 goto out_child; 918 goto out_child;
834 919
@@ -879,7 +964,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
879 } 964 }
880 965
881 if (opts->initial_delay) { 966 if (opts->initial_delay) {
882 usleep(opts->initial_delay * 1000); 967 usleep(opts->initial_delay * USEC_PER_MSEC);
883 perf_evlist__enable(rec->evlist); 968 perf_evlist__enable(rec->evlist);
884 } 969 }
885 970
@@ -888,6 +973,17 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
888 for (;;) { 973 for (;;) {
889 unsigned long long hits = rec->samples; 974 unsigned long long hits = rec->samples;
890 975
976 /*
977 * rec->evlist->bkw_mmap_state is possible to be
978 * BKW_MMAP_EMPTY here: when done == true and
979 * hits != rec->samples in previous round.
980 *
981 * perf_evlist__toggle_bkw_mmap ensure we never
982 * convert BKW_MMAP_EMPTY to BKW_MMAP_DATA_PENDING.
983 */
984 if (trigger_is_hit(&switch_output_trigger) || done || draining)
985 perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_DATA_PENDING);
986
891 if (record__mmap_read_all(rec) < 0) { 987 if (record__mmap_read_all(rec) < 0) {
892 trigger_error(&auxtrace_snapshot_trigger); 988 trigger_error(&auxtrace_snapshot_trigger);
893 trigger_error(&switch_output_trigger); 989 trigger_error(&switch_output_trigger);
@@ -907,8 +1003,26 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
907 } 1003 }
908 1004
909 if (trigger_is_hit(&switch_output_trigger)) { 1005 if (trigger_is_hit(&switch_output_trigger)) {
1006 /*
1007 * If switch_output_trigger is hit, the data in
1008 * overwritable ring buffer should have been collected,
1009 * so bkw_mmap_state should be set to BKW_MMAP_EMPTY.
1010 *
1011 * If SIGUSR2 raise after or during record__mmap_read_all(),
1012 * record__mmap_read_all() didn't collect data from
1013 * overwritable ring buffer. Read again.
1014 */
1015 if (rec->evlist->bkw_mmap_state == BKW_MMAP_RUNNING)
1016 continue;
910 trigger_ready(&switch_output_trigger); 1017 trigger_ready(&switch_output_trigger);
911 1018
1019 /*
1020 * Reenable events in overwrite ring buffer after
1021 * record__mmap_read_all(): we should have collected
1022 * data from it.
1023 */
1024 perf_evlist__toggle_bkw_mmap(rec->evlist, BKW_MMAP_RUNNING);
1025
912 if (!quiet) 1026 if (!quiet)
913 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n", 1027 fprintf(stderr, "[ perf record: dump data: Woken up %ld times ]\n",
914 waking); 1028 waking);
@@ -954,7 +1068,7 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
954 1068
955 if (forks && workload_exec_errno) { 1069 if (forks && workload_exec_errno) {
956 char msg[STRERR_BUFSIZE]; 1070 char msg[STRERR_BUFSIZE];
957 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 1071 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
958 pr_err("Workload failed: %s\n", emsg); 1072 pr_err("Workload failed: %s\n", emsg);
959 err = -1; 1073 err = -1;
960 goto out_child; 1074 goto out_child;
@@ -963,6 +1077,9 @@ static int __cmd_record(struct record *rec, int argc, const char **argv)
963 if (!quiet) 1077 if (!quiet)
964 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking); 1078 fprintf(stderr, "[ perf record: Woken up %ld times to write data ]\n", waking);
965 1079
1080 if (target__none(&rec->opts.target))
1081 record__synthesize_workload(rec, true);
1082
966out_child: 1083out_child:
967 if (forks) { 1084 if (forks) {
968 int exit_status; 1085 int exit_status;
@@ -981,6 +1098,7 @@ out_child:
981 } else 1098 } else
982 status = err; 1099 status = err;
983 1100
1101 record__synthesize(rec, true);
984 /* this will be recalculated during process_buildids() */ 1102 /* this will be recalculated during process_buildids() */
985 rec->samples = 0; 1103 rec->samples = 0;
986 1104
@@ -1267,6 +1385,8 @@ static struct record record = {
1267const char record_callchain_help[] = CALLCHAIN_RECORD_HELP 1385const char record_callchain_help[] = CALLCHAIN_RECORD_HELP
1268 "\n\t\t\t\tDefault: fp"; 1386 "\n\t\t\t\tDefault: fp";
1269 1387
1388static bool dry_run;
1389
1270/* 1390/*
1271 * XXX Will stay a global variable till we fix builtin-script.c to stop messing 1391 * XXX Will stay a global variable till we fix builtin-script.c to stop messing
1272 * with it and switch to use the library functions in perf_evlist that came 1392 * with it and switch to use the library functions in perf_evlist that came
@@ -1303,6 +1423,9 @@ struct option __record_options[] = {
1303 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit, 1423 OPT_BOOLEAN_SET('i', "no-inherit", &record.opts.no_inherit,
1304 &record.opts.no_inherit_set, 1424 &record.opts.no_inherit_set,
1305 "child tasks do not inherit counters"), 1425 "child tasks do not inherit counters"),
1426 OPT_BOOLEAN(0, "tail-synthesize", &record.opts.tail_synthesize,
1427 "synthesize non-sample events at the end of output"),
1428 OPT_BOOLEAN(0, "overwrite", &record.opts.overwrite, "use overwrite mode"),
1306 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"), 1429 OPT_UINTEGER('F', "freq", &record.opts.user_freq, "profile at this frequency"),
1307 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]", 1430 OPT_CALLBACK('m', "mmap-pages", &record.opts, "pages[,pages]",
1308 "number of mmap data pages and AUX area tracing mmap pages", 1431 "number of mmap data pages and AUX area tracing mmap pages",
@@ -1321,6 +1444,7 @@ struct option __record_options[] = {
1321 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat, 1444 OPT_BOOLEAN('s', "stat", &record.opts.inherit_stat,
1322 "per thread counts"), 1445 "per thread counts"),
1323 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"), 1446 OPT_BOOLEAN('d', "data", &record.opts.sample_address, "Record the sample addresses"),
1447 OPT_BOOLEAN(0, "sample-cpu", &record.opts.sample_cpu, "Record the sample cpu"),
1324 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time, 1448 OPT_BOOLEAN_SET('T', "timestamp", &record.opts.sample_time,
1325 &record.opts.sample_time_set, 1449 &record.opts.sample_time_set,
1326 "Record the sample timestamps"), 1450 "Record the sample timestamps"),
@@ -1386,6 +1510,8 @@ struct option __record_options[] = {
1386 "append timestamp to output filename"), 1510 "append timestamp to output filename"),
1387 OPT_BOOLEAN(0, "switch-output", &record.switch_output, 1511 OPT_BOOLEAN(0, "switch-output", &record.switch_output,
1388 "Switch output when receive SIGUSR2"), 1512 "Switch output when receive SIGUSR2"),
1513 OPT_BOOLEAN(0, "dry-run", &dry_run,
1514 "Parse options then exit"),
1389 OPT_END() 1515 OPT_END()
1390}; 1516};
1391 1517
@@ -1447,26 +1573,39 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1447 if (!rec->itr) { 1573 if (!rec->itr) {
1448 rec->itr = auxtrace_record__init(rec->evlist, &err); 1574 rec->itr = auxtrace_record__init(rec->evlist, &err);
1449 if (err) 1575 if (err)
1450 return err; 1576 goto out;
1451 } 1577 }
1452 1578
1453 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts, 1579 err = auxtrace_parse_snapshot_options(rec->itr, &rec->opts,
1454 rec->opts.auxtrace_snapshot_opts); 1580 rec->opts.auxtrace_snapshot_opts);
1455 if (err) 1581 if (err)
1456 return err; 1582 goto out;
1583
1584 /*
1585 * Allow aliases to facilitate the lookup of symbols for address
1586 * filters. Refer to auxtrace_parse_filters().
1587 */
1588 symbol_conf.allow_aliases = true;
1589
1590 symbol__init(NULL);
1591
1592 err = auxtrace_parse_filters(rec->evlist);
1593 if (err)
1594 goto out;
1595
1596 if (dry_run)
1597 goto out;
1457 1598
1458 err = bpf__setup_stdout(rec->evlist); 1599 err = bpf__setup_stdout(rec->evlist);
1459 if (err) { 1600 if (err) {
1460 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf)); 1601 bpf__strerror_setup_stdout(rec->evlist, err, errbuf, sizeof(errbuf));
1461 pr_err("ERROR: Setup BPF stdout failed: %s\n", 1602 pr_err("ERROR: Setup BPF stdout failed: %s\n",
1462 errbuf); 1603 errbuf);
1463 return err; 1604 goto out;
1464 } 1605 }
1465 1606
1466 err = -ENOMEM; 1607 err = -ENOMEM;
1467 1608
1468 symbol__init(NULL);
1469
1470 if (symbol_conf.kptr_restrict) 1609 if (symbol_conf.kptr_restrict)
1471 pr_warning( 1610 pr_warning(
1472"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n" 1611"WARNING: Kernel address maps (/proc/{kallsyms,modules}) are restricted,\n"
@@ -1508,10 +1647,13 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1508 } 1647 }
1509 } 1648 }
1510 1649
1650 if (record.opts.overwrite)
1651 record.opts.tail_synthesize = true;
1652
1511 if (rec->evlist->nr_entries == 0 && 1653 if (rec->evlist->nr_entries == 0 &&
1512 perf_evlist__add_default(rec->evlist) < 0) { 1654 perf_evlist__add_default(rec->evlist) < 0) {
1513 pr_err("Not enough memory for event selector list\n"); 1655 pr_err("Not enough memory for event selector list\n");
1514 goto out_symbol_exit; 1656 goto out;
1515 } 1657 }
1516 1658
1517 if (rec->opts.target.tid && !rec->opts.no_inherit_set) 1659 if (rec->opts.target.tid && !rec->opts.no_inherit_set)
@@ -1531,7 +1673,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1531 ui__error("%s", errbuf); 1673 ui__error("%s", errbuf);
1532 1674
1533 err = -saved_errno; 1675 err = -saved_errno;
1534 goto out_symbol_exit; 1676 goto out;
1535 } 1677 }
1536 1678
1537 err = -ENOMEM; 1679 err = -ENOMEM;
@@ -1540,7 +1682,7 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1540 1682
1541 err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts); 1683 err = auxtrace_record__options(rec->itr, rec->evlist, &rec->opts);
1542 if (err) 1684 if (err)
1543 goto out_symbol_exit; 1685 goto out;
1544 1686
1545 /* 1687 /*
1546 * We take all buildids when the file contains 1688 * We take all buildids when the file contains
@@ -1552,11 +1694,11 @@ int cmd_record(int argc, const char **argv, const char *prefix __maybe_unused)
1552 1694
1553 if (record_opts__config(&rec->opts)) { 1695 if (record_opts__config(&rec->opts)) {
1554 err = -EINVAL; 1696 err = -EINVAL;
1555 goto out_symbol_exit; 1697 goto out;
1556 } 1698 }
1557 1699
1558 err = __cmd_record(&record, argc, argv); 1700 err = __cmd_record(&record, argc, argv);
1559out_symbol_exit: 1701out:
1560 perf_evlist__delete(rec->evlist); 1702 perf_evlist__delete(rec->evlist);
1561 symbol__exit(); 1703 symbol__exit();
1562 auxtrace_record__free(rec->itr); 1704 auxtrace_record__free(rec->itr);
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index a87cb338bdf1..6e88460cd13d 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"
@@ -89,6 +89,10 @@ static int report__config(const char *var, const char *value, void *cb)
89 rep->queue_size = perf_config_u64(var, value); 89 rep->queue_size = perf_config_u64(var, value);
90 return 0; 90 return 0;
91 } 91 }
92 if (!strcmp(var, "report.sort_order")) {
93 default_sort_order = strdup(value);
94 return 0;
95 }
92 96
93 return 0; 97 return 0;
94} 98}
@@ -361,7 +365,7 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
361 struct perf_evsel *pos; 365 struct perf_evsel *pos;
362 366
363 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples); 367 fprintf(stdout, "#\n# Total Lost Samples: %" PRIu64 "\n#\n", evlist->stats.total_lost_samples);
364 evlist__for_each(evlist, pos) { 368 evlist__for_each_entry(evlist, pos) {
365 struct hists *hists = evsel__hists(pos); 369 struct hists *hists = evsel__hists(pos);
366 const char *evname = perf_evsel__name(pos); 370 const char *evname = perf_evsel__name(pos);
367 371
@@ -370,7 +374,8 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
370 continue; 374 continue;
371 375
372 hists__fprintf_nr_sample_events(hists, rep, evname, stdout); 376 hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
373 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout); 377 hists__fprintf(hists, true, 0, 0, rep->min_percent, stdout,
378 symbol_conf.use_callchain);
374 fprintf(stdout, "\n\n"); 379 fprintf(stdout, "\n\n");
375 } 380 }
376 381
@@ -477,7 +482,7 @@ static int report__collapse_hists(struct report *rep)
477 482
478 ui_progress__init(&prog, rep->nr_entries, "Merging related events..."); 483 ui_progress__init(&prog, rep->nr_entries, "Merging related events...");
479 484
480 evlist__for_each(rep->session->evlist, pos) { 485 evlist__for_each_entry(rep->session->evlist, pos) {
481 struct hists *hists = evsel__hists(pos); 486 struct hists *hists = evsel__hists(pos);
482 487
483 if (pos->idx == 0) 488 if (pos->idx == 0)
@@ -510,7 +515,7 @@ static void report__output_resort(struct report *rep)
510 515
511 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output..."); 516 ui_progress__init(&prog, rep->nr_entries, "Sorting events for output...");
512 517
513 evlist__for_each(rep->session->evlist, pos) 518 evlist__for_each_entry(rep->session->evlist, pos)
514 perf_evsel__output_resort(pos, &prog); 519 perf_evsel__output_resort(pos, &prog);
515 520
516 ui_progress__finish(); 521 ui_progress__finish();
@@ -551,7 +556,7 @@ static int __cmd_report(struct report *rep)
551 556
552 report__warn_kptr_restrict(rep); 557 report__warn_kptr_restrict(rep);
553 558
554 evlist__for_each(session->evlist, pos) 559 evlist__for_each_entry(session->evlist, pos)
555 rep->nr_entries += evsel__hists(pos)->nr_entries; 560 rep->nr_entries += evsel__hists(pos)->nr_entries;
556 561
557 if (use_browser == 0) { 562 if (use_browser == 0) {
@@ -582,7 +587,7 @@ static int __cmd_report(struct report *rep)
582 * might be changed during the collapse phase. 587 * might be changed during the collapse phase.
583 */ 588 */
584 rep->nr_entries = 0; 589 rep->nr_entries = 0;
585 evlist__for_each(session->evlist, pos) 590 evlist__for_each_entry(session->evlist, pos)
586 rep->nr_entries += evsel__hists(pos)->nr_entries; 591 rep->nr_entries += evsel__hists(pos)->nr_entries;
587 592
588 if (rep->nr_entries == 0) { 593 if (rep->nr_entries == 0) {
@@ -816,6 +821,9 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused)
816 "Show raw trace event output (do not use print fmt or plugins)"), 821 "Show raw trace event output (do not use print fmt or plugins)"),
817 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy, 822 OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
818 "Show entries in a hierarchy"), 823 "Show entries in a hierarchy"),
824 OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
825 "'always' (default), 'never' or 'auto' only applicable to --stdio mode",
826 stdio__config_color, "always"),
819 OPT_END() 827 OPT_END()
820 }; 828 };
821 struct perf_data_file file = { 829 struct perf_data_file file = {
@@ -927,7 +935,6 @@ repeat:
927 935
928 if (symbol_conf.report_hierarchy) { 936 if (symbol_conf.report_hierarchy) {
929 /* disable incompatible options */ 937 /* disable incompatible options */
930 symbol_conf.event_group = false;
931 symbol_conf.cumulate_callchain = false; 938 symbol_conf.cumulate_callchain = false;
932 939
933 if (field_order) { 940 if (field_order) {
@@ -976,9 +983,9 @@ repeat:
976 * implementation. 983 * implementation.
977 */ 984 */
978 if (ui__has_annotation()) { 985 if (ui__has_annotation()) {
979 symbol_conf.priv_size = sizeof(struct annotation); 986 ret = symbol__annotation_init();
980 machines__set_symbol_filter(&session->machines, 987 if (ret < 0)
981 symbol__annotate_init); 988 goto error;
982 /* 989 /*
983 * For searching by name on the "Browse map details". 990 * For searching by name on the "Browse map details".
984 * providing it only in verbose mode not to bloat too 991 * providing it only in verbose mode not to bloat too
diff --git a/tools/perf/builtin-sched.c b/tools/perf/builtin-sched.c
index afa057666c2a..f5503ca22e1c 100644
--- a/tools/perf/builtin-sched.c
+++ b/tools/perf/builtin-sched.c
@@ -26,6 +26,7 @@
26#include <pthread.h> 26#include <pthread.h>
27#include <math.h> 27#include <math.h>
28#include <api/fs/fs.h> 28#include <api/fs/fs.h>
29#include <linux/time64.h>
29 30
30#define PR_SET_NAME 15 /* Set process name */ 31#define PR_SET_NAME 15 /* Set process name */
31#define MAX_CPUS 4096 32#define MAX_CPUS 4096
@@ -199,7 +200,7 @@ static u64 get_nsecs(void)
199 200
200 clock_gettime(CLOCK_MONOTONIC, &ts); 201 clock_gettime(CLOCK_MONOTONIC, &ts);
201 202
202 return ts.tv_sec * 1000000000ULL + ts.tv_nsec; 203 return ts.tv_sec * NSEC_PER_SEC + ts.tv_nsec;
203} 204}
204 205
205static void burn_nsecs(struct perf_sched *sched, u64 nsecs) 206static void burn_nsecs(struct perf_sched *sched, u64 nsecs)
@@ -223,7 +224,7 @@ static void sleep_nsecs(u64 nsecs)
223 224
224static void calibrate_run_measurement_overhead(struct perf_sched *sched) 225static void calibrate_run_measurement_overhead(struct perf_sched *sched)
225{ 226{
226 u64 T0, T1, delta, min_delta = 1000000000ULL; 227 u64 T0, T1, delta, min_delta = NSEC_PER_SEC;
227 int i; 228 int i;
228 229
229 for (i = 0; i < 10; i++) { 230 for (i = 0; i < 10; i++) {
@@ -240,7 +241,7 @@ static void calibrate_run_measurement_overhead(struct perf_sched *sched)
240 241
241static void calibrate_sleep_measurement_overhead(struct perf_sched *sched) 242static void calibrate_sleep_measurement_overhead(struct perf_sched *sched)
242{ 243{
243 u64 T0, T1, delta, min_delta = 1000000000ULL; 244 u64 T0, T1, delta, min_delta = NSEC_PER_SEC;
244 int i; 245 int i;
245 246
246 for (i = 0; i < 10; i++) { 247 for (i = 0; i < 10; i++) {
@@ -452,8 +453,8 @@ static u64 get_cpu_usage_nsec_parent(void)
452 err = getrusage(RUSAGE_SELF, &ru); 453 err = getrusage(RUSAGE_SELF, &ru);
453 BUG_ON(err); 454 BUG_ON(err);
454 455
455 sum = ru.ru_utime.tv_sec*1e9 + ru.ru_utime.tv_usec*1e3; 456 sum = ru.ru_utime.tv_sec * NSEC_PER_SEC + ru.ru_utime.tv_usec * NSEC_PER_USEC;
456 sum += ru.ru_stime.tv_sec*1e9 + ru.ru_stime.tv_usec*1e3; 457 sum += ru.ru_stime.tv_sec * NSEC_PER_SEC + ru.ru_stime.tv_usec * NSEC_PER_USEC;
457 458
458 return sum; 459 return sum;
459} 460}
@@ -494,7 +495,7 @@ force_again:
494 } 495 }
495 pr_err("Error: sys_perf_event_open() syscall returned " 496 pr_err("Error: sys_perf_event_open() syscall returned "
496 "with %d (%s)\n%s", fd, 497 "with %d (%s)\n%s", fd,
497 strerror_r(errno, sbuf, sizeof(sbuf)), info); 498 str_error_r(errno, sbuf, sizeof(sbuf)), info);
498 exit(EXIT_FAILURE); 499 exit(EXIT_FAILURE);
499 } 500 }
500 return fd; 501 return fd;
@@ -667,12 +668,12 @@ static void run_one_test(struct perf_sched *sched)
667 sched->run_avg = delta; 668 sched->run_avg = delta;
668 sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat; 669 sched->run_avg = (sched->run_avg * (sched->replay_repeat - 1) + delta) / sched->replay_repeat;
669 670
670 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / 1000000.0); 671 printf("#%-3ld: %0.3f, ", sched->nr_runs, (double)delta / NSEC_PER_MSEC);
671 672
672 printf("ravg: %0.2f, ", (double)sched->run_avg / 1e6); 673 printf("ravg: %0.2f, ", (double)sched->run_avg / NSEC_PER_MSEC);
673 674
674 printf("cpu: %0.2f / %0.2f", 675 printf("cpu: %0.2f / %0.2f",
675 (double)sched->cpu_usage / 1e6, (double)sched->runavg_cpu_usage / 1e6); 676 (double)sched->cpu_usage / NSEC_PER_MSEC, (double)sched->runavg_cpu_usage / NSEC_PER_MSEC);
676 677
677#if 0 678#if 0
678 /* 679 /*
@@ -680,8 +681,8 @@ static void run_one_test(struct perf_sched *sched)
680 * accurate than the sched->sum_exec_runtime based statistics: 681 * accurate than the sched->sum_exec_runtime based statistics:
681 */ 682 */
682 printf(" [%0.2f / %0.2f]", 683 printf(" [%0.2f / %0.2f]",
683 (double)sched->parent_cpu_usage/1e6, 684 (double)sched->parent_cpu_usage / NSEC_PER_MSEC,
684 (double)sched->runavg_parent_cpu_usage/1e6); 685 (double)sched->runavg_parent_cpu_usage / NSEC_PER_MSEC);
685#endif 686#endif
686 687
687 printf("\n"); 688 printf("\n");
@@ -696,13 +697,13 @@ static void test_calibrations(struct perf_sched *sched)
696 u64 T0, T1; 697 u64 T0, T1;
697 698
698 T0 = get_nsecs(); 699 T0 = get_nsecs();
699 burn_nsecs(sched, 1e6); 700 burn_nsecs(sched, NSEC_PER_MSEC);
700 T1 = get_nsecs(); 701 T1 = get_nsecs();
701 702
702 printf("the run test took %" PRIu64 " nsecs\n", T1 - T0); 703 printf("the run test took %" PRIu64 " nsecs\n", T1 - T0);
703 704
704 T0 = get_nsecs(); 705 T0 = get_nsecs();
705 sleep_nsecs(1e6); 706 sleep_nsecs(NSEC_PER_MSEC);
706 T1 = get_nsecs(); 707 T1 = get_nsecs();
707 708
708 printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0); 709 printf("the sleep test took %" PRIu64 " nsecs\n", T1 - T0);
@@ -1213,10 +1214,10 @@ static void output_lat_thread(struct perf_sched *sched, struct work_atoms *work_
1213 avg = work_list->total_lat / work_list->nb_atoms; 1214 avg = work_list->total_lat / work_list->nb_atoms;
1214 1215
1215 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13.6f s\n", 1216 printf("|%11.3f ms |%9" PRIu64 " | avg:%9.3f ms | max:%9.3f ms | max at: %13.6f s\n",
1216 (double)work_list->total_runtime / 1e6, 1217 (double)work_list->total_runtime / NSEC_PER_MSEC,
1217 work_list->nb_atoms, (double)avg / 1e6, 1218 work_list->nb_atoms, (double)avg / NSEC_PER_MSEC,
1218 (double)work_list->max_lat / 1e6, 1219 (double)work_list->max_lat / NSEC_PER_MSEC,
1219 (double)work_list->max_lat_at / 1e9); 1220 (double)work_list->max_lat_at / NSEC_PER_SEC);
1220} 1221}
1221 1222
1222static int pid_cmp(struct work_atoms *l, struct work_atoms *r) 1223static int pid_cmp(struct work_atoms *l, struct work_atoms *r)
@@ -1491,7 +1492,7 @@ static int map_switch_event(struct perf_sched *sched, struct perf_evsel *evsel,
1491 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu)) 1492 if (sched->map.cpus && !cpu_map__has(sched->map.cpus, this_cpu))
1492 goto out; 1493 goto out;
1493 1494
1494 color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp/1e9); 1495 color_fprintf(stdout, color, " %12.6f secs ", (double)timestamp / NSEC_PER_SEC);
1495 if (new_shortname) { 1496 if (new_shortname) {
1496 const char *pid_color = color; 1497 const char *pid_color = color;
1497 1498
@@ -1753,7 +1754,7 @@ static int perf_sched__lat(struct perf_sched *sched)
1753 1754
1754 printf(" -----------------------------------------------------------------------------------------------------------------\n"); 1755 printf(" -----------------------------------------------------------------------------------------------------------------\n");
1755 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n", 1756 printf(" TOTAL: |%11.3f ms |%9" PRIu64 " |\n",
1756 (double)sched->all_runtime / 1e6, sched->all_count); 1757 (double)sched->all_runtime / NSEC_PER_MSEC, sched->all_count);
1757 1758
1758 printf(" ---------------------------------------------------\n"); 1759 printf(" ---------------------------------------------------\n");
1759 1760
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index e3ce2f34d3ad..7228d141a789 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -21,8 +21,10 @@
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>
25#include <linux/stringify.h> 26#include <linux/stringify.h>
27#include <linux/time64.h>
26#include "asm/bug.h" 28#include "asm/bug.h"
27#include "util/mem-events.h" 29#include "util/mem-events.h"
28 30
@@ -63,6 +65,7 @@ enum perf_output_field {
63 PERF_OUTPUT_DATA_SRC = 1U << 17, 65 PERF_OUTPUT_DATA_SRC = 1U << 17,
64 PERF_OUTPUT_WEIGHT = 1U << 18, 66 PERF_OUTPUT_WEIGHT = 1U << 18,
65 PERF_OUTPUT_BPF_OUTPUT = 1U << 19, 67 PERF_OUTPUT_BPF_OUTPUT = 1U << 19,
68 PERF_OUTPUT_CALLINDENT = 1U << 20,
66}; 69};
67 70
68struct output_option { 71struct output_option {
@@ -89,6 +92,7 @@ struct output_option {
89 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC}, 92 {.str = "data_src", .field = PERF_OUTPUT_DATA_SRC},
90 {.str = "weight", .field = PERF_OUTPUT_WEIGHT}, 93 {.str = "weight", .field = PERF_OUTPUT_WEIGHT},
91 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT}, 94 {.str = "bpf-output", .field = PERF_OUTPUT_BPF_OUTPUT},
95 {.str = "callindent", .field = PERF_OUTPUT_CALLINDENT},
92}; 96};
93 97
94/* default set to maintain compatibility with current format */ 98/* default set to maintain compatibility with current format */
@@ -339,7 +343,7 @@ static void set_print_ip_opts(struct perf_event_attr *attr)
339 */ 343 */
340static int perf_session__check_output_opt(struct perf_session *session) 344static int perf_session__check_output_opt(struct perf_session *session)
341{ 345{
342 int j; 346 unsigned int j;
343 struct perf_evsel *evsel; 347 struct perf_evsel *evsel;
344 348
345 for (j = 0; j < PERF_TYPE_MAX; ++j) { 349 for (j = 0; j < PERF_TYPE_MAX; ++j) {
@@ -368,14 +372,16 @@ static int perf_session__check_output_opt(struct perf_session *session)
368 372
369 if (!no_callchain) { 373 if (!no_callchain) {
370 bool use_callchain = false; 374 bool use_callchain = false;
375 bool not_pipe = false;
371 376
372 evlist__for_each(session->evlist, evsel) { 377 evlist__for_each_entry(session->evlist, evsel) {
378 not_pipe = true;
373 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) { 379 if (evsel->attr.sample_type & PERF_SAMPLE_CALLCHAIN) {
374 use_callchain = true; 380 use_callchain = true;
375 break; 381 break;
376 } 382 }
377 } 383 }
378 if (!use_callchain) 384 if (not_pipe && !use_callchain)
379 symbol_conf.use_callchain = false; 385 symbol_conf.use_callchain = false;
380 } 386 }
381 387
@@ -388,17 +394,20 @@ static int perf_session__check_output_opt(struct perf_session *session)
388 struct perf_event_attr *attr; 394 struct perf_event_attr *attr;
389 395
390 j = PERF_TYPE_TRACEPOINT; 396 j = PERF_TYPE_TRACEPOINT;
391 evsel = perf_session__find_first_evtype(session, j);
392 if (evsel == NULL)
393 goto out;
394 397
395 attr = &evsel->attr; 398 evlist__for_each_entry(session->evlist, evsel) {
399 if (evsel->attr.type != j)
400 continue;
401
402 attr = &evsel->attr;
396 403
397 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) { 404 if (attr->sample_type & PERF_SAMPLE_CALLCHAIN) {
398 output[j].fields |= PERF_OUTPUT_IP; 405 output[j].fields |= PERF_OUTPUT_IP;
399 output[j].fields |= PERF_OUTPUT_SYM; 406 output[j].fields |= PERF_OUTPUT_SYM;
400 output[j].fields |= PERF_OUTPUT_DSO; 407 output[j].fields |= PERF_OUTPUT_DSO;
401 set_print_ip_opts(attr); 408 set_print_ip_opts(attr);
409 goto out;
410 }
402 } 411 }
403 } 412 }
404 413
@@ -456,9 +465,9 @@ static void print_sample_start(struct perf_sample *sample,
456 465
457 if (PRINT_FIELD(TIME)) { 466 if (PRINT_FIELD(TIME)) {
458 nsecs = sample->time; 467 nsecs = sample->time;
459 secs = nsecs / NSECS_PER_SEC; 468 secs = nsecs / NSEC_PER_SEC;
460 nsecs -= secs * NSECS_PER_SEC; 469 nsecs -= secs * NSEC_PER_SEC;
461 usecs = nsecs / NSECS_PER_USEC; 470 usecs = nsecs / NSEC_PER_USEC;
462 if (nanosecs) 471 if (nanosecs)
463 printf("%5lu.%09llu: ", secs, nsecs); 472 printf("%5lu.%09llu: ", secs, nsecs);
464 else 473 else
@@ -513,11 +522,11 @@ static void print_sample_brstacksym(struct perf_sample *sample,
513 522
514 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf); 523 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, from, &alf);
515 if (alf.map) 524 if (alf.map)
516 alf.sym = map__find_symbol(alf.map, alf.addr, NULL); 525 alf.sym = map__find_symbol(alf.map, alf.addr);
517 526
518 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt); 527 thread__find_addr_map(thread, sample->cpumode, MAP__FUNCTION, to, &alt);
519 if (alt.map) 528 if (alt.map)
520 alt.sym = map__find_symbol(alt.map, alt.addr, NULL); 529 alt.sym = map__find_symbol(alt.map, alt.addr);
521 530
522 symbol__fprintf_symname_offs(alf.sym, &alf, stdout); 531 symbol__fprintf_symname_offs(alf.sym, &alf, stdout);
523 putchar('/'); 532 putchar('/');
@@ -559,6 +568,62 @@ static void print_sample_addr(struct perf_sample *sample,
559 } 568 }
560} 569}
561 570
571static void print_sample_callindent(struct perf_sample *sample,
572 struct perf_evsel *evsel,
573 struct thread *thread,
574 struct addr_location *al)
575{
576 struct perf_event_attr *attr = &evsel->attr;
577 size_t depth = thread_stack__depth(thread);
578 struct addr_location addr_al;
579 const char *name = NULL;
580 static int spacing;
581 int len = 0;
582 u64 ip = 0;
583
584 /*
585 * The 'return' has already been popped off the stack so the depth has
586 * to be adjusted to match the 'call'.
587 */
588 if (thread->ts && sample->flags & PERF_IP_FLAG_RETURN)
589 depth += 1;
590
591 if (sample->flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN)) {
592 if (sample_addr_correlates_sym(attr)) {
593 thread__resolve(thread, &addr_al, sample);
594 if (addr_al.sym)
595 name = addr_al.sym->name;
596 else
597 ip = sample->addr;
598 } else {
599 ip = sample->addr;
600 }
601 } else if (sample->flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END)) {
602 if (al->sym)
603 name = al->sym->name;
604 else
605 ip = sample->ip;
606 }
607
608 if (name)
609 len = printf("%*s%s", (int)depth * 4, "", name);
610 else if (ip)
611 len = printf("%*s%16" PRIx64, (int)depth * 4, "", ip);
612
613 if (len < 0)
614 return;
615
616 /*
617 * Try to keep the output length from changing frequently so that the
618 * output lines up more nicely.
619 */
620 if (len > spacing || (len && len < spacing - 52))
621 spacing = round_up(len + 4, 32);
622
623 if (len < spacing)
624 printf("%*s", spacing - len, "");
625}
626
562static void print_sample_bts(struct perf_sample *sample, 627static void print_sample_bts(struct perf_sample *sample,
563 struct perf_evsel *evsel, 628 struct perf_evsel *evsel,
564 struct thread *thread, 629 struct thread *thread,
@@ -567,6 +632,9 @@ static void print_sample_bts(struct perf_sample *sample,
567 struct perf_event_attr *attr = &evsel->attr; 632 struct perf_event_attr *attr = &evsel->attr;
568 bool print_srcline_last = false; 633 bool print_srcline_last = false;
569 634
635 if (PRINT_FIELD(CALLINDENT))
636 print_sample_callindent(sample, evsel, thread, al);
637
570 /* print branch_from information */ 638 /* print branch_from information */
571 if (PRINT_FIELD(IP)) { 639 if (PRINT_FIELD(IP)) {
572 unsigned int print_opts = output[attr->type].print_ip_opts; 640 unsigned int print_opts = output[attr->type].print_ip_opts;
@@ -603,13 +671,42 @@ static void print_sample_bts(struct perf_sample *sample,
603 printf("\n"); 671 printf("\n");
604} 672}
605 673
674static struct {
675 u32 flags;
676 const char *name;
677} sample_flags[] = {
678 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL, "call"},
679 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN, "return"},
680 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CONDITIONAL, "jcc"},
681 {PERF_IP_FLAG_BRANCH, "jmp"},
682 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_INTERRUPT, "int"},
683 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_INTERRUPT, "iret"},
684 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_SYSCALLRET, "syscall"},
685 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_RETURN | PERF_IP_FLAG_SYSCALLRET, "sysret"},
686 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_ASYNC, "async"},
687 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_CALL | PERF_IP_FLAG_ASYNC | PERF_IP_FLAG_INTERRUPT, "hw int"},
688 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TX_ABORT, "tx abrt"},
689 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_BEGIN, "tr strt"},
690 {PERF_IP_FLAG_BRANCH | PERF_IP_FLAG_TRACE_END, "tr end"},
691 {0, NULL}
692};
693
606static void print_sample_flags(u32 flags) 694static void print_sample_flags(u32 flags)
607{ 695{
608 const char *chars = PERF_IP_FLAG_CHARS; 696 const char *chars = PERF_IP_FLAG_CHARS;
609 const int n = strlen(PERF_IP_FLAG_CHARS); 697 const int n = strlen(PERF_IP_FLAG_CHARS);
698 bool in_tx = flags & PERF_IP_FLAG_IN_TX;
699 const char *name = NULL;
610 char str[33]; 700 char str[33];
611 int i, pos = 0; 701 int i, pos = 0;
612 702
703 for (i = 0; sample_flags[i].name ; i++) {
704 if (sample_flags[i].flags == (flags & ~PERF_IP_FLAG_IN_TX)) {
705 name = sample_flags[i].name;
706 break;
707 }
708 }
709
613 for (i = 0; i < n; i++, flags >>= 1) { 710 for (i = 0; i < n; i++, flags >>= 1) {
614 if (flags & 1) 711 if (flags & 1)
615 str[pos++] = chars[i]; 712 str[pos++] = chars[i];
@@ -619,7 +716,11 @@ static void print_sample_flags(u32 flags)
619 str[pos++] = '?'; 716 str[pos++] = '?';
620 } 717 }
621 str[pos] = 0; 718 str[pos] = 0;
622 printf(" %-4s ", str); 719
720 if (name)
721 printf(" %-7s%4s ", name, in_tx ? "(x)" : "");
722 else
723 printf(" %-11s ", str);
623} 724}
624 725
625struct printer_data { 726struct printer_data {
@@ -717,7 +818,7 @@ static int perf_evlist__max_name_len(struct perf_evlist *evlist)
717 struct perf_evsel *evsel; 818 struct perf_evsel *evsel;
718 int max = 0; 819 int max = 0;
719 820
720 evlist__for_each(evlist, evsel) { 821 evlist__for_each_entry(evlist, evsel) {
721 int len = strlen(perf_evsel__name(evsel)); 822 int len = strlen(perf_evsel__name(evsel));
722 823
723 max = MAX(len, max); 824 max = MAX(len, max);
@@ -942,7 +1043,7 @@ static int process_attr(struct perf_tool *tool, union perf_event *event,
942 if (evsel->attr.type >= PERF_TYPE_MAX) 1043 if (evsel->attr.type >= PERF_TYPE_MAX)
943 return 0; 1044 return 0;
944 1045
945 evlist__for_each(evlist, pos) { 1046 evlist__for_each_entry(evlist, pos) {
946 if (pos->attr.type == evsel->attr.type && pos != evsel) 1047 if (pos->attr.type == evsel->attr.type && pos != evsel)
947 return 0; 1048 return 0;
948 } 1049 }
@@ -1592,8 +1693,13 @@ static int list_available_scripts(const struct option *opt __maybe_unused,
1592 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path()); 1693 snprintf(scripts_path, MAXPATHLEN, "%s/scripts", get_argv_exec_path());
1593 1694
1594 scripts_dir = opendir(scripts_path); 1695 scripts_dir = opendir(scripts_path);
1595 if (!scripts_dir) 1696 if (!scripts_dir) {
1596 return -1; 1697 fprintf(stdout,
1698 "open(%s) failed.\n"
1699 "Check \"PERF_EXEC_PATH\" env to set scripts dir.\n",
1700 scripts_path);
1701 exit(-1);
1702 }
1597 1703
1598 for_each_lang(scripts_path, scripts_dir, lang_dirent) { 1704 for_each_lang(scripts_path, scripts_dir, lang_dirent) {
1599 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path, 1705 snprintf(lang_path, MAXPATHLEN, "%s/%s/bin", scripts_path,
@@ -1668,7 +1774,7 @@ static int check_ev_match(char *dir_name, char *scriptname,
1668 snprintf(evname, len + 1, "%s", p); 1774 snprintf(evname, len + 1, "%s", p);
1669 1775
1670 match = 0; 1776 match = 0;
1671 evlist__for_each(session->evlist, pos) { 1777 evlist__for_each_entry(session->evlist, pos) {
1672 if (!strcmp(perf_evsel__name(pos), evname)) { 1778 if (!strcmp(perf_evsel__name(pos), evname)) {
1673 match = 1; 1779 match = 1;
1674 break; 1780 break;
@@ -1870,7 +1976,7 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
1870 struct stat_round_event *round = &event->stat_round; 1976 struct stat_round_event *round = &event->stat_round;
1871 struct perf_evsel *counter; 1977 struct perf_evsel *counter;
1872 1978
1873 evlist__for_each(session->evlist, counter) { 1979 evlist__for_each_entry(session->evlist, counter) {
1874 perf_stat_process_counter(&stat_config, counter); 1980 perf_stat_process_counter(&stat_config, counter);
1875 process_stat(counter, round->time); 1981 process_stat(counter, round->time);
1876 } 1982 }
@@ -2017,7 +2123,8 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2017 "comma separated output fields prepend with 'type:'. " 2123 "comma separated output fields prepend with 'type:'. "
2018 "Valid types: hw,sw,trace,raw. " 2124 "Valid types: hw,sw,trace,raw. "
2019 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso," 2125 "Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,"
2020 "addr,symoff,period,iregs,brstack,brstacksym,flags", parse_output_fields), 2126 "addr,symoff,period,iregs,brstack,brstacksym,flags,"
2127 "bpf-output,callindent", parse_output_fields),
2021 OPT_BOOLEAN('a', "all-cpus", &system_wide, 2128 OPT_BOOLEAN('a', "all-cpus", &system_wide,
2022 "system-wide collection from all CPUs"), 2129 "system-wide collection from all CPUs"),
2023 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]", 2130 OPT_STRING('S', "symbols", &symbol_conf.sym_list_str, "symbol[,symbol...]",
@@ -2256,6 +2363,9 @@ int cmd_script(int argc, const char **argv, const char *prefix __maybe_unused)
2256 script.session = session; 2363 script.session = session;
2257 script__setup_sample_type(&script); 2364 script__setup_sample_type(&script);
2258 2365
2366 if (output[PERF_TYPE_HARDWARE].fields & PERF_OUTPUT_CALLINDENT)
2367 itrace_synth_opts.thread_stack = true;
2368
2259 session->itrace_synth_opts = &itrace_synth_opts; 2369 session->itrace_synth_opts = &itrace_synth_opts;
2260 2370
2261 if (cpu_list) { 2371 if (cpu_list) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index ee7ada78d86f..688dea7cb08f 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -52,6 +52,7 @@
52#include "util/evlist.h" 52#include "util/evlist.h"
53#include "util/evsel.h" 53#include "util/evsel.h"
54#include "util/debug.h" 54#include "util/debug.h"
55#include "util/drv_configs.h"
55#include "util/color.h" 56#include "util/color.h"
56#include "util/stat.h" 57#include "util/stat.h"
57#include "util/header.h" 58#include "util/header.h"
@@ -59,10 +60,14 @@
59#include "util/thread.h" 60#include "util/thread.h"
60#include "util/thread_map.h" 61#include "util/thread_map.h"
61#include "util/counts.h" 62#include "util/counts.h"
63#include "util/group.h"
62#include "util/session.h" 64#include "util/session.h"
63#include "util/tool.h" 65#include "util/tool.h"
66#include "util/group.h"
64#include "asm/bug.h" 67#include "asm/bug.h"
65 68
69#include <linux/time64.h>
70#include <api/fs/fs.h>
66#include <stdlib.h> 71#include <stdlib.h>
67#include <sys/prctl.h> 72#include <sys/prctl.h>
68#include <locale.h> 73#include <locale.h>
@@ -98,6 +103,15 @@ static const char * transaction_limited_attrs = {
98 "}" 103 "}"
99}; 104};
100 105
106static const char * topdown_attrs[] = {
107 "topdown-total-slots",
108 "topdown-slots-retired",
109 "topdown-recovery-bubbles",
110 "topdown-fetch-bubbles",
111 "topdown-slots-issued",
112 NULL,
113};
114
101static struct perf_evlist *evsel_list; 115static struct perf_evlist *evsel_list;
102 116
103static struct target target = { 117static struct target target = {
@@ -112,6 +126,7 @@ static volatile pid_t child_pid = -1;
112static bool null_run = false; 126static bool null_run = false;
113static int detailed_run = 0; 127static int detailed_run = 0;
114static bool transaction_run; 128static bool transaction_run;
129static bool topdown_run = false;
115static bool big_num = true; 130static bool big_num = true;
116static int big_num_opt = -1; 131static int big_num_opt = -1;
117static const char *csv_sep = NULL; 132static const char *csv_sep = NULL;
@@ -124,6 +139,7 @@ static unsigned int initial_delay = 0;
124static unsigned int unit_width = 4; /* strlen("unit") */ 139static unsigned int unit_width = 4; /* strlen("unit") */
125static bool forever = false; 140static bool forever = false;
126static bool metric_only = false; 141static bool metric_only = false;
142static bool force_metric_only = false;
127static struct timespec ref_time; 143static struct timespec ref_time;
128static struct cpu_map *aggr_map; 144static struct cpu_map *aggr_map;
129static aggr_get_id_t aggr_get_id; 145static aggr_get_id_t aggr_get_id;
@@ -158,7 +174,7 @@ static inline void diff_timespec(struct timespec *r, struct timespec *a,
158{ 174{
159 r->tv_sec = a->tv_sec - b->tv_sec; 175 r->tv_sec = a->tv_sec - b->tv_sec;
160 if (a->tv_nsec < b->tv_nsec) { 176 if (a->tv_nsec < b->tv_nsec) {
161 r->tv_nsec = a->tv_nsec + 1000000000L - b->tv_nsec; 177 r->tv_nsec = a->tv_nsec + NSEC_PER_SEC - b->tv_nsec;
162 r->tv_sec--; 178 r->tv_sec--;
163 } else { 179 } else {
164 r->tv_nsec = a->tv_nsec - b->tv_nsec ; 180 r->tv_nsec = a->tv_nsec - b->tv_nsec ;
@@ -276,8 +292,12 @@ perf_evsel__write_stat_event(struct perf_evsel *counter, u32 cpu, u32 thread,
276static int read_counter(struct perf_evsel *counter) 292static int read_counter(struct perf_evsel *counter)
277{ 293{
278 int nthreads = thread_map__nr(evsel_list->threads); 294 int nthreads = thread_map__nr(evsel_list->threads);
279 int ncpus = perf_evsel__nr_cpus(counter); 295 int ncpus, cpu, thread;
280 int cpu, thread; 296
297 if (target__has_cpu(&target))
298 ncpus = perf_evsel__nr_cpus(counter);
299 else
300 ncpus = 1;
281 301
282 if (!counter->supported) 302 if (!counter->supported)
283 return -ENOENT; 303 return -ENOENT;
@@ -313,21 +333,16 @@ static int read_counter(struct perf_evsel *counter)
313 return 0; 333 return 0;
314} 334}
315 335
316static void read_counters(bool close_counters) 336static void read_counters(void)
317{ 337{
318 struct perf_evsel *counter; 338 struct perf_evsel *counter;
319 339
320 evlist__for_each(evsel_list, counter) { 340 evlist__for_each_entry(evsel_list, counter) {
321 if (read_counter(counter)) 341 if (read_counter(counter))
322 pr_debug("failed to read counter %s\n", counter->name); 342 pr_debug("failed to read counter %s\n", counter->name);
323 343
324 if (perf_stat_process_counter(&stat_config, counter)) 344 if (perf_stat_process_counter(&stat_config, counter))
325 pr_warning("failed to process counter %s\n", counter->name); 345 pr_warning("failed to process counter %s\n", counter->name);
326
327 if (close_counters) {
328 perf_evsel__close_fd(counter, perf_evsel__nr_cpus(counter),
329 thread_map__nr(evsel_list->threads));
330 }
331 } 346 }
332} 347}
333 348
@@ -335,13 +350,13 @@ static void process_interval(void)
335{ 350{
336 struct timespec ts, rs; 351 struct timespec ts, rs;
337 352
338 read_counters(false); 353 read_counters();
339 354
340 clock_gettime(CLOCK_MONOTONIC, &ts); 355 clock_gettime(CLOCK_MONOTONIC, &ts);
341 diff_timespec(&rs, &ts, &ref_time); 356 diff_timespec(&rs, &ts, &ref_time);
342 357
343 if (STAT_RECORD) { 358 if (STAT_RECORD) {
344 if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSECS_PER_SEC + rs.tv_nsec, INTERVAL)) 359 if (WRITE_STAT_ROUND_EVENT(rs.tv_sec * NSEC_PER_SEC + rs.tv_nsec, INTERVAL))
345 pr_err("failed to write stat round event\n"); 360 pr_err("failed to write stat round event\n");
346 } 361 }
347 362
@@ -351,7 +366,7 @@ static void process_interval(void)
351static void enable_counters(void) 366static void enable_counters(void)
352{ 367{
353 if (initial_delay) 368 if (initial_delay)
354 usleep(initial_delay * 1000); 369 usleep(initial_delay * USEC_PER_MSEC);
355 370
356 /* 371 /*
357 * We need to enable counters only if: 372 * We need to enable counters only if:
@@ -362,6 +377,17 @@ static void enable_counters(void)
362 perf_evlist__enable(evsel_list); 377 perf_evlist__enable(evsel_list);
363} 378}
364 379
380static void disable_counters(void)
381{
382 /*
383 * If we don't have tracee (attaching to task or cpu), counters may
384 * still be running. To get accurate group ratios, we must stop groups
385 * from counting before reading their constituent counters.
386 */
387 if (!target__none(&target))
388 perf_evlist__disable(evsel_list);
389}
390
365static volatile int workload_exec_errno; 391static volatile int workload_exec_errno;
366 392
367/* 393/*
@@ -403,7 +429,7 @@ static int perf_stat_synthesize_config(bool is_pipe)
403 * Synthesize other events stuff not carried within 429 * Synthesize other events stuff not carried within
404 * attr event - unit, scale, name 430 * attr event - unit, scale, name
405 */ 431 */
406 evlist__for_each(evsel_list, counter) { 432 evlist__for_each_entry(evsel_list, counter) {
407 if (!counter->supported) 433 if (!counter->supported)
408 continue; 434 continue;
409 435
@@ -515,10 +541,11 @@ static int __run_perf_stat(int argc, const char **argv)
515 int status = 0; 541 int status = 0;
516 const bool forks = (argc > 0); 542 const bool forks = (argc > 0);
517 bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false; 543 bool is_pipe = STAT_RECORD ? perf_stat.file.is_pipe : false;
544 struct perf_evsel_config_term *err_term;
518 545
519 if (interval) { 546 if (interval) {
520 ts.tv_sec = interval / 1000; 547 ts.tv_sec = interval / USEC_PER_MSEC;
521 ts.tv_nsec = (interval % 1000) * 1000000; 548 ts.tv_nsec = (interval % USEC_PER_MSEC) * NSEC_PER_MSEC;
522 } else { 549 } else {
523 ts.tv_sec = 1; 550 ts.tv_sec = 1;
524 ts.tv_nsec = 0; 551 ts.tv_nsec = 0;
@@ -536,7 +563,7 @@ static int __run_perf_stat(int argc, const char **argv)
536 if (group) 563 if (group)
537 perf_evlist__set_leader(evsel_list); 564 perf_evlist__set_leader(evsel_list);
538 565
539 evlist__for_each(evsel_list, counter) { 566 evlist__for_each_entry(evsel_list, counter) {
540try_again: 567try_again:
541 if (create_perf_stat_counter(counter) < 0) { 568 if (create_perf_stat_counter(counter) < 0) {
542 /* 569 /*
@@ -582,7 +609,14 @@ try_again:
582 if (perf_evlist__apply_filters(evsel_list, &counter)) { 609 if (perf_evlist__apply_filters(evsel_list, &counter)) {
583 error("failed to set filter \"%s\" on event %s with %d (%s)\n", 610 error("failed to set filter \"%s\" on event %s with %d (%s)\n",
584 counter->filter, perf_evsel__name(counter), errno, 611 counter->filter, perf_evsel__name(counter), errno,
585 strerror_r(errno, msg, sizeof(msg))); 612 str_error_r(errno, msg, sizeof(msg)));
613 return -1;
614 }
615
616 if (perf_evlist__apply_drv_configs(evsel_list, &counter, &err_term)) {
617 error("failed to set config \"%s\" on event %s with %d (%s)\n",
618 err_term->val.drv_cfg, perf_evsel__name(counter), errno,
619 str_error_r(errno, msg, sizeof(msg)));
586 return -1; 620 return -1;
587 } 621 }
588 622
@@ -623,7 +657,7 @@ try_again:
623 wait(&status); 657 wait(&status);
624 658
625 if (workload_exec_errno) { 659 if (workload_exec_errno) {
626 const char *emsg = strerror_r(workload_exec_errno, msg, sizeof(msg)); 660 const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
627 pr_err("Workload failed: %s\n", emsg); 661 pr_err("Workload failed: %s\n", emsg);
628 return -1; 662 return -1;
629 } 663 }
@@ -639,11 +673,20 @@ try_again:
639 } 673 }
640 } 674 }
641 675
676 disable_counters();
677
642 t1 = rdclock(); 678 t1 = rdclock();
643 679
644 update_stats(&walltime_nsecs_stats, t1 - t0); 680 update_stats(&walltime_nsecs_stats, t1 - t0);
645 681
646 read_counters(true); 682 /*
683 * Closing a group leader splits the group, and as we only disable
684 * group leaders, results in remaining events becoming enabled. To
685 * avoid arbitrary skew, we must read all counters before closing any
686 * group leaders.
687 */
688 read_counters();
689 perf_evlist__close(evsel_list);
647 690
648 return WEXITSTATUS(status); 691 return WEXITSTATUS(status);
649} 692}
@@ -938,7 +981,7 @@ static void print_metric_header(void *ctx, const char *color __maybe_unused,
938static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg) 981static void nsec_printout(int id, int nr, struct perf_evsel *evsel, double avg)
939{ 982{
940 FILE *output = stat_config.output; 983 FILE *output = stat_config.output;
941 double msecs = avg / 1e6; 984 double msecs = avg / NSEC_PER_MSEC;
942 const char *fmt_v, *fmt_n; 985 const char *fmt_v, *fmt_n;
943 char name[25]; 986 char name[25];
944 987
@@ -1120,7 +1163,7 @@ static void aggr_update_shadow(void)
1120 1163
1121 for (s = 0; s < aggr_map->nr; s++) { 1164 for (s = 0; s < aggr_map->nr; s++) {
1122 id = aggr_map->map[s]; 1165 id = aggr_map->map[s];
1123 evlist__for_each(evsel_list, counter) { 1166 evlist__for_each_entry(evsel_list, counter) {
1124 val = 0; 1167 val = 0;
1125 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1168 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
1126 s2 = aggr_get_id(evsel_list->cpus, cpu); 1169 s2 = aggr_get_id(evsel_list->cpus, cpu);
@@ -1159,7 +1202,7 @@ static void print_aggr(char *prefix)
1159 1202
1160 id = aggr_map->map[s]; 1203 id = aggr_map->map[s];
1161 first = true; 1204 first = true;
1162 evlist__for_each(evsel_list, counter) { 1205 evlist__for_each_entry(evsel_list, counter) {
1163 val = ena = run = 0; 1206 val = ena = run = 0;
1164 nr = 0; 1207 nr = 0;
1165 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) { 1208 for (cpu = 0; cpu < perf_evsel__nr_cpus(counter); cpu++) {
@@ -1278,7 +1321,7 @@ static void print_no_aggr_metric(char *prefix)
1278 1321
1279 if (prefix) 1322 if (prefix)
1280 fputs(prefix, stat_config.output); 1323 fputs(prefix, stat_config.output);
1281 evlist__for_each(evsel_list, counter) { 1324 evlist__for_each_entry(evsel_list, counter) {
1282 if (first) { 1325 if (first) {
1283 aggr_printout(counter, cpu, 0); 1326 aggr_printout(counter, cpu, 0);
1284 first = false; 1327 first = false;
@@ -1302,7 +1345,15 @@ static int aggr_header_lens[] = {
1302 [AGGR_GLOBAL] = 0, 1345 [AGGR_GLOBAL] = 0,
1303}; 1346};
1304 1347
1305static void print_metric_headers(char *prefix) 1348static const char *aggr_header_csv[] = {
1349 [AGGR_CORE] = "core,cpus,",
1350 [AGGR_SOCKET] = "socket,cpus",
1351 [AGGR_NONE] = "cpu,",
1352 [AGGR_THREAD] = "comm-pid,",
1353 [AGGR_GLOBAL] = ""
1354};
1355
1356static void print_metric_headers(const char *prefix, bool no_indent)
1306{ 1357{
1307 struct perf_stat_output_ctx out; 1358 struct perf_stat_output_ctx out;
1308 struct perf_evsel *counter; 1359 struct perf_evsel *counter;
@@ -1313,12 +1364,18 @@ static void print_metric_headers(char *prefix)
1313 if (prefix) 1364 if (prefix)
1314 fprintf(stat_config.output, "%s", prefix); 1365 fprintf(stat_config.output, "%s", prefix);
1315 1366
1316 if (!csv_output) 1367 if (!csv_output && !no_indent)
1317 fprintf(stat_config.output, "%*s", 1368 fprintf(stat_config.output, "%*s",
1318 aggr_header_lens[stat_config.aggr_mode], ""); 1369 aggr_header_lens[stat_config.aggr_mode], "");
1370 if (csv_output) {
1371 if (stat_config.interval)
1372 fputs("time,", stat_config.output);
1373 fputs(aggr_header_csv[stat_config.aggr_mode],
1374 stat_config.output);
1375 }
1319 1376
1320 /* Print metrics headers only */ 1377 /* Print metrics headers only */
1321 evlist__for_each(evsel_list, counter) { 1378 evlist__for_each_entry(evsel_list, counter) {
1322 os.evsel = counter; 1379 os.evsel = counter;
1323 out.ctx = &os; 1380 out.ctx = &os;
1324 out.print_metric = print_metric_header; 1381 out.print_metric = print_metric_header;
@@ -1338,28 +1395,40 @@ static void print_interval(char *prefix, struct timespec *ts)
1338 1395
1339 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep); 1396 sprintf(prefix, "%6lu.%09lu%s", ts->tv_sec, ts->tv_nsec, csv_sep);
1340 1397
1341 if (num_print_interval == 0 && !csv_output && !metric_only) { 1398 if (num_print_interval == 0 && !csv_output) {
1342 switch (stat_config.aggr_mode) { 1399 switch (stat_config.aggr_mode) {
1343 case AGGR_SOCKET: 1400 case AGGR_SOCKET:
1344 fprintf(output, "# time socket cpus counts %*s events\n", unit_width, "unit"); 1401 fprintf(output, "# time socket cpus");
1402 if (!metric_only)
1403 fprintf(output, " counts %*s events\n", unit_width, "unit");
1345 break; 1404 break;
1346 case AGGR_CORE: 1405 case AGGR_CORE:
1347 fprintf(output, "# time core cpus counts %*s events\n", unit_width, "unit"); 1406 fprintf(output, "# time core cpus");
1407 if (!metric_only)
1408 fprintf(output, " counts %*s events\n", unit_width, "unit");
1348 break; 1409 break;
1349 case AGGR_NONE: 1410 case AGGR_NONE:
1350 fprintf(output, "# time CPU counts %*s events\n", unit_width, "unit"); 1411 fprintf(output, "# time CPU");
1412 if (!metric_only)
1413 fprintf(output, " counts %*s events\n", unit_width, "unit");
1351 break; 1414 break;
1352 case AGGR_THREAD: 1415 case AGGR_THREAD:
1353 fprintf(output, "# time comm-pid counts %*s events\n", unit_width, "unit"); 1416 fprintf(output, "# time comm-pid");
1417 if (!metric_only)
1418 fprintf(output, " counts %*s events\n", unit_width, "unit");
1354 break; 1419 break;
1355 case AGGR_GLOBAL: 1420 case AGGR_GLOBAL:
1356 default: 1421 default:
1357 fprintf(output, "# time counts %*s events\n", unit_width, "unit"); 1422 fprintf(output, "# time");
1423 if (!metric_only)
1424 fprintf(output, " counts %*s events\n", unit_width, "unit");
1358 case AGGR_UNSET: 1425 case AGGR_UNSET:
1359 break; 1426 break;
1360 } 1427 }
1361 } 1428 }
1362 1429
1430 if (num_print_interval == 0 && metric_only)
1431 print_metric_headers(" ", true);
1363 if (++num_print_interval == 25) 1432 if (++num_print_interval == 25)
1364 num_print_interval = 0; 1433 num_print_interval = 0;
1365} 1434}
@@ -1401,7 +1470,7 @@ static void print_footer(void)
1401 if (!null_run) 1470 if (!null_run)
1402 fprintf(output, "\n"); 1471 fprintf(output, "\n");
1403 fprintf(output, " %17.9f seconds time elapsed", 1472 fprintf(output, " %17.9f seconds time elapsed",
1404 avg_stats(&walltime_nsecs_stats)/1e9); 1473 avg_stats(&walltime_nsecs_stats) / NSEC_PER_SEC);
1405 if (run_count > 1) { 1474 if (run_count > 1) {
1406 fprintf(output, " "); 1475 fprintf(output, " ");
1407 print_noise_pct(stddev_stats(&walltime_nsecs_stats), 1476 print_noise_pct(stddev_stats(&walltime_nsecs_stats),
@@ -1428,8 +1497,8 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1428 if (metric_only) { 1497 if (metric_only) {
1429 static int num_print_iv; 1498 static int num_print_iv;
1430 1499
1431 if (num_print_iv == 0) 1500 if (num_print_iv == 0 && !interval)
1432 print_metric_headers(prefix); 1501 print_metric_headers(prefix, false);
1433 if (num_print_iv++ == 25) 1502 if (num_print_iv++ == 25)
1434 num_print_iv = 0; 1503 num_print_iv = 0;
1435 if (stat_config.aggr_mode == AGGR_GLOBAL && prefix) 1504 if (stat_config.aggr_mode == AGGR_GLOBAL && prefix)
@@ -1442,11 +1511,11 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1442 print_aggr(prefix); 1511 print_aggr(prefix);
1443 break; 1512 break;
1444 case AGGR_THREAD: 1513 case AGGR_THREAD:
1445 evlist__for_each(evsel_list, counter) 1514 evlist__for_each_entry(evsel_list, counter)
1446 print_aggr_thread(counter, prefix); 1515 print_aggr_thread(counter, prefix);
1447 break; 1516 break;
1448 case AGGR_GLOBAL: 1517 case AGGR_GLOBAL:
1449 evlist__for_each(evsel_list, counter) 1518 evlist__for_each_entry(evsel_list, counter)
1450 print_counter_aggr(counter, prefix); 1519 print_counter_aggr(counter, prefix);
1451 if (metric_only) 1520 if (metric_only)
1452 fputc('\n', stat_config.output); 1521 fputc('\n', stat_config.output);
@@ -1455,7 +1524,7 @@ static void print_counters(struct timespec *ts, int argc, const char **argv)
1455 if (metric_only) 1524 if (metric_only)
1456 print_no_aggr_metric(prefix); 1525 print_no_aggr_metric(prefix);
1457 else { 1526 else {
1458 evlist__for_each(evsel_list, counter) 1527 evlist__for_each_entry(evsel_list, counter)
1459 print_counter(counter, prefix); 1528 print_counter(counter, prefix);
1460 } 1529 }
1461 break; 1530 break;
@@ -1520,6 +1589,14 @@ static int stat__set_big_num(const struct option *opt __maybe_unused,
1520 return 0; 1589 return 0;
1521} 1590}
1522 1591
1592static int enable_metric_only(const struct option *opt __maybe_unused,
1593 const char *s __maybe_unused, int unset)
1594{
1595 force_metric_only = true;
1596 metric_only = !unset;
1597 return 0;
1598}
1599
1523static const struct option stat_options[] = { 1600static const struct option stat_options[] = {
1524 OPT_BOOLEAN('T', "transaction", &transaction_run, 1601 OPT_BOOLEAN('T', "transaction", &transaction_run,
1525 "hardware transaction statistics"), 1602 "hardware transaction statistics"),
@@ -1578,8 +1655,10 @@ static const struct option stat_options[] = {
1578 "aggregate counts per thread", AGGR_THREAD), 1655 "aggregate counts per thread", AGGR_THREAD),
1579 OPT_UINTEGER('D', "delay", &initial_delay, 1656 OPT_UINTEGER('D', "delay", &initial_delay,
1580 "ms to wait before starting measurement after program start"), 1657 "ms to wait before starting measurement after program start"),
1581 OPT_BOOLEAN(0, "metric-only", &metric_only, 1658 OPT_CALLBACK_NOOPT(0, "metric-only", &metric_only, NULL,
1582 "Only print computed metrics. No raw values"), 1659 "Only print computed metrics. No raw values", enable_metric_only),
1660 OPT_BOOLEAN(0, "topdown", &topdown_run,
1661 "measure topdown level 1 statistics"),
1583 OPT_END() 1662 OPT_END()
1584}; 1663};
1585 1664
@@ -1772,12 +1851,62 @@ static int perf_stat_init_aggr_mode_file(struct perf_stat *st)
1772 return 0; 1851 return 0;
1773} 1852}
1774 1853
1854static int topdown_filter_events(const char **attr, char **str, bool use_group)
1855{
1856 int off = 0;
1857 int i;
1858 int len = 0;
1859 char *s;
1860
1861 for (i = 0; attr[i]; i++) {
1862 if (pmu_have_event("cpu", attr[i])) {
1863 len += strlen(attr[i]) + 1;
1864 attr[i - off] = attr[i];
1865 } else
1866 off++;
1867 }
1868 attr[i - off] = NULL;
1869
1870 *str = malloc(len + 1 + 2);
1871 if (!*str)
1872 return -1;
1873 s = *str;
1874 if (i - off == 0) {
1875 *s = 0;
1876 return 0;
1877 }
1878 if (use_group)
1879 *s++ = '{';
1880 for (i = 0; attr[i]; i++) {
1881 strcpy(s, attr[i]);
1882 s += strlen(s);
1883 *s++ = ',';
1884 }
1885 if (use_group) {
1886 s[-1] = '}';
1887 *s = 0;
1888 } else
1889 s[-1] = 0;
1890 return 0;
1891}
1892
1893__weak bool arch_topdown_check_group(bool *warn)
1894{
1895 *warn = false;
1896 return false;
1897}
1898
1899__weak void arch_topdown_group_warn(void)
1900{
1901}
1902
1775/* 1903/*
1776 * Add default attributes, if there were no attributes specified or 1904 * Add default attributes, if there were no attributes specified or
1777 * if -d/--detailed, -d -d or -d -d -d is used: 1905 * if -d/--detailed, -d -d or -d -d -d is used:
1778 */ 1906 */
1779static int add_default_attributes(void) 1907static int add_default_attributes(void)
1780{ 1908{
1909 int err;
1781 struct perf_event_attr default_attrs0[] = { 1910 struct perf_event_attr default_attrs0[] = {
1782 1911
1783 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK }, 1912 { .type = PERF_TYPE_SOFTWARE, .config = PERF_COUNT_SW_TASK_CLOCK },
@@ -1896,7 +2025,6 @@ static int add_default_attributes(void)
1896 return 0; 2025 return 0;
1897 2026
1898 if (transaction_run) { 2027 if (transaction_run) {
1899 int err;
1900 if (pmu_have_event("cpu", "cycles-ct") && 2028 if (pmu_have_event("cpu", "cycles-ct") &&
1901 pmu_have_event("cpu", "el-start")) 2029 pmu_have_event("cpu", "el-start"))
1902 err = parse_events(evsel_list, transaction_attrs, NULL); 2030 err = parse_events(evsel_list, transaction_attrs, NULL);
@@ -1909,6 +2037,46 @@ static int add_default_attributes(void)
1909 return 0; 2037 return 0;
1910 } 2038 }
1911 2039
2040 if (topdown_run) {
2041 char *str = NULL;
2042 bool warn = false;
2043
2044 if (stat_config.aggr_mode != AGGR_GLOBAL &&
2045 stat_config.aggr_mode != AGGR_CORE) {
2046 pr_err("top down event configuration requires --per-core mode\n");
2047 return -1;
2048 }
2049 stat_config.aggr_mode = AGGR_CORE;
2050 if (nr_cgroups || !target__has_cpu(&target)) {
2051 pr_err("top down event configuration requires system-wide mode (-a)\n");
2052 return -1;
2053 }
2054
2055 if (!force_metric_only)
2056 metric_only = true;
2057 if (topdown_filter_events(topdown_attrs, &str,
2058 arch_topdown_check_group(&warn)) < 0) {
2059 pr_err("Out of memory\n");
2060 return -1;
2061 }
2062 if (topdown_attrs[0] && str) {
2063 if (warn)
2064 arch_topdown_group_warn();
2065 err = parse_events(evsel_list, str, NULL);
2066 if (err) {
2067 fprintf(stderr,
2068 "Cannot set up top down events %s: %d\n",
2069 str, err);
2070 free(str);
2071 return -1;
2072 }
2073 } else {
2074 fprintf(stderr, "System does not support topdown\n");
2075 return -1;
2076 }
2077 free(str);
2078 }
2079
1912 if (!evsel_list->nr_entries) { 2080 if (!evsel_list->nr_entries) {
1913 if (target__has_cpu(&target)) 2081 if (target__has_cpu(&target))
1914 default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK; 2082 default_attrs0[0].config = PERF_COUNT_SW_CPU_CLOCK;
@@ -2010,15 +2178,15 @@ static int process_stat_round_event(struct perf_tool *tool __maybe_unused,
2010 const char **argv = session->header.env.cmdline_argv; 2178 const char **argv = session->header.env.cmdline_argv;
2011 int argc = session->header.env.nr_cmdline; 2179 int argc = session->header.env.nr_cmdline;
2012 2180
2013 evlist__for_each(evsel_list, counter) 2181 evlist__for_each_entry(evsel_list, counter)
2014 perf_stat_process_counter(&stat_config, counter); 2182 perf_stat_process_counter(&stat_config, counter);
2015 2183
2016 if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL) 2184 if (stat_round->type == PERF_STAT_ROUND_TYPE__FINAL)
2017 update_stats(&walltime_nsecs_stats, stat_round->time); 2185 update_stats(&walltime_nsecs_stats, stat_round->time);
2018 2186
2019 if (stat_config.interval && stat_round->time) { 2187 if (stat_config.interval && stat_round->time) {
2020 tsh.tv_sec = stat_round->time / NSECS_PER_SEC; 2188 tsh.tv_sec = stat_round->time / NSEC_PER_SEC;
2021 tsh.tv_nsec = stat_round->time % NSECS_PER_SEC; 2189 tsh.tv_nsec = stat_round->time % NSEC_PER_SEC;
2022 ts = &tsh; 2190 ts = &tsh;
2023 } 2191 }
2024 2192
diff --git a/tools/perf/builtin-timechart.c b/tools/perf/builtin-timechart.c
index 733a55422d03..e7eaa298d34a 100644
--- a/tools/perf/builtin-timechart.c
+++ b/tools/perf/builtin-timechart.c
@@ -24,6 +24,7 @@
24#include "util/evlist.h" 24#include "util/evlist.h"
25#include "util/evsel.h" 25#include "util/evsel.h"
26#include <linux/rbtree.h> 26#include <linux/rbtree.h>
27#include <linux/time64.h>
27#include "util/symbol.h" 28#include "util/symbol.h"
28#include "util/callchain.h" 29#include "util/callchain.h"
29#include "util/strlist.h" 30#include "util/strlist.h"
@@ -1288,9 +1289,9 @@ static void draw_process_bars(struct timechart *tchart)
1288 if (c->comm) { 1289 if (c->comm) {
1289 char comm[256]; 1290 char comm[256];
1290 if (c->total_time > 5000000000) /* 5 seconds */ 1291 if (c->total_time > 5000000000) /* 5 seconds */
1291 sprintf(comm, "%s:%i (%2.2fs)", c->comm, p->pid, c->total_time / 1000000000.0); 1292 sprintf(comm, "%s:%i (%2.2fs)", c->comm, p->pid, c->total_time / (double)NSEC_PER_SEC);
1292 else 1293 else
1293 sprintf(comm, "%s:%i (%3.1fms)", c->comm, p->pid, c->total_time / 1000000.0); 1294 sprintf(comm, "%s:%i (%3.1fms)", c->comm, p->pid, c->total_time / (double)NSEC_PER_MSEC);
1294 1295
1295 svg_text(Y, c->start_time, comm); 1296 svg_text(Y, c->start_time, comm);
1296 } 1297 }
@@ -1637,7 +1638,7 @@ static int __cmd_timechart(struct timechart *tchart, const char *output_name)
1637 write_svg_file(tchart, output_name); 1638 write_svg_file(tchart, output_name);
1638 1639
1639 pr_info("Written %2.1f seconds of trace to %s.\n", 1640 pr_info("Written %2.1f seconds of trace to %s.\n",
1640 (tchart->last_time - tchart->first_time) / 1000000000.0, output_name); 1641 (tchart->last_time - tchart->first_time) / (double)NSEC_PER_SEC, output_name);
1641out_delete: 1642out_delete:
1642 perf_session__delete(session); 1643 perf_session__delete(session);
1643 return ret; 1644 return ret;
@@ -1901,10 +1902,10 @@ parse_time(const struct option *opt, const char *arg, int __maybe_unused unset)
1901 if (sscanf(arg, "%" PRIu64 "%cs", value, &unit) > 0) { 1902 if (sscanf(arg, "%" PRIu64 "%cs", value, &unit) > 0) {
1902 switch (unit) { 1903 switch (unit) {
1903 case 'm': 1904 case 'm':
1904 *value *= 1000000; 1905 *value *= NSEC_PER_MSEC;
1905 break; 1906 break;
1906 case 'u': 1907 case 'u':
1907 *value *= 1000; 1908 *value *= NSEC_PER_USEC;
1908 break; 1909 break;
1909 case 'n': 1910 case 'n':
1910 break; 1911 break;
@@ -1928,7 +1929,7 @@ int cmd_timechart(int argc, const char **argv,
1928 .ordered_events = true, 1929 .ordered_events = true,
1929 }, 1930 },
1930 .proc_num = 15, 1931 .proc_num = 15,
1931 .min_time = 1000000, 1932 .min_time = NSEC_PER_MSEC,
1932 .merge_dist = 1000, 1933 .merge_dist = 1000,
1933 }; 1934 };
1934 const char *output_name = "output.svg"; 1935 const char *output_name = "output.svg";
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 2a6cc254ad0c..fe3af9535e85 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -22,8 +22,9 @@
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/drv_configs.h"
27#include "util/evlist.h" 28#include "util/evlist.h"
28#include "util/evsel.h" 29#include "util/evsel.h"
29#include "util/machine.h" 30#include "util/machine.h"
@@ -68,6 +69,7 @@
68#include <sys/mman.h> 69#include <sys/mman.h>
69 70
70#include <linux/stringify.h> 71#include <linux/stringify.h>
72#include <linux/time64.h>
71#include <linux/types.h> 73#include <linux/types.h>
72 74
73static volatile int done; 75static volatile int done;
@@ -128,10 +130,14 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
128 return err; 130 return err;
129 } 131 }
130 132
131 err = symbol__annotate(sym, map, 0); 133 err = symbol__disassemble(sym, map, 0);
132 if (err == 0) { 134 if (err == 0) {
133out_assign: 135out_assign:
134 top->sym_filter_entry = he; 136 top->sym_filter_entry = he;
137 } else {
138 char msg[BUFSIZ];
139 symbol__strerror_disassemble(sym, map, err, msg, sizeof(msg));
140 pr_err("Couldn't annotate %s: %s\n", sym->name, msg);
135 } 141 }
136 142
137 pthread_mutex_unlock(&notes->lock); 143 pthread_mutex_unlock(&notes->lock);
@@ -295,7 +301,7 @@ static void perf_top__print_sym_table(struct perf_top *top)
295 hists__output_recalc_col_len(hists, top->print_entries - printed); 301 hists__output_recalc_col_len(hists, top->print_entries - printed);
296 putchar('\n'); 302 putchar('\n');
297 hists__fprintf(hists, false, top->print_entries - printed, win_width, 303 hists__fprintf(hists, false, top->print_entries - printed, win_width,
298 top->min_percent, stdout); 304 top->min_percent, stdout, symbol_conf.use_callchain);
299} 305}
300 306
301static void prompt_integer(int *target, const char *msg) 307static void prompt_integer(int *target, const char *msg)
@@ -479,7 +485,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
479 485
480 fprintf(stderr, "\nAvailable events:"); 486 fprintf(stderr, "\nAvailable events:");
481 487
482 evlist__for_each(top->evlist, top->sym_evsel) 488 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)); 489 fprintf(stderr, "\n\t%d %s", top->sym_evsel->idx, perf_evsel__name(top->sym_evsel));
484 490
485 prompt_integer(&counter, "Enter details event counter"); 491 prompt_integer(&counter, "Enter details event counter");
@@ -490,7 +496,7 @@ static bool perf_top__handle_keypress(struct perf_top *top, int c)
490 sleep(1); 496 sleep(1);
491 break; 497 break;
492 } 498 }
493 evlist__for_each(top->evlist, top->sym_evsel) 499 evlist__for_each_entry(top->evlist, top->sym_evsel)
494 if (top->sym_evsel->idx == counter) 500 if (top->sym_evsel->idx == counter)
495 break; 501 break;
496 } else 502 } else
@@ -583,7 +589,7 @@ static void *display_thread_tui(void *arg)
583 * Zooming in/out UIDs. For now juse use whatever the user passed 589 * Zooming in/out UIDs. For now juse use whatever the user passed
584 * via --uid. 590 * via --uid.
585 */ 591 */
586 evlist__for_each(top->evlist, pos) { 592 evlist__for_each_entry(top->evlist, pos) {
587 struct hists *hists = evsel__hists(pos); 593 struct hists *hists = evsel__hists(pos);
588 hists->uid_filter_str = top->record_opts.target.uid_str; 594 hists->uid_filter_str = top->record_opts.target.uid_str;
589 } 595 }
@@ -620,7 +626,7 @@ static void *display_thread(void *arg)
620 display_setup_sig(); 626 display_setup_sig();
621 pthread__unblock_sigwinch(); 627 pthread__unblock_sigwinch();
622repeat: 628repeat:
623 delay_msecs = top->delay_secs * 1000; 629 delay_msecs = top->delay_secs * MSEC_PER_SEC;
624 set_term_quiet_input(&save); 630 set_term_quiet_input(&save);
625 /* trash return*/ 631 /* trash return*/
626 getc(stdin); 632 getc(stdin);
@@ -652,34 +658,6 @@ repeat:
652 return NULL; 658 return NULL;
653} 659}
654 660
655static int symbol_filter(struct map *map, struct symbol *sym)
656{
657 const char *name = sym->name;
658
659 if (!__map__is_kernel(map))
660 return 0;
661 /*
662 * ppc64 uses function descriptors and appends a '.' to the
663 * start of every instruction address. Remove it.
664 */
665 if (name[0] == '.')
666 name++;
667
668 if (!strcmp(name, "_text") ||
669 !strcmp(name, "_etext") ||
670 !strcmp(name, "_sinittext") ||
671 !strncmp("init_module", name, 11) ||
672 !strncmp("cleanup_module", name, 14) ||
673 strstr(name, "_text_start") ||
674 strstr(name, "_text_end"))
675 return 1;
676
677 if (symbol__is_idle(sym))
678 sym->ignore = true;
679
680 return 0;
681}
682
683static int hist_iter__top_callback(struct hist_entry_iter *iter, 661static int hist_iter__top_callback(struct hist_entry_iter *iter,
684 struct addr_location *al, bool single, 662 struct addr_location *al, bool single,
685 void *arg) 663 void *arg)
@@ -778,7 +756,7 @@ static void perf_event__process_sample(struct perf_tool *tool,
778 } 756 }
779 } 757 }
780 758
781 if (al.sym == NULL || !al.sym->ignore) { 759 if (al.sym == NULL || !al.sym->idle) {
782 struct hists *hists = evsel__hists(evsel); 760 struct hists *hists = evsel__hists(evsel);
783 struct hist_entry_iter iter = { 761 struct hist_entry_iter iter = {
784 .evsel = evsel, 762 .evsel = evsel,
@@ -888,7 +866,7 @@ static int perf_top__start_counters(struct perf_top *top)
888 866
889 perf_evlist__config(evlist, opts, &callchain_param); 867 perf_evlist__config(evlist, opts, &callchain_param);
890 868
891 evlist__for_each(evlist, counter) { 869 evlist__for_each_entry(evlist, counter) {
892try_again: 870try_again:
893 if (perf_evsel__open(counter, top->evlist->cpus, 871 if (perf_evsel__open(counter, top->evlist->cpus,
894 top->evlist->threads) < 0) { 872 top->evlist->threads) < 0) {
@@ -907,7 +885,7 @@ try_again:
907 885
908 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) { 886 if (perf_evlist__mmap(evlist, opts->mmap_pages, false) < 0) {
909 ui__error("Failed to mmap with %d (%s)\n", 887 ui__error("Failed to mmap with %d (%s)\n",
910 errno, strerror_r(errno, msg, sizeof(msg))); 888 errno, str_error_r(errno, msg, sizeof(msg)));
911 goto out_err; 889 goto out_err;
912 } 890 }
913 891
@@ -936,6 +914,10 @@ static int callchain_param__setup_sample_type(struct callchain_param *callchain)
936 914
937static int __cmd_top(struct perf_top *top) 915static int __cmd_top(struct perf_top *top)
938{ 916{
917 char msg[512];
918 struct perf_evsel *pos;
919 struct perf_evsel_config_term *err_term;
920 struct perf_evlist *evlist = top->evlist;
939 struct record_opts *opts = &top->record_opts; 921 struct record_opts *opts = &top->record_opts;
940 pthread_t thread; 922 pthread_t thread;
941 int ret; 923 int ret;
@@ -944,8 +926,6 @@ static int __cmd_top(struct perf_top *top)
944 if (top->session == NULL) 926 if (top->session == NULL)
945 return -1; 927 return -1;
946 928
947 machines__set_symbol_filter(&top->session->machines, symbol_filter);
948
949 if (!objdump_path) { 929 if (!objdump_path) {
950 ret = perf_env__lookup_objdump(&top->session->header.env); 930 ret = perf_env__lookup_objdump(&top->session->header.env);
951 if (ret) 931 if (ret)
@@ -972,6 +952,14 @@ static int __cmd_top(struct perf_top *top)
972 if (ret) 952 if (ret)
973 goto out_delete; 953 goto out_delete;
974 954
955 ret = perf_evlist__apply_drv_configs(evlist, &pos, &err_term);
956 if (ret) {
957 error("failed to set config \"%s\" on event %s with %d (%s)\n",
958 err_term->val.drv_cfg, perf_evsel__name(pos), errno,
959 str_error_r(errno, msg, sizeof(msg)));
960 goto out_delete;
961 }
962
975 top->session->evlist = top->evlist; 963 top->session->evlist = top->evlist;
976 perf_session__set_id_hdr_size(top->session); 964 perf_session__set_id_hdr_size(top->session);
977 965
@@ -1028,7 +1016,7 @@ out_delete:
1028 1016
1029out_err_cpu_topo: { 1017out_err_cpu_topo: {
1030 char errbuf[BUFSIZ]; 1018 char errbuf[BUFSIZ];
1031 const char *err = strerror_r(-ret, errbuf, sizeof(errbuf)); 1019 const char *err = str_error_r(-ret, errbuf, sizeof(errbuf));
1032 1020
1033 ui__error("Could not read the CPU topology map: %s\n", err); 1021 ui__error("Could not read the CPU topology map: %s\n", err);
1034 goto out_delete; 1022 goto out_delete;
@@ -1295,7 +1283,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1295 1283
1296 if (perf_evlist__create_maps(top.evlist, target) < 0) { 1284 if (perf_evlist__create_maps(top.evlist, target) < 0) {
1297 ui__error("Couldn't create thread/CPU maps: %s\n", 1285 ui__error("Couldn't create thread/CPU maps: %s\n",
1298 errno == ENOENT ? "No such process" : strerror_r(errno, errbuf, sizeof(errbuf))); 1286 errno == ENOENT ? "No such process" : str_error_r(errno, errbuf, sizeof(errbuf)));
1299 goto out_delete_evlist; 1287 goto out_delete_evlist;
1300 } 1288 }
1301 1289
@@ -1319,7 +1307,9 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused)
1319 if (symbol_conf.cumulate_callchain && !callchain_param.order_set) 1307 if (symbol_conf.cumulate_callchain && !callchain_param.order_set)
1320 callchain_param.order = ORDER_CALLER; 1308 callchain_param.order = ORDER_CALLER;
1321 1309
1322 symbol_conf.priv_size = sizeof(struct annotation); 1310 status = symbol__annotation_init();
1311 if (status < 0)
1312 goto out_delete_evlist;
1323 1313
1324 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL); 1314 symbol_conf.try_vmlinux_path = (symbol_conf.vmlinux_name == NULL);
1325 if (symbol__init(NULL) < 0) 1315 if (symbol__init(NULL) < 0)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 5c50fe70d6b3..c298bd3e1d90 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -43,9 +43,9 @@
43#include <linux/err.h> 43#include <linux/err.h>
44#include <linux/filter.h> 44#include <linux/filter.h>
45#include <linux/audit.h> 45#include <linux/audit.h>
46#include <sys/ptrace.h>
47#include <linux/random.h> 46#include <linux/random.h>
48#include <linux/stringify.h> 47#include <linux/stringify.h>
48#include <linux/time64.h>
49 49
50#ifndef O_CLOEXEC 50#ifndef O_CLOEXEC
51# define O_CLOEXEC 02000000 51# define O_CLOEXEC 02000000
@@ -334,6 +334,10 @@ static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
334 334
335#define SCA_FD syscall_arg__scnprintf_fd 335#define SCA_FD syscall_arg__scnprintf_fd
336 336
337#ifndef AT_FDCWD
338#define AT_FDCWD -100
339#endif
340
337static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size, 341static size_t syscall_arg__scnprintf_fd_at(char *bf, size_t size,
338 struct syscall_arg *arg) 342 struct syscall_arg *arg)
339{ 343{
@@ -738,6 +742,8 @@ static struct syscall_fmt {
738 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, }, 742 .arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
739 { .name = "rt_tgsigqueueinfo", .errmsg = true, 743 { .name = "rt_tgsigqueueinfo", .errmsg = true,
740 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, }, 744 .arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
745 { .name = "sched_getattr", .errmsg = true, },
746 { .name = "sched_setattr", .errmsg = true, },
741 { .name = "sched_setscheduler", .errmsg = true, 747 { .name = "sched_setscheduler", .errmsg = true,
742 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, }, 748 .arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
743 { .name = "seccomp", .errmsg = true, 749 { .name = "seccomp", .errmsg = true,
@@ -1247,7 +1253,7 @@ static int trace__validate_ev_qualifier(struct trace *trace)
1247 1253
1248 i = 0; 1254 i = 0;
1249 1255
1250 strlist__for_each(pos, trace->ev_qualifier) { 1256 strlist__for_each_entry(pos, trace->ev_qualifier) {
1251 const char *sc = pos->s; 1257 const char *sc = pos->s;
1252 int id = syscalltbl__id(trace->sctbl, sc); 1258 int id = syscalltbl__id(trace->sctbl, sc);
1253 1259
@@ -1601,7 +1607,7 @@ signed_print:
1601 fprintf(trace->output, ") = %ld", ret); 1607 fprintf(trace->output, ") = %ld", ret);
1602 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) { 1608 } else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
1603 char bf[STRERR_BUFSIZE]; 1609 char bf[STRERR_BUFSIZE];
1604 const char *emsg = strerror_r(-ret, bf, sizeof(bf)), 1610 const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
1605 *e = audit_errno_to_name(-ret); 1611 *e = audit_errno_to_name(-ret);
1606 1612
1607 fprintf(trace->output, ") = -1 %s %s", e, emsg); 1613 fprintf(trace->output, ") = -1 %s %s", e, emsg);
@@ -2137,6 +2143,7 @@ out_delete_sys_enter:
2137static int trace__set_ev_qualifier_filter(struct trace *trace) 2143static int trace__set_ev_qualifier_filter(struct trace *trace)
2138{ 2144{
2139 int err = -1; 2145 int err = -1;
2146 struct perf_evsel *sys_exit;
2140 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier, 2147 char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
2141 trace->ev_qualifier_ids.nr, 2148 trace->ev_qualifier_ids.nr,
2142 trace->ev_qualifier_ids.entries); 2149 trace->ev_qualifier_ids.entries);
@@ -2144,8 +2151,11 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
2144 if (filter == NULL) 2151 if (filter == NULL)
2145 goto out_enomem; 2152 goto out_enomem;
2146 2153
2147 if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter)) 2154 if (!perf_evsel__append_tp_filter(trace->syscalls.events.sys_enter,
2148 err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter); 2155 filter)) {
2156 sys_exit = trace->syscalls.events.sys_exit;
2157 err = perf_evsel__append_tp_filter(sys_exit, filter);
2158 }
2149 2159
2150 free(filter); 2160 free(filter);
2151out: 2161out:
@@ -2402,7 +2412,7 @@ out_error_apply_filters:
2402 fprintf(trace->output, 2412 fprintf(trace->output,
2403 "Failed to set filter \"%s\" on event %s with %d (%s)\n", 2413 "Failed to set filter \"%s\" on event %s with %d (%s)\n",
2404 evsel->filter, perf_evsel__name(evsel), errno, 2414 evsel->filter, perf_evsel__name(evsel), errno,
2405 strerror_r(errno, errbuf, sizeof(errbuf))); 2415 str_error_r(errno, errbuf, sizeof(errbuf)));
2406 goto out_delete_evlist; 2416 goto out_delete_evlist;
2407} 2417}
2408out_error_mem: 2418out_error_mem:
@@ -2483,7 +2493,7 @@ static int trace__replay(struct trace *trace)
2483 goto out; 2493 goto out;
2484 } 2494 }
2485 2495
2486 evlist__for_each(session->evlist, evsel) { 2496 evlist__for_each_entry(session->evlist, evsel) {
2487 if (evsel->attr.type == PERF_TYPE_SOFTWARE && 2497 if (evsel->attr.type == PERF_TYPE_SOFTWARE &&
2488 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ || 2498 (evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MAJ ||
2489 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN || 2499 evsel->attr.config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
@@ -2550,7 +2560,7 @@ static size_t thread__dump_stats(struct thread_trace *ttrace,
2550 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n"); 2560 printed += fprintf(fp, " (msec) (msec) (msec) (msec) (%%)\n");
2551 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n"); 2561 printed += fprintf(fp, " --------------- -------- --------- --------- --------- --------- ------\n");
2552 2562
2553 resort_rb__for_each(nd, syscall_stats) { 2563 resort_rb__for_each_entry(nd, syscall_stats) {
2554 struct stats *stats = syscall_stats_entry->stats; 2564 struct stats *stats = syscall_stats_entry->stats;
2555 if (stats) { 2565 if (stats) {
2556 double min = (double)(stats->min) / NSEC_PER_MSEC; 2566 double min = (double)(stats->min) / NSEC_PER_MSEC;
@@ -2627,7 +2637,7 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp)
2627 return 0; 2637 return 0;
2628 } 2638 }
2629 2639
2630 resort_rb__for_each(nd, threads) 2640 resort_rb__for_each_entry(nd, threads)
2631 printed += trace__fprintf_thread(fp, threads_entry->thread, trace); 2641 printed += trace__fprintf_thread(fp, threads_entry->thread, trace);
2632 2642
2633 resort_rb__delete(threads); 2643 resort_rb__delete(threads);
@@ -2714,7 +2724,7 @@ static void evlist__set_evsel_handler(struct perf_evlist *evlist, void *handler)
2714{ 2724{
2715 struct perf_evsel *evsel; 2725 struct perf_evsel *evsel;
2716 2726
2717 evlist__for_each(evlist, evsel) 2727 evlist__for_each_entry(evlist, evsel)
2718 evsel->handler = handler; 2728 evsel->handler = handler;
2719} 2729}
2720 2730
diff --git a/tools/perf/jvmti/jvmti_agent.c b/tools/perf/jvmti/jvmti_agent.c
index 3573f315f955..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,11 +80,7 @@ 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);
@@ -491,10 +486,11 @@ jvmti_write_debug_info(void *agent, uint64_t code, const char *file,
491 if (sret != 1) 486 if (sret != 1)
492 goto error; 487 goto error;
493 } 488 }
494 if (padding_count) 489 if (padding_count) {
495 sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp); 490 sret = fwrite_unlocked(pad_bytes, padding_count, 1, fp);
496 if (sret != 1) 491 if (sret != 1)
497 goto error; 492 goto error;
493 }
498 494
499 funlockfile(fp); 495 funlockfile(fp);
500 return 0; 496 return 0;
diff --git a/tools/perf/perf-sys.h b/tools/perf/perf-sys.h
index 83a25cef82fd..e4b717e9eb6c 100644
--- a/tools/perf/perf-sys.h
+++ b/tools/perf/perf-sys.h
@@ -5,39 +5,21 @@
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__
40#include "../../arch/powerpc/include/uapi/asm/unistd.h"
41#define CPUINFO_PROC {"cpu"} 23#define CPUINFO_PROC {"cpu"}
42#endif 24#endif
43 25
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 15982cee5ef3..64c06961bfe4 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -10,7 +10,7 @@
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"
@@ -139,8 +139,6 @@ struct option options[] = {
139 OPT_ARGUMENT("html-path", "html-path"), 139 OPT_ARGUMENT("html-path", "html-path"),
140 OPT_ARGUMENT("paginate", "paginate"), 140 OPT_ARGUMENT("paginate", "paginate"),
141 OPT_ARGUMENT("no-pager", "no-pager"), 141 OPT_ARGUMENT("no-pager", "no-pager"),
142 OPT_ARGUMENT("perf-dir", "perf-dir"),
143 OPT_ARGUMENT("work-tree", "work-tree"),
144 OPT_ARGUMENT("debugfs-dir", "debugfs-dir"), 142 OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
145 OPT_ARGUMENT("buildid-dir", "buildid-dir"), 143 OPT_ARGUMENT("buildid-dir", "buildid-dir"),
146 OPT_ARGUMENT("list-cmds", "list-cmds"), 144 OPT_ARGUMENT("list-cmds", "list-cmds"),
@@ -200,35 +198,6 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
200 use_pager = 0; 198 use_pager = 0;
201 if (envchanged) 199 if (envchanged)
202 *envchanged = 1; 200 *envchanged = 1;
203 } else if (!strcmp(cmd, "--perf-dir")) {
204 if (*argc < 2) {
205 fprintf(stderr, "No directory given for --perf-dir.\n");
206 usage(perf_usage_string);
207 }
208 setenv(PERF_DIR_ENVIRONMENT, (*argv)[1], 1);
209 if (envchanged)
210 *envchanged = 1;
211 (*argv)++;
212 (*argc)--;
213 handled++;
214 } else if (!prefixcmp(cmd, CMD_PERF_DIR)) {
215 setenv(PERF_DIR_ENVIRONMENT, cmd + strlen(CMD_PERF_DIR), 1);
216 if (envchanged)
217 *envchanged = 1;
218 } else if (!strcmp(cmd, "--work-tree")) {
219 if (*argc < 2) {
220 fprintf(stderr, "No directory given for --work-tree.\n");
221 usage(perf_usage_string);
222 }
223 setenv(PERF_WORK_TREE_ENVIRONMENT, (*argv)[1], 1);
224 if (envchanged)
225 *envchanged = 1;
226 (*argv)++;
227 (*argc)--;
228 } else if (!prefixcmp(cmd, CMD_WORK_TREE)) {
229 setenv(PERF_WORK_TREE_ENVIRONMENT, cmd + strlen(CMD_WORK_TREE), 1);
230 if (envchanged)
231 *envchanged = 1;
232 } else if (!strcmp(cmd, "--debugfs-dir")) { 201 } else if (!strcmp(cmd, "--debugfs-dir")) {
233 if (*argc < 2) { 202 if (*argc < 2) {
234 fprintf(stderr, "No directory given for --debugfs-dir.\n"); 203 fprintf(stderr, "No directory given for --debugfs-dir.\n");
@@ -363,11 +332,6 @@ const char perf_version_string[] = PERF_VERSION;
363 332
364#define RUN_SETUP (1<<0) 333#define RUN_SETUP (1<<0)
365#define USE_PAGER (1<<1) 334#define USE_PAGER (1<<1)
366/*
367 * require working tree to be present -- anything uses this needs
368 * RUN_SETUP for reading from the configuration file.
369 */
370#define NEED_WORK_TREE (1<<2)
371 335
372static 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)
373{ 337{
@@ -391,6 +355,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
391 355
392 perf_env__set_cmdline(&perf_env, argc, argv); 356 perf_env__set_cmdline(&perf_env, argc, argv);
393 status = p->fn(argc, argv, prefix); 357 status = p->fn(argc, argv, prefix);
358 perf_config__exit();
394 exit_browser(status); 359 exit_browser(status);
395 perf_env__exit(&perf_env); 360 perf_env__exit(&perf_env);
396 bpf__clear(); 361 bpf__clear();
@@ -409,7 +374,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
409 /* Check for ENOSPC and EIO errors.. */ 374 /* Check for ENOSPC and EIO errors.. */
410 if (fflush(stdout)) { 375 if (fflush(stdout)) {
411 fprintf(stderr, "write failure on standard output: %s", 376 fprintf(stderr, "write failure on standard output: %s",
412 strerror_r(errno, sbuf, sizeof(sbuf))); 377 str_error_r(errno, sbuf, sizeof(sbuf)));
413 goto out; 378 goto out;
414 } 379 }
415 if (ferror(stdout)) { 380 if (ferror(stdout)) {
@@ -418,7 +383,7 @@ static int run_builtin(struct cmd_struct *p, int argc, const char **argv)
418 } 383 }
419 if (fclose(stdout)) { 384 if (fclose(stdout)) {
420 fprintf(stderr, "close failed on standard output: %s", 385 fprintf(stderr, "close failed on standard output: %s",
421 strerror_r(errno, sbuf, sizeof(sbuf))); 386 str_error_r(errno, sbuf, sizeof(sbuf)));
422 goto out; 387 goto out;
423 } 388 }
424 status = 0; 389 status = 0;
@@ -532,6 +497,16 @@ void pthread__unblock_sigwinch(void)
532 pthread_sigmask(SIG_UNBLOCK, &set, NULL); 497 pthread_sigmask(SIG_UNBLOCK, &set, NULL);
533} 498}
534 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
535int main(int argc, const char **argv) 510int main(int argc, const char **argv)
536{ 511{
537 const char *cmd; 512 const char *cmd;
@@ -544,7 +519,7 @@ int main(int argc, const char **argv)
544 519
545 /* The page_size is placed in util object. */ 520 /* The page_size is placed in util object. */
546 page_size = sysconf(_SC_PAGE_SIZE); 521 page_size = sysconf(_SC_PAGE_SIZE);
547 cacheline_size = sysconf(_SC_LEVEL1_DCACHE_LINESIZE); 522 cache_line_size(&cacheline_size);
548 523
549 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0) 524 if (sysctl__read_int("kernel/perf_event_max_stack", &value) == 0)
550 sysctl_perf_event_max_stack = value; 525 sysctl_perf_event_max_stack = value;
@@ -558,6 +533,7 @@ int main(int argc, const char **argv)
558 533
559 srandom(time(NULL)); 534 srandom(time(NULL));
560 535
536 perf_config__init();
561 perf_config(perf_default_config, NULL); 537 perf_config(perf_default_config, NULL);
562 set_buildid_dir(NULL); 538 set_buildid_dir(NULL);
563 539
@@ -649,7 +625,7 @@ int main(int argc, const char **argv)
649 } 625 }
650 626
651 fprintf(stderr, "Failed to run command '%s': %s\n", 627 fprintf(stderr, "Failed to run command '%s': %s\n",
652 cmd, strerror_r(errno, sbuf, sizeof(sbuf))); 628 cmd, str_error_r(errno, sbuf, sizeof(sbuf)));
653out: 629out:
654 return 1; 630 return 1;
655} 631}
diff --git a/tools/perf/perf.h b/tools/perf/perf.h
index cd8f1b150f9e..9a0236a4cf95 100644
--- a/tools/perf/perf.h
+++ b/tools/perf/perf.h
@@ -14,13 +14,6 @@ void test_attr__open(struct perf_event_attr *attr, pid_t pid, int cpu,
14#define HAVE_ATTR_TEST 14#define HAVE_ATTR_TEST
15#include "perf-sys.h" 15#include "perf-sys.h"
16 16
17#ifndef NSEC_PER_SEC
18# define NSEC_PER_SEC 1000000000ULL
19#endif
20#ifndef NSEC_PER_USEC
21# define NSEC_PER_USEC 1000ULL
22#endif
23
24static inline unsigned long long rdclock(void) 17static inline unsigned long long rdclock(void)
25{ 18{
26 struct timespec ts; 19 struct timespec ts;
@@ -52,6 +45,7 @@ struct record_opts {
52 bool sample_weight; 45 bool sample_weight;
53 bool sample_time; 46 bool sample_time;
54 bool sample_time_set; 47 bool sample_time_set;
48 bool sample_cpu;
55 bool period; 49 bool period;
56 bool running_time; 50 bool running_time;
57 bool full_auxtrace; 51 bool full_auxtrace;
@@ -59,6 +53,8 @@ struct record_opts {
59 bool record_switch_events; 53 bool record_switch_events;
60 bool all_kernel; 54 bool all_kernel;
61 bool all_user; 55 bool all_user;
56 bool tail_synthesize;
57 bool overwrite;
62 unsigned int freq; 58 unsigned int freq;
63 unsigned int mmap_pages; 59 unsigned int mmap_pages;
64 unsigned int auxtrace_mmap_pages; 60 unsigned int auxtrace_mmap_pages;
diff --git a/tools/perf/pmu-events/Build b/tools/perf/pmu-events/Build
new file mode 100644
index 000000000000..9213a1273697
--- /dev/null
+++ b/tools/perf/pmu-events/Build
@@ -0,0 +1,13 @@
1hostprogs := jevents
2
3jevents-y += json.o jsmn.o jevents.o
4pmu-events-y += pmu-events.o
5JDIR = pmu-events/arch/$(ARCH)
6JSON = $(shell [ -d $(JDIR) ] && \
7 find $(JDIR) -name '*.json' -o -name 'mapfile.csv')
8#
9# Locate/process JSON files in pmu-events/arch/
10# directory and create tables in pmu-events.c.
11#
12$(OUTPUT)pmu-events/pmu-events.c: $(JSON) $(JEVENTS)
13 $(Q)$(call echo-cmd,gen)$(JEVENTS) $(ARCH) pmu-events/arch $(OUTPUT)pmu-events/pmu-events.c $(V)
diff --git a/tools/perf/pmu-events/README b/tools/perf/pmu-events/README
new file mode 100644
index 000000000000..1408ade0d773
--- /dev/null
+++ b/tools/perf/pmu-events/README
@@ -0,0 +1,147 @@
1
2The contents of this directory allow users to specify PMU events in their
3CPUs by their symbolic names rather than raw event codes (see example below).
4
5The main program in this directory, is the 'jevents', which is built and
6executed _BEFORE_ the perf binary itself is built.
7
8The 'jevents' program tries to locate and process JSON files in the directory
9tree tools/perf/pmu-events/arch/foo.
10
11 - Regular files with '.json' extension in the name are assumed to be
12 JSON files, each of which describes a set of PMU events.
13
14 - Regular files with basename starting with 'mapfile.csv' are assumed
15 to be a CSV file that maps a specific CPU to its set of PMU events.
16 (see below for mapfile format)
17
18 - Directories are traversed, but all other files are ignored.
19
20The PMU events supported by a CPU model are expected to grouped into topics
21such as Pipelining, Cache, Memory, Floating-point etc. All events for a topic
22should be placed in a separate JSON file - where the file name identifies
23the topic. Eg: "Floating-point.json".
24
25All the topic JSON files for a CPU model/family should be in a separate
26sub directory. Thus for the Silvermont X86 CPU:
27
28 $ ls tools/perf/pmu-events/arch/x86/Silvermont_core
29 Cache.json Memory.json Virtual-Memory.json
30 Frontend.json Pipeline.json
31
32Using the JSON files and the mapfile, 'jevents' generates the C source file,
33'pmu-events.c', which encodes the two sets of tables:
34
35 - Set of 'PMU events tables' for all known CPUs in the architecture,
36 (one table like the following, per JSON file; table name 'pme_power8'
37 is derived from JSON file name, 'power8.json').
38
39 struct pmu_event pme_power8[] = {
40
41 ...
42
43 {
44 .name = "pm_1plus_ppc_cmpl",
45 .event = "event=0x100f2",
46 .desc = "1 or more ppc insts finished,",
47 },
48
49 ...
50 }
51
52 - A 'mapping table' that maps each CPU of the architecture, to its
53 'PMU events table'
54
55 struct pmu_events_map pmu_events_map[] = {
56 {
57 .cpuid = "004b0000",
58 .version = "1",
59 .type = "core",
60 .table = pme_power8
61 },
62 ...
63
64 };
65
66After the 'pmu-events.c' is generated, it is compiled and the resulting
67'pmu-events.o' is added to 'libperf.a' which is then used to build perf.
68
69NOTES:
70 1. Several CPUs can support same set of events and hence use a common
71 JSON file. Hence several entries in the pmu_events_map[] could map
72 to a single 'PMU events table'.
73
74 2. The 'pmu-events.h' has an extern declaration for the mapping table
75 and the generated 'pmu-events.c' defines this table.
76
77 3. _All_ known CPU tables for architecture are included in the perf
78 binary.
79
80At run time, perf determines the actual CPU it is running on, finds the
81matching events table and builds aliases for those events. This allows
82users to specify events by their name:
83
84 $ perf stat -e pm_1plus_ppc_cmpl sleep 1
85
86where 'pm_1plus_ppc_cmpl' is a Power8 PMU event.
87
88In case of errors when processing files in the tools/perf/pmu-events/arch
89directory, 'jevents' tries to create an empty mapping file to allow the perf
90build to succeed even if the PMU event aliases cannot be used.
91
92However some errors in processing may cause the perf build to fail.
93
94Mapfile format
95===============
96
97The mapfile enables multiple CPU models to share a single set of PMU events.
98It is required even if such mapping is 1:1.
99
100The mapfile.csv format is expected to be:
101
102 Header line
103 CPUID,Version,Dir/path/name,Type
104
105where:
106
107 Comma:
108 is the required field delimiter (i.e other fields cannot
109 have commas within them).
110
111 Comments:
112 Lines in which the first character is either '\n' or '#'
113 are ignored.
114
115 Header line
116 The header line is the first line in the file, which is
117 always _IGNORED_. It can empty.
118
119 CPUID:
120 CPUID is an arch-specific char string, that can be used
121 to identify CPU (and associate it with a set of PMU events
122 it supports). Multiple CPUIDS can point to the same
123 File/path/name.json.
124
125 Example:
126 CPUID == 'GenuineIntel-6-2E' (on x86).
127 CPUID == '004b0100' (PVR value in Powerpc)
128 Version:
129 is the Version of the mapfile.
130
131 Dir/path/name:
132 is the pathname to the directory containing the CPU's JSON
133 files, relative to the directory containing the mapfile.csv
134
135 Type:
136 indicates whether the events or "core" or "uncore" events.
137
138
139 Eg:
140
141 $ grep Silvermont tools/perf/pmu-events/arch/x86/mapfile.csv
142 GenuineIntel-6-37,V13,Silvermont_core,core
143 GenuineIntel-6-4D,V13,Silvermont_core,core
144 GenuineIntel-6-4C,V13,Silvermont_core,core
145
146 i.e the three CPU models use the JSON files (i.e PMU events) listed
147 in the directory 'tools/perf/pmu-events/arch/x86/Silvermont_core'.
diff --git a/tools/perf/pmu-events/jevents.c b/tools/perf/pmu-events/jevents.c
new file mode 100644
index 000000000000..41611d7f9873
--- /dev/null
+++ b/tools/perf/pmu-events/jevents.c
@@ -0,0 +1,814 @@
1#define _XOPEN_SOURCE 500 /* needed for nftw() */
2#define _GNU_SOURCE /* needed for asprintf() */
3
4/* Parse event JSON files */
5
6/*
7 * Copyright (c) 2014, Intel Corporation
8 * All rights reserved.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
32*/
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <errno.h>
37#include <string.h>
38#include <ctype.h>
39#include <unistd.h>
40#include <stdarg.h>
41#include <libgen.h>
42#include <dirent.h>
43#include <sys/time.h> /* getrlimit */
44#include <sys/resource.h> /* getrlimit */
45#include <ftw.h>
46#include <sys/stat.h>
47#include "jsmn.h"
48#include "json.h"
49#include "jevents.h"
50
51#ifndef __maybe_unused
52#define __maybe_unused __attribute__((unused))
53#endif
54
55int verbose;
56char *prog;
57
58int eprintf(int level, int var, const char *fmt, ...)
59{
60
61 int ret;
62 va_list args;
63
64 if (var < level)
65 return 0;
66
67 va_start(args, fmt);
68
69 ret = vfprintf(stderr, fmt, args);
70
71 va_end(args);
72
73 return ret;
74}
75
76__attribute__((weak)) char *get_cpu_str(void)
77{
78 return NULL;
79}
80
81static void addfield(char *map, char **dst, const char *sep,
82 const char *a, jsmntok_t *bt)
83{
84 unsigned int len = strlen(a) + 1 + strlen(sep);
85 int olen = *dst ? strlen(*dst) : 0;
86 int blen = bt ? json_len(bt) : 0;
87 char *out;
88
89 out = realloc(*dst, len + olen + blen);
90 if (!out) {
91 /* Don't add field in this case */
92 return;
93 }
94 *dst = out;
95
96 if (!olen)
97 *(*dst) = 0;
98 else
99 strcat(*dst, sep);
100 strcat(*dst, a);
101 if (bt)
102 strncat(*dst, map + bt->start, blen);
103}
104
105static void fixname(char *s)
106{
107 for (; *s; s++)
108 *s = tolower(*s);
109}
110
111static void fixdesc(char *s)
112{
113 char *e = s + strlen(s);
114
115 /* Remove trailing dots that look ugly in perf list */
116 --e;
117 while (e >= s && isspace(*e))
118 --e;
119 if (*e == '.')
120 *e = 0;
121}
122
123static struct msrmap {
124 const char *num;
125 const char *pname;
126} msrmap[] = {
127 { "0x3F6", "ldlat=" },
128 { "0x1A6", "offcore_rsp=" },
129 { "0x1A7", "offcore_rsp=" },
130 { "0x3F7", "frontend=" },
131 { NULL, NULL }
132};
133
134static struct field {
135 const char *field;
136 const char *kernel;
137} fields[] = {
138 { "EventCode", "event=" },
139 { "UMask", "umask=" },
140 { "CounterMask", "cmask=" },
141 { "Invert", "inv=" },
142 { "AnyThread", "any=" },
143 { "EdgeDetect", "edge=" },
144 { "SampleAfterValue", "period=" },
145 { NULL, NULL }
146};
147
148static void cut_comma(char *map, jsmntok_t *newval)
149{
150 int i;
151
152 /* Cut off everything after comma */
153 for (i = newval->start; i < newval->end; i++) {
154 if (map[i] == ',')
155 newval->end = i;
156 }
157}
158
159static int match_field(char *map, jsmntok_t *field, int nz,
160 char **event, jsmntok_t *val)
161{
162 struct field *f;
163 jsmntok_t newval = *val;
164
165 for (f = fields; f->field; f++)
166 if (json_streq(map, field, f->field) && nz) {
167 cut_comma(map, &newval);
168 addfield(map, event, ",", f->kernel, &newval);
169 return 1;
170 }
171 return 0;
172}
173
174static struct msrmap *lookup_msr(char *map, jsmntok_t *val)
175{
176 jsmntok_t newval = *val;
177 static bool warned;
178 int i;
179
180 cut_comma(map, &newval);
181 for (i = 0; msrmap[i].num; i++)
182 if (json_streq(map, &newval, msrmap[i].num))
183 return &msrmap[i];
184 if (!warned) {
185 warned = true;
186 pr_err("%s: Unknown MSR in event file %.*s\n", prog,
187 json_len(val), map + val->start);
188 }
189 return NULL;
190}
191
192#define EXPECT(e, t, m) do { if (!(e)) { \
193 jsmntok_t *loc = (t); \
194 if (!(t)->start && (t) > tokens) \
195 loc = (t) - 1; \
196 pr_err("%s:%d: " m ", got %s\n", fn, \
197 json_line(map, loc), \
198 json_name(t)); \
199 goto out_free; \
200} } while (0)
201
202#define TOPIC_DEPTH 256
203static char *topic_array[TOPIC_DEPTH];
204static int topic_level;
205
206static char *get_topic(void)
207{
208 char *tp_old, *tp = NULL;
209 int i;
210
211 for (i = 0; i < topic_level + 1; i++) {
212 int n;
213
214 tp_old = tp;
215 n = asprintf(&tp, "%s%s", tp ?: "", topic_array[i]);
216 if (n < 0) {
217 pr_info("%s: asprintf() error %s\n", prog);
218 return NULL;
219 }
220 free(tp_old);
221 }
222
223 for (i = 0; i < (int) strlen(tp); i++) {
224 char c = tp[i];
225
226 if (c == '-')
227 tp[i] = ' ';
228 else if (c == '.') {
229 tp[i] = '\0';
230 break;
231 }
232 }
233
234 return tp;
235}
236
237static int add_topic(int level, char *bname)
238{
239 char *topic;
240
241 level -= 2;
242
243 if (level >= TOPIC_DEPTH)
244 return -EINVAL;
245
246 topic = strdup(bname);
247 if (!topic) {
248 pr_info("%s: strdup() error %s for file %s\n", prog,
249 strerror(errno), bname);
250 return -ENOMEM;
251 }
252
253 free(topic_array[topic_level]);
254 topic_array[topic_level] = topic;
255 topic_level = level;
256 return 0;
257}
258
259struct perf_entry_data {
260 FILE *outfp;
261 char *topic;
262};
263
264static int close_table;
265
266static void print_events_table_prefix(FILE *fp, const char *tblname)
267{
268 fprintf(fp, "struct pmu_event %s[] = {\n", tblname);
269 close_table = 1;
270}
271
272static int print_events_table_entry(void *data, char *name, char *event,
273 char *desc, char *long_desc)
274{
275 struct perf_entry_data *pd = data;
276 FILE *outfp = pd->outfp;
277 char *topic = pd->topic;
278
279 /*
280 * TODO: Remove formatting chars after debugging to reduce
281 * string lengths.
282 */
283 fprintf(outfp, "{\n");
284
285 fprintf(outfp, "\t.name = \"%s\",\n", name);
286 fprintf(outfp, "\t.event = \"%s\",\n", event);
287 fprintf(outfp, "\t.desc = \"%s\",\n", desc);
288 fprintf(outfp, "\t.topic = \"%s\",\n", topic);
289 if (long_desc && long_desc[0])
290 fprintf(outfp, "\t.long_desc = \"%s\",\n", long_desc);
291
292 fprintf(outfp, "},\n");
293
294 return 0;
295}
296
297static void print_events_table_suffix(FILE *outfp)
298{
299 fprintf(outfp, "{\n");
300
301 fprintf(outfp, "\t.name = 0,\n");
302 fprintf(outfp, "\t.event = 0,\n");
303 fprintf(outfp, "\t.desc = 0,\n");
304
305 fprintf(outfp, "},\n");
306 fprintf(outfp, "};\n");
307 close_table = 0;
308}
309
310static struct fixed {
311 const char *name;
312 const char *event;
313} fixed[] = {
314 { "inst_retired.any", "event=0xc0" },
315 { "inst_retired.any_p", "event=0xc0" },
316 { "cpu_clk_unhalted.ref", "event=0x0,umask=0x03" },
317 { "cpu_clk_unhalted.thread", "event=0x3c" },
318 { "cpu_clk_unhalted.thread_any", "event=0x3c,any=1" },
319 { NULL, NULL},
320};
321
322/*
323 * Handle different fixed counter encodings between JSON and perf.
324 */
325static char *real_event(const char *name, char *event)
326{
327 int i;
328
329 for (i = 0; fixed[i].name; i++)
330 if (!strcasecmp(name, fixed[i].name))
331 return (char *)fixed[i].event;
332 return event;
333}
334
335/* Call func with each event in the json file */
336int json_events(const char *fn,
337 int (*func)(void *data, char *name, char *event, char *desc,
338 char *long_desc),
339 void *data)
340{
341 int err = -EIO;
342 size_t size;
343 jsmntok_t *tokens, *tok;
344 int i, j, len;
345 char *map;
346
347 if (!fn)
348 return -ENOENT;
349
350 tokens = parse_json(fn, &map, &size, &len);
351 if (!tokens)
352 return -EIO;
353 EXPECT(tokens->type == JSMN_ARRAY, tokens, "expected top level array");
354 tok = tokens + 1;
355 for (i = 0; i < tokens->size; i++) {
356 char *event = NULL, *desc = NULL, *name = NULL;
357 char *long_desc = NULL;
358 char *extra_desc = NULL;
359 struct msrmap *msr = NULL;
360 jsmntok_t *msrval = NULL;
361 jsmntok_t *precise = NULL;
362 jsmntok_t *obj = tok++;
363
364 EXPECT(obj->type == JSMN_OBJECT, obj, "expected object");
365 for (j = 0; j < obj->size; j += 2) {
366 jsmntok_t *field, *val;
367 int nz;
368
369 field = tok + j;
370 EXPECT(field->type == JSMN_STRING, tok + j,
371 "Expected field name");
372 val = tok + j + 1;
373 EXPECT(val->type == JSMN_STRING, tok + j + 1,
374 "Expected string value");
375
376 nz = !json_streq(map, val, "0");
377 if (match_field(map, field, nz, &event, val)) {
378 /* ok */
379 } else if (json_streq(map, field, "EventName")) {
380 addfield(map, &name, "", "", val);
381 } else if (json_streq(map, field, "BriefDescription")) {
382 addfield(map, &desc, "", "", val);
383 fixdesc(desc);
384 } else if (json_streq(map, field,
385 "PublicDescription")) {
386 addfield(map, &long_desc, "", "", val);
387 fixdesc(long_desc);
388 } else if (json_streq(map, field, "PEBS") && nz) {
389 precise = val;
390 } else if (json_streq(map, field, "MSRIndex") && nz) {
391 msr = lookup_msr(map, val);
392 } else if (json_streq(map, field, "MSRValue")) {
393 msrval = val;
394 } else if (json_streq(map, field, "Errata") &&
395 !json_streq(map, val, "null")) {
396 addfield(map, &extra_desc, ". ",
397 " Spec update: ", val);
398 } else if (json_streq(map, field, "Data_LA") && nz) {
399 addfield(map, &extra_desc, ". ",
400 " Supports address when precise",
401 NULL);
402 }
403 /* ignore unknown fields */
404 }
405 if (precise && desc && !strstr(desc, "(Precise Event)")) {
406 if (json_streq(map, precise, "2"))
407 addfield(map, &extra_desc, " ",
408 "(Must be precise)", NULL);
409 else
410 addfield(map, &extra_desc, " ",
411 "(Precise event)", NULL);
412 }
413 if (desc && extra_desc)
414 addfield(map, &desc, " ", extra_desc, NULL);
415 if (long_desc && extra_desc)
416 addfield(map, &long_desc, " ", extra_desc, NULL);
417 if (msr != NULL)
418 addfield(map, &event, ",", msr->pname, msrval);
419 fixname(name);
420
421 err = func(data, name, real_event(name, event), desc, long_desc);
422 free(event);
423 free(desc);
424 free(name);
425 free(long_desc);
426 free(extra_desc);
427 if (err)
428 break;
429 tok += j;
430 }
431 EXPECT(tok - tokens == len, tok, "unexpected objects at end");
432 err = 0;
433out_free:
434 free_json(map, size, tokens);
435 return err;
436}
437
438static char *file_name_to_table_name(char *fname)
439{
440 unsigned int i;
441 int n;
442 int c;
443 char *tblname;
444
445 /*
446 * Ensure tablename starts with alphabetic character.
447 * Derive rest of table name from basename of the JSON file,
448 * replacing hyphens and stripping out .json suffix.
449 */
450 n = asprintf(&tblname, "pme_%s", basename(fname));
451 if (n < 0) {
452 pr_info("%s: asprintf() error %s for file %s\n", prog,
453 strerror(errno), fname);
454 return NULL;
455 }
456
457 for (i = 0; i < strlen(tblname); i++) {
458 c = tblname[i];
459
460 if (c == '-')
461 tblname[i] = '_';
462 else if (c == '.') {
463 tblname[i] = '\0';
464 break;
465 } else if (!isalnum(c) && c != '_') {
466 pr_err("%s: Invalid character '%c' in file name %s\n",
467 prog, c, basename(fname));
468 free(tblname);
469 tblname = NULL;
470 break;
471 }
472 }
473
474 return tblname;
475}
476
477static void print_mapping_table_prefix(FILE *outfp)
478{
479 fprintf(outfp, "struct pmu_events_map pmu_events_map[] = {\n");
480}
481
482static void print_mapping_table_suffix(FILE *outfp)
483{
484 /*
485 * Print the terminating, NULL entry.
486 */
487 fprintf(outfp, "{\n");
488 fprintf(outfp, "\t.cpuid = 0,\n");
489 fprintf(outfp, "\t.version = 0,\n");
490 fprintf(outfp, "\t.type = 0,\n");
491 fprintf(outfp, "\t.table = 0,\n");
492 fprintf(outfp, "},\n");
493
494 /* and finally, the closing curly bracket for the struct */
495 fprintf(outfp, "};\n");
496}
497
498static int process_mapfile(FILE *outfp, char *fpath)
499{
500 int n = 16384;
501 FILE *mapfp;
502 char *save = NULL;
503 char *line, *p;
504 int line_num;
505 char *tblname;
506
507 pr_info("%s: Processing mapfile %s\n", prog, fpath);
508
509 line = malloc(n);
510 if (!line)
511 return -1;
512
513 mapfp = fopen(fpath, "r");
514 if (!mapfp) {
515 pr_info("%s: Error %s opening %s\n", prog, strerror(errno),
516 fpath);
517 return -1;
518 }
519
520 print_mapping_table_prefix(outfp);
521
522 /* Skip first line (header) */
523 p = fgets(line, n, mapfp);
524 if (!p)
525 goto out;
526
527 line_num = 1;
528 while (1) {
529 char *cpuid, *version, *type, *fname;
530
531 line_num++;
532 p = fgets(line, n, mapfp);
533 if (!p)
534 break;
535
536 if (line[0] == '#' || line[0] == '\n')
537 continue;
538
539 if (line[strlen(line)-1] != '\n') {
540 /* TODO Deal with lines longer than 16K */
541 pr_info("%s: Mapfile %s: line %d too long, aborting\n",
542 prog, fpath, line_num);
543 return -1;
544 }
545 line[strlen(line)-1] = '\0';
546
547 cpuid = strtok_r(p, ",", &save);
548 version = strtok_r(NULL, ",", &save);
549 fname = strtok_r(NULL, ",", &save);
550 type = strtok_r(NULL, ",", &save);
551
552 tblname = file_name_to_table_name(fname);
553 fprintf(outfp, "{\n");
554 fprintf(outfp, "\t.cpuid = \"%s\",\n", cpuid);
555 fprintf(outfp, "\t.version = \"%s\",\n", version);
556 fprintf(outfp, "\t.type = \"%s\",\n", type);
557
558 /*
559 * CHECK: We can't use the type (eg "core") field in the
560 * table name. For us to do that, we need to somehow tweak
561 * the other caller of file_name_to_table(), process_json()
562 * to determine the type. process_json() file has no way
563 * of knowing these are "core" events unless file name has
564 * core in it. If filename has core in it, we can safely
565 * ignore the type field here also.
566 */
567 fprintf(outfp, "\t.table = %s\n", tblname);
568 fprintf(outfp, "},\n");
569 }
570
571out:
572 print_mapping_table_suffix(outfp);
573 return 0;
574}
575
576/*
577 * If we fail to locate/process JSON and map files, create a NULL mapping
578 * table. This would at least allow perf to build even if we can't find/use
579 * the aliases.
580 */
581static void create_empty_mapping(const char *output_file)
582{
583 FILE *outfp;
584
585 pr_info("%s: Creating empty pmu_events_map[] table\n", prog);
586
587 /* Truncate file to clear any partial writes to it */
588 outfp = fopen(output_file, "w");
589 if (!outfp) {
590 perror("fopen()");
591 _Exit(1);
592 }
593
594 fprintf(outfp, "#include \"../../pmu-events/pmu-events.h\"\n");
595 print_mapping_table_prefix(outfp);
596 print_mapping_table_suffix(outfp);
597 fclose(outfp);
598}
599
600static int get_maxfds(void)
601{
602 struct rlimit rlim;
603
604 if (getrlimit(RLIMIT_NOFILE, &rlim) == 0)
605 return min((int)rlim.rlim_max / 2, 512);
606
607 return 512;
608}
609
610/*
611 * nftw() doesn't let us pass an argument to the processing function,
612 * so use a global variables.
613 */
614static FILE *eventsfp;
615static char *mapfile;
616
617static int process_one_file(const char *fpath, const struct stat *sb,
618 int typeflag, struct FTW *ftwbuf)
619{
620 char *tblname, *bname = (char *) fpath + ftwbuf->base;
621 int is_dir = typeflag == FTW_D;
622 int is_file = typeflag == FTW_F;
623 int level = ftwbuf->level;
624 int err = 0;
625
626 pr_debug("%s %d %7jd %-20s %s\n",
627 is_file ? "f" : is_dir ? "d" : "x",
628 level, sb->st_size, bname, fpath);
629
630 /* base dir */
631 if (level == 0)
632 return 0;
633
634 /* model directory, reset topic */
635 if (level == 1 && is_dir) {
636 if (close_table)
637 print_events_table_suffix(eventsfp);
638
639 /*
640 * Drop file name suffix. Replace hyphens with underscores.
641 * Fail if file name contains any alphanum characters besides
642 * underscores.
643 */
644 tblname = file_name_to_table_name(bname);
645 if (!tblname) {
646 pr_info("%s: Error determining table name for %s\n", prog,
647 bname);
648 return -1;
649 }
650
651 print_events_table_prefix(eventsfp, tblname);
652 return 0;
653 }
654
655 /*
656 * Save the mapfile name for now. We will process mapfile
657 * after processing all JSON files (so we can write out the
658 * mapping table after all PMU events tables).
659 *
660 * TODO: Allow for multiple mapfiles? Punt for now.
661 */
662 if (level == 1 && is_file) {
663 if (!strncmp(bname, "mapfile.csv", 11)) {
664 if (mapfile) {
665 pr_info("%s: Many mapfiles? Using %s, ignoring %s\n",
666 prog, mapfile, fpath);
667 } else {
668 mapfile = strdup(fpath);
669 }
670 return 0;
671 }
672
673 pr_info("%s: Ignoring file %s\n", prog, fpath);
674 return 0;
675 }
676
677 /*
678 * If the file name does not have a .json extension,
679 * ignore it. It could be a readme.txt for instance.
680 */
681 if (is_file) {
682 char *suffix = bname + strlen(bname) - 5;
683
684 if (strncmp(suffix, ".json", 5)) {
685 pr_info("%s: Ignoring file without .json suffix %s\n", prog,
686 fpath);
687 return 0;
688 }
689 }
690
691 if (level > 1 && add_topic(level, bname))
692 return -ENOMEM;
693
694 /*
695 * Assume all other files are JSON files.
696 *
697 * If mapfile refers to 'power7_core.json', we create a table
698 * named 'power7_core'. Any inconsistencies between the mapfile
699 * and directory tree could result in build failure due to table
700 * names not being found.
701 *
702 * Atleast for now, be strict with processing JSON file names.
703 * i.e. if JSON file name cannot be mapped to C-style table name,
704 * fail.
705 */
706 if (is_file) {
707 struct perf_entry_data data = {
708 .topic = get_topic(),
709 .outfp = eventsfp,
710 };
711
712 err = json_events(fpath, print_events_table_entry, &data);
713
714 free(data.topic);
715 }
716
717 return err;
718}
719
720#ifndef PATH_MAX
721#define PATH_MAX 4096
722#endif
723
724/*
725 * Starting in directory 'start_dirname', find the "mapfile.csv" and
726 * the set of JSON files for the architecture 'arch'.
727 *
728 * From each JSON file, create a C-style "PMU events table" from the
729 * JSON file (see struct pmu_event).
730 *
731 * From the mapfile, create a mapping between the CPU revisions and
732 * PMU event tables (see struct pmu_events_map).
733 *
734 * Write out the PMU events tables and the mapping table to pmu-event.c.
735 *
736 * If unable to process the JSON or arch files, create an empty mapping
737 * table so we can continue to build/use perf even if we cannot use the
738 * PMU event aliases.
739 */
740int main(int argc, char *argv[])
741{
742 int rc;
743 int maxfds;
744 char ldirname[PATH_MAX];
745
746 const char *arch;
747 const char *output_file;
748 const char *start_dirname;
749
750 prog = basename(argv[0]);
751 if (argc < 4) {
752 pr_err("Usage: %s <arch> <starting_dir> <output_file>\n", prog);
753 return 1;
754 }
755
756 arch = argv[1];
757 start_dirname = argv[2];
758 output_file = argv[3];
759
760 if (argc > 4)
761 verbose = atoi(argv[4]);
762
763 eventsfp = fopen(output_file, "w");
764 if (!eventsfp) {
765 pr_err("%s Unable to create required file %s (%s)\n",
766 prog, output_file, strerror(errno));
767 return 2;
768 }
769
770 /* Include pmu-events.h first */
771 fprintf(eventsfp, "#include \"../../pmu-events/pmu-events.h\"\n");
772
773 sprintf(ldirname, "%s/%s", start_dirname, arch);
774
775 /*
776 * The mapfile allows multiple CPUids to point to the same JSON file,
777 * so, not sure if there is a need for symlinks within the pmu-events
778 * directory.
779 *
780 * For now, treat symlinks of JSON files as regular files and create
781 * separate tables for each symlink (presumably, each symlink refers
782 * to specific version of the CPU).
783 */
784
785 maxfds = get_maxfds();
786 mapfile = NULL;
787 rc = nftw(ldirname, process_one_file, maxfds, 0);
788 if (rc && verbose) {
789 pr_info("%s: Error walking file tree %s\n", prog, ldirname);
790 goto empty_map;
791 } else if (rc) {
792 goto empty_map;
793 }
794
795 if (close_table)
796 print_events_table_suffix(eventsfp);
797
798 if (!mapfile) {
799 pr_info("%s: No CPU->JSON mapping?\n", prog);
800 goto empty_map;
801 }
802
803 if (process_mapfile(eventsfp, mapfile)) {
804 pr_info("%s: Error processing mapfile %s\n", prog, mapfile);
805 goto empty_map;
806 }
807
808 return 0;
809
810empty_map:
811 fclose(eventsfp);
812 create_empty_mapping(output_file);
813 return 0;
814}
diff --git a/tools/perf/pmu-events/jevents.h b/tools/perf/pmu-events/jevents.h
new file mode 100644
index 000000000000..b0eb2744b498
--- /dev/null
+++ b/tools/perf/pmu-events/jevents.h
@@ -0,0 +1,18 @@
1#ifndef JEVENTS_H
2#define JEVENTS_H 1
3
4int json_events(const char *fn,
5 int (*func)(void *data, char *name, char *event, char *desc,
6 char *long_desc),
7 void *data);
8char *get_cpu_str(void);
9
10#ifndef min
11#define min(x, y) ({ \
12 typeof(x) _min1 = (x); \
13 typeof(y) _min2 = (y); \
14 (void) (&_min1 == &_min2); \
15 _min1 < _min2 ? _min1 : _min2; })
16#endif
17
18#endif
diff --git a/tools/perf/pmu-events/jsmn.c b/tools/perf/pmu-events/jsmn.c
new file mode 100644
index 000000000000..11d1fa18bfa5
--- /dev/null
+++ b/tools/perf/pmu-events/jsmn.c
@@ -0,0 +1,313 @@
1/*
2 * Copyright (c) 2010 Serge A. Zaitsev
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 *
22 * Slightly modified by AK to not assume 0 terminated input.
23 */
24
25#include <stdlib.h>
26#include "jsmn.h"
27
28/*
29 * Allocates a fresh unused token from the token pool.
30 */
31static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
32 jsmntok_t *tokens, size_t num_tokens)
33{
34 jsmntok_t *tok;
35
36 if ((unsigned)parser->toknext >= num_tokens)
37 return NULL;
38 tok = &tokens[parser->toknext++];
39 tok->start = tok->end = -1;
40 tok->size = 0;
41 return tok;
42}
43
44/*
45 * Fills token type and boundaries.
46 */
47static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
48 int start, int end)
49{
50 token->type = type;
51 token->start = start;
52 token->end = end;
53 token->size = 0;
54}
55
56/*
57 * Fills next available token with JSON primitive.
58 */
59static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
60 size_t len,
61 jsmntok_t *tokens, size_t num_tokens)
62{
63 jsmntok_t *token;
64 int start;
65
66 start = parser->pos;
67
68 for (; parser->pos < len; parser->pos++) {
69 switch (js[parser->pos]) {
70#ifndef JSMN_STRICT
71 /*
72 * In strict mode primitive must be followed by ","
73 * or "}" or "]"
74 */
75 case ':':
76#endif
77 case '\t':
78 case '\r':
79 case '\n':
80 case ' ':
81 case ',':
82 case ']':
83 case '}':
84 goto found;
85 default:
86 break;
87 }
88 if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
89 parser->pos = start;
90 return JSMN_ERROR_INVAL;
91 }
92 }
93#ifdef JSMN_STRICT
94 /*
95 * In strict mode primitive must be followed by a
96 * comma/object/array.
97 */
98 parser->pos = start;
99 return JSMN_ERROR_PART;
100#endif
101
102found:
103 token = jsmn_alloc_token(parser, tokens, num_tokens);
104 if (token == NULL) {
105 parser->pos = start;
106 return JSMN_ERROR_NOMEM;
107 }
108 jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
109 parser->pos--; /* parent sees closing brackets */
110 return JSMN_SUCCESS;
111}
112
113/*
114 * Fills next token with JSON string.
115 */
116static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
117 size_t len,
118 jsmntok_t *tokens, size_t num_tokens)
119{
120 jsmntok_t *token;
121 int start = parser->pos;
122
123 /* Skip starting quote */
124 parser->pos++;
125
126 for (; parser->pos < len; parser->pos++) {
127 char c = js[parser->pos];
128
129 /* Quote: end of string */
130 if (c == '\"') {
131 token = jsmn_alloc_token(parser, tokens, num_tokens);
132 if (token == NULL) {
133 parser->pos = start;
134 return JSMN_ERROR_NOMEM;
135 }
136 jsmn_fill_token(token, JSMN_STRING, start+1,
137 parser->pos);
138 return JSMN_SUCCESS;
139 }
140
141 /* Backslash: Quoted symbol expected */
142 if (c == '\\') {
143 parser->pos++;
144 switch (js[parser->pos]) {
145 /* Allowed escaped symbols */
146 case '\"':
147 case '/':
148 case '\\':
149 case 'b':
150 case 'f':
151 case 'r':
152 case 'n':
153 case 't':
154 break;
155 /* Allows escaped symbol \uXXXX */
156 case 'u':
157 /* TODO */
158 break;
159 /* Unexpected symbol */
160 default:
161 parser->pos = start;
162 return JSMN_ERROR_INVAL;
163 }
164 }
165 }
166 parser->pos = start;
167 return JSMN_ERROR_PART;
168}
169
170/*
171 * Parse JSON string and fill tokens.
172 */
173jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
174 jsmntok_t *tokens, unsigned int num_tokens)
175{
176 jsmnerr_t r;
177 int i;
178 jsmntok_t *token;
179
180 for (; parser->pos < len; parser->pos++) {
181 char c;
182 jsmntype_t type;
183
184 c = js[parser->pos];
185 switch (c) {
186 case '{':
187 case '[':
188 token = jsmn_alloc_token(parser, tokens, num_tokens);
189 if (token == NULL)
190 return JSMN_ERROR_NOMEM;
191 if (parser->toksuper != -1)
192 tokens[parser->toksuper].size++;
193 token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
194 token->start = parser->pos;
195 parser->toksuper = parser->toknext - 1;
196 break;
197 case '}':
198 case ']':
199 type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
200 for (i = parser->toknext - 1; i >= 0; i--) {
201 token = &tokens[i];
202 if (token->start != -1 && token->end == -1) {
203 if (token->type != type)
204 return JSMN_ERROR_INVAL;
205 parser->toksuper = -1;
206 token->end = parser->pos + 1;
207 break;
208 }
209 }
210 /* Error if unmatched closing bracket */
211 if (i == -1)
212 return JSMN_ERROR_INVAL;
213 for (; i >= 0; i--) {
214 token = &tokens[i];
215 if (token->start != -1 && token->end == -1) {
216 parser->toksuper = i;
217 break;
218 }
219 }
220 break;
221 case '\"':
222 r = jsmn_parse_string(parser, js, len, tokens,
223 num_tokens);
224 if (r < 0)
225 return r;
226 if (parser->toksuper != -1)
227 tokens[parser->toksuper].size++;
228 break;
229 case '\t':
230 case '\r':
231 case '\n':
232 case ':':
233 case ',':
234 case ' ':
235 break;
236#ifdef JSMN_STRICT
237 /*
238 * In strict mode primitives are:
239 * numbers and booleans.
240 */
241 case '-':
242 case '0':
243 case '1':
244 case '2':
245 case '3':
246 case '4':
247 case '5':
248 case '6':
249 case '7':
250 case '8':
251 case '9':
252 case 't':
253 case 'f':
254 case 'n':
255#else
256 /*
257 * In non-strict mode every unquoted value
258 * is a primitive.
259 */
260 /*FALL THROUGH */
261 default:
262#endif
263 r = jsmn_parse_primitive(parser, js, len, tokens,
264 num_tokens);
265 if (r < 0)
266 return r;
267 if (parser->toksuper != -1)
268 tokens[parser->toksuper].size++;
269 break;
270
271#ifdef JSMN_STRICT
272 /* Unexpected char in strict mode */
273 default:
274 return JSMN_ERROR_INVAL;
275#endif
276 }
277 }
278
279 for (i = parser->toknext - 1; i >= 0; i--) {
280 /* Unmatched opened object or array */
281 if (tokens[i].start != -1 && tokens[i].end == -1)
282 return JSMN_ERROR_PART;
283 }
284
285 return JSMN_SUCCESS;
286}
287
288/*
289 * Creates a new parser based over a given buffer with an array of tokens
290 * available.
291 */
292void jsmn_init(jsmn_parser *parser)
293{
294 parser->pos = 0;
295 parser->toknext = 0;
296 parser->toksuper = -1;
297}
298
299const char *jsmn_strerror(jsmnerr_t err)
300{
301 switch (err) {
302 case JSMN_ERROR_NOMEM:
303 return "No enough tokens";
304 case JSMN_ERROR_INVAL:
305 return "Invalid character inside JSON string";
306 case JSMN_ERROR_PART:
307 return "The string is not a full JSON packet, more bytes expected";
308 case JSMN_SUCCESS:
309 return "Success";
310 default:
311 return "Unknown json error";
312 }
313}
diff --git a/tools/perf/pmu-events/jsmn.h b/tools/perf/pmu-events/jsmn.h
new file mode 100644
index 000000000000..d666b10cf25b
--- /dev/null
+++ b/tools/perf/pmu-events/jsmn.h
@@ -0,0 +1,67 @@
1#ifndef __JSMN_H_
2#define __JSMN_H_
3
4/*
5 * JSON type identifier. Basic types are:
6 * o Object
7 * o Array
8 * o String
9 * o Other primitive: number, boolean (true/false) or null
10 */
11typedef enum {
12 JSMN_PRIMITIVE = 0,
13 JSMN_OBJECT = 1,
14 JSMN_ARRAY = 2,
15 JSMN_STRING = 3
16} jsmntype_t;
17
18typedef enum {
19 /* Not enough tokens were provided */
20 JSMN_ERROR_NOMEM = -1,
21 /* Invalid character inside JSON string */
22 JSMN_ERROR_INVAL = -2,
23 /* The string is not a full JSON packet, more bytes expected */
24 JSMN_ERROR_PART = -3,
25 /* Everything was fine */
26 JSMN_SUCCESS = 0
27} jsmnerr_t;
28
29/*
30 * JSON token description.
31 * @param type type (object, array, string etc.)
32 * @param start start position in JSON data string
33 * @param end end position in JSON data string
34 */
35typedef struct {
36 jsmntype_t type;
37 int start;
38 int end;
39 int size;
40} jsmntok_t;
41
42/*
43 * JSON parser. Contains an array of token blocks available. Also stores
44 * the string being parsed now and current position in that string
45 */
46typedef struct {
47 unsigned int pos; /* offset in the JSON string */
48 int toknext; /* next token to allocate */
49 int toksuper; /* superior token node, e.g parent object or array */
50} jsmn_parser;
51
52/*
53 * Create JSON parser over an array of tokens
54 */
55void jsmn_init(jsmn_parser *parser);
56
57/*
58 * Run JSON parser. It parses a JSON data string into and array of tokens,
59 * each describing a single JSON object.
60 */
61jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js,
62 size_t len,
63 jsmntok_t *tokens, unsigned int num_tokens);
64
65const char *jsmn_strerror(jsmnerr_t err);
66
67#endif /* __JSMN_H_ */
diff --git a/tools/perf/pmu-events/json.c b/tools/perf/pmu-events/json.c
new file mode 100644
index 000000000000..f67bbb0aa36e
--- /dev/null
+++ b/tools/perf/pmu-events/json.c
@@ -0,0 +1,162 @@
1/* Parse JSON files using the JSMN parser. */
2
3/*
4 * Copyright (c) 2014, Intel Corporation
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
29*/
30
31#include <stdlib.h>
32#include <string.h>
33#include <sys/mman.h>
34#include <sys/stat.h>
35#include <fcntl.h>
36#include <stdio.h>
37#include <errno.h>
38#include <unistd.h>
39#include "jsmn.h"
40#include "json.h"
41#include <linux/kernel.h>
42
43
44static char *mapfile(const char *fn, size_t *size)
45{
46 unsigned ps = sysconf(_SC_PAGESIZE);
47 struct stat st;
48 char *map = NULL;
49 int err;
50 int fd = open(fn, O_RDONLY);
51
52 if (fd < 0 && verbose && fn) {
53 pr_err("Error opening events file '%s': %s\n", fn,
54 strerror(errno));
55 }
56
57 if (fd < 0)
58 return NULL;
59 err = fstat(fd, &st);
60 if (err < 0)
61 goto out;
62 *size = st.st_size;
63 map = mmap(NULL,
64 (st.st_size + ps - 1) & ~(ps - 1),
65 PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
66 if (map == MAP_FAILED)
67 map = NULL;
68out:
69 close(fd);
70 return map;
71}
72
73static void unmapfile(char *map, size_t size)
74{
75 unsigned ps = sysconf(_SC_PAGESIZE);
76 munmap(map, roundup(size, ps));
77}
78
79/*
80 * Parse json file using jsmn. Return array of tokens,
81 * and mapped file. Caller needs to free array.
82 */
83jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len)
84{
85 jsmn_parser parser;
86 jsmntok_t *tokens;
87 jsmnerr_t res;
88 unsigned sz;
89
90 *map = mapfile(fn, size);
91 if (!*map)
92 return NULL;
93 /* Heuristic */
94 sz = *size * 16;
95 tokens = malloc(sz);
96 if (!tokens)
97 goto error;
98 jsmn_init(&parser);
99 res = jsmn_parse(&parser, *map, *size, tokens,
100 sz / sizeof(jsmntok_t));
101 if (res != JSMN_SUCCESS) {
102 pr_err("%s: json error %s\n", fn, jsmn_strerror(res));
103 goto error_free;
104 }
105 if (len)
106 *len = parser.toknext;
107 return tokens;
108error_free:
109 free(tokens);
110error:
111 unmapfile(*map, *size);
112 return NULL;
113}
114
115void free_json(char *map, size_t size, jsmntok_t *tokens)
116{
117 free(tokens);
118 unmapfile(map, size);
119}
120
121static int countchar(char *map, char c, int end)
122{
123 int i;
124 int count = 0;
125 for (i = 0; i < end; i++)
126 if (map[i] == c)
127 count++;
128 return count;
129}
130
131/* Return line number of a jsmn token */
132int json_line(char *map, jsmntok_t *t)
133{
134 return countchar(map, '\n', t->start) + 1;
135}
136
137static const char * const jsmn_types[] = {
138 [JSMN_PRIMITIVE] = "primitive",
139 [JSMN_ARRAY] = "array",
140 [JSMN_OBJECT] = "object",
141 [JSMN_STRING] = "string"
142};
143
144#define LOOKUP(a, i) ((i) < (sizeof(a)/sizeof(*(a))) ? ((a)[i]) : "?")
145
146/* Return type name of a jsmn token */
147const char *json_name(jsmntok_t *t)
148{
149 return LOOKUP(jsmn_types, t->type);
150}
151
152int json_len(jsmntok_t *t)
153{
154 return t->end - t->start;
155}
156
157/* Is string t equal to s? */
158int json_streq(char *map, jsmntok_t *t, const char *s)
159{
160 unsigned len = json_len(t);
161 return len == strlen(s) && !strncasecmp(map + t->start, s, len);
162}
diff --git a/tools/perf/pmu-events/json.h b/tools/perf/pmu-events/json.h
new file mode 100644
index 000000000000..278ebd32cfb6
--- /dev/null
+++ b/tools/perf/pmu-events/json.h
@@ -0,0 +1,38 @@
1#ifndef JSON_H
2#define JSON_H 1
3
4#include "jsmn.h"
5
6jsmntok_t *parse_json(const char *fn, char **map, size_t *size, int *len);
7void free_json(char *map, size_t size, jsmntok_t *tokens);
8int json_line(char *map, jsmntok_t *t);
9const char *json_name(jsmntok_t *t);
10int json_streq(char *map, jsmntok_t *t, const char *s);
11int json_len(jsmntok_t *t);
12
13extern int verbose;
14
15#include <stdbool.h>
16
17extern int eprintf(int level, int var, const char *fmt, ...);
18#define pr_fmt(fmt) fmt
19
20#define pr_err(fmt, ...) \
21 eprintf(0, verbose, pr_fmt(fmt), ##__VA_ARGS__)
22
23#define pr_info(fmt, ...) \
24 eprintf(1, verbose, pr_fmt(fmt), ##__VA_ARGS__)
25
26#define pr_debug(fmt, ...) \
27 eprintf(2, verbose, pr_fmt(fmt), ##__VA_ARGS__)
28
29#ifndef roundup
30#define roundup(x, y) ( \
31{ \
32 const typeof(y) __y = y; \
33 (((x) + (__y - 1)) / __y) * __y; \
34} \
35)
36#endif
37
38#endif
diff --git a/tools/perf/pmu-events/pmu-events.h b/tools/perf/pmu-events/pmu-events.h
new file mode 100644
index 000000000000..2eaef595d8a0
--- /dev/null
+++ b/tools/perf/pmu-events/pmu-events.h
@@ -0,0 +1,37 @@
1#ifndef PMU_EVENTS_H
2#define PMU_EVENTS_H
3
4/*
5 * Describe each PMU event. Each CPU has a table of PMU events.
6 */
7struct pmu_event {
8 const char *name;
9 const char *event;
10 const char *desc;
11 const char *topic;
12 const char *long_desc;
13};
14
15/*
16 *
17 * Map a CPU to its table of PMU events. The CPU is identified by the
18 * cpuid field, which is an arch-specific identifier for the CPU.
19 * The identifier specified in tools/perf/pmu-events/arch/xxx/mapfile
20 * must match the get_cpustr() in tools/perf/arch/xxx/util/header.c)
21 *
22 * The cpuid can contain any character other than the comma.
23 */
24struct pmu_events_map {
25 const char *cpuid;
26 const char *version;
27 const char *type; /* core, uncore etc */
28 struct pmu_event *table;
29};
30
31/*
32 * Global table mapping each known CPU for the architecture to its
33 * table of PMU events.
34 */
35extern struct pmu_events_map pmu_events_map[];
36
37#endif
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/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 66a28982547b..8a4ce492f7b2 100644
--- a/tools/perf/tests/Build
+++ b/tools/perf/tests/Build
@@ -39,6 +39,9 @@ perf-y += stat.o
39perf-y += event_update.o 39perf-y += event_update.o
40perf-y += event-times.o 40perf-y += event-times.o
41perf-y += backward-ring-buffer.o 41perf-y += backward-ring-buffer.o
42perf-y += sdt.o
43perf-y += is_printable_array.o
44perf-y += bitmap.o
42 45
43$(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
44 $(call rule_mkdir) 47 $(call rule_mkdir)
@@ -68,7 +71,7 @@ $(OUTPUT)tests/llvm-src-relocation.c: tests/bpf-script-test-relocation.c tests/B
68 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@ 71 $(Q)sed -e 's/"/\\"/g' -e 's/\(.*\)/"\1\\n"/g' $< >> $@
69 $(Q)echo ';' >> $@ 72 $(Q)echo ';' >> $@
70 73
71ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64)) 74ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64 powerpc))
72perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o 75perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
73endif 76endif
74 77
diff --git a/tools/perf/tests/backward-ring-buffer.c b/tools/perf/tests/backward-ring-buffer.c
index d9ba991a9a30..e6d1816e431a 100644
--- a/tools/perf/tests/backward-ring-buffer.c
+++ b/tools/perf/tests/backward-ring-buffer.c
@@ -31,8 +31,8 @@ static int count_samples(struct perf_evlist *evlist, int *sample_count,
31 for (i = 0; i < evlist->nr_mmaps; i++) { 31 for (i = 0; i < evlist->nr_mmaps; i++) {
32 union perf_event *event; 32 union perf_event *event;
33 33
34 perf_evlist__mmap_read_catchup(evlist, i); 34 perf_mmap__read_catchup(&evlist->backward_mmap[i]);
35 while ((event = perf_evlist__mmap_read_backward(evlist, i)) != NULL) { 35 while ((event = perf_mmap__read_backward(&evlist->backward_mmap[i])) != NULL) {
36 const u32 type = event->header.type; 36 const u32 type = event->header.type;
37 37
38 switch (type) { 38 switch (type) {
@@ -60,7 +60,7 @@ static int do_test(struct perf_evlist *evlist, int mmap_pages,
60 err = perf_evlist__mmap(evlist, mmap_pages, true); 60 err = perf_evlist__mmap(evlist, mmap_pages, true);
61 if (err < 0) { 61 if (err < 0) {
62 pr_debug("perf_evlist__mmap: %s\n", 62 pr_debug("perf_evlist__mmap: %s\n",
63 strerror_r(errno, sbuf, sizeof(sbuf))); 63 str_error_r(errno, sbuf, sizeof(sbuf)));
64 return TEST_FAIL; 64 return TEST_FAIL;
65 } 65 }
66 66
@@ -97,7 +97,7 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
97 97
98 evlist = perf_evlist__new(); 98 evlist = perf_evlist__new();
99 if (!evlist) { 99 if (!evlist) {
100 pr_debug("No ehough memory to create evlist\n"); 100 pr_debug("No enough memory to create evlist\n");
101 return TEST_FAIL; 101 return TEST_FAIL;
102 } 102 }
103 103
@@ -108,7 +108,11 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
108 } 108 }
109 109
110 bzero(&parse_error, sizeof(parse_error)); 110 bzero(&parse_error, sizeof(parse_error));
111 err = parse_events(evlist, "syscalls:sys_enter_prctl", &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);
112 if (err) { 116 if (err) {
113 pr_debug("Failed to parse tracepoint event, try use root\n"); 117 pr_debug("Failed to parse tracepoint event, try use root\n");
114 ret = TEST_SKIP; 118 ret = TEST_SKIP;
@@ -117,14 +121,10 @@ int test__backward_ring_buffer(int subtest __maybe_unused)
117 121
118 perf_evlist__config(evlist, &opts, NULL); 122 perf_evlist__config(evlist, &opts, NULL);
119 123
120 /* Set backward bit, ring buffer should be writing from end */
121 evlist__for_each(evlist, evsel)
122 evsel->attr.write_backward = 1;
123
124 err = perf_evlist__open(evlist); 124 err = perf_evlist__open(evlist);
125 if (err < 0) { 125 if (err < 0) {
126 pr_debug("perf_evlist__open: %s\n", 126 pr_debug("perf_evlist__open: %s\n",
127 strerror_r(errno, sbuf, sizeof(sbuf))); 127 str_error_r(errno, sbuf, sizeof(sbuf)));
128 goto out_delete_evlist; 128 goto out_delete_evlist;
129 } 129 }
130 130
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 f31eed31c1a9..2673e86ed50f 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
@@ -125,7 +125,7 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
125 /* Instead of perf_evlist__new_default, don't add default events */ 125 /* Instead of perf_evlist__new_default, don't add default events */
126 evlist = perf_evlist__new(); 126 evlist = perf_evlist__new();
127 if (!evlist) { 127 if (!evlist) {
128 pr_debug("No ehough memory to create evlist\n"); 128 pr_debug("No enough memory to create evlist\n");
129 return TEST_FAIL; 129 return TEST_FAIL;
130 } 130 }
131 131
@@ -143,14 +143,14 @@ static int do_test(struct bpf_object *obj, int (*func)(void),
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 0e95c20ecf6e..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,
@@ -212,6 +214,22 @@ static struct test generic_tests[] = {
212 .func = test__backward_ring_buffer, 214 .func = test__backward_ring_buffer,
213 }, 215 },
214 { 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 {
215 .func = NULL, 233 .func = NULL,
216 }, 234 },
217}; 235};
@@ -247,44 +265,51 @@ static bool perf_test__matches(struct test *test, int curr, int argc, const char
247 265
248static int run_test(struct test *test, int subtest) 266static int run_test(struct test *test, int subtest)
249{ 267{
250 int status, err = -1, child = fork(); 268 int status, err = -1, child = dont_fork ? 0 : fork();
251 char sbuf[STRERR_BUFSIZE]; 269 char sbuf[STRERR_BUFSIZE];
252 270
253 if (child < 0) { 271 if (child < 0) {
254 pr_err("failed to fork test: %s\n", 272 pr_err("failed to fork test: %s\n",
255 strerror_r(errno, sbuf, sizeof(sbuf))); 273 str_error_r(errno, sbuf, sizeof(sbuf)));
256 return -1; 274 return -1;
257 } 275 }
258 276
259 if (!child) { 277 if (!child) {
260 pr_debug("test child forked, pid %d\n", getpid()); 278 if (!dont_fork) {
261 if (!verbose) { 279 pr_debug("test child forked, pid %d\n", getpid());
262 int nullfd = open("/dev/null", O_WRONLY); 280
263 if (nullfd >= 0) { 281 if (!verbose) {
264 close(STDERR_FILENO); 282 int nullfd = open("/dev/null", O_WRONLY);
265 close(STDOUT_FILENO); 283
266 284 if (nullfd >= 0) {
267 dup2(nullfd, STDOUT_FILENO); 285 close(STDERR_FILENO);
268 dup2(STDOUT_FILENO, STDERR_FILENO); 286 close(STDOUT_FILENO);
269 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);
270 } 295 }
271 } else {
272 signal(SIGSEGV, sighandler_dump_stack);
273 signal(SIGFPE, sighandler_dump_stack);
274 } 296 }
275 297
276 err = test->func(subtest); 298 err = test->func(subtest);
277 exit(err); 299 if (!dont_fork)
300 exit(err);
278 } 301 }
279 302
280 wait(&status); 303 if (!dont_fork) {
304 wait(&status);
281 305
282 if (WIFEXITED(status)) { 306 if (WIFEXITED(status)) {
283 err = (signed char)WEXITSTATUS(status); 307 err = (signed char)WEXITSTATUS(status);
284 pr_debug("test child finished with %d\n", err); 308 pr_debug("test child finished with %d\n", err);
285 } else if (WIFSIGNALED(status)) { 309 } else if (WIFSIGNALED(status)) {
286 err = -1; 310 err = -1;
287 pr_debug("test child interrupted\n"); 311 pr_debug("test child interrupted\n");
312 }
288 } 313 }
289 314
290 return err; 315 return err;
@@ -425,6 +450,8 @@ int cmd_test(int argc, const char **argv, const char *prefix __maybe_unused)
425 OPT_STRING('s', "skip", &skip, "tests", "tests to skip"), 450 OPT_STRING('s', "skip", &skip, "tests", "tests to skip"),
426 OPT_INCR('v', "verbose", &verbose, 451 OPT_INCR('v', "verbose", &verbose,
427 "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"),
428 OPT_END() 455 OPT_END()
429 }; 456 };
430 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 68a69a195545..ff5bc6363a79 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 }
@@ -221,7 +263,7 @@ static int read_object_code(u64 addr, size_t len, u8 cpumode,
221 * Converting addresses for use by objdump requires more information. 263 * Converting addresses for use by objdump requires more information.
222 * map__load() does that. See map__rip_2objdump() for details. 264 * map__load() does that. See map__rip_2objdump() for details.
223 */ 265 */
224 if (map__load(al.map, NULL)) 266 if (map__load(al.map))
225 return -1; 267 return -1;
226 268
227 /* objdump struggles with kcore - try each map only once */ 269 /* objdump struggles with kcore - try each map only once */
@@ -469,7 +511,7 @@ static int do_test_code_reading(bool try_kcore)
469 511
470 /* Load kernel map */ 512 /* Load kernel map */
471 map = machine__kernel_map(machine); 513 map = machine__kernel_map(machine);
472 ret = map__load(map, NULL); 514 ret = map__load(map);
473 if (ret < 0) { 515 if (ret < 0) {
474 pr_debug("map__load failed\n"); 516 pr_debug("map__load failed\n");
475 goto out_err; 517 goto out_err;
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 8cf0d9e189a8..13725e09ba22 100644
--- a/tools/perf/tests/dso-data.c
+++ b/tools/perf/tests/dso-data.c
@@ -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/dwarf-unwind.c b/tools/perf/tests/dwarf-unwind.c
index 8f6eb853aaf7..1046491de4b2 100644
--- a/tools/perf/tests/dwarf-unwind.c
+++ b/tools/perf/tests/dwarf-unwind.c
@@ -11,7 +11,7 @@
11#include "thread.h" 11#include "thread.h"
12#include "callchain.h" 12#include "callchain.h"
13 13
14#if defined (__x86_64__) || defined (__i386__) 14#if defined (__x86_64__) || defined (__i386__) || defined (__powerpc__)
15#include "arch-tests.h" 15#include "arch-tests.h"
16#endif 16#endif
17 17
diff --git a/tools/perf/tests/event-times.c b/tools/perf/tests/event-times.c
index 95fb744f6628..19ef77bd6eb4 100644
--- a/tools/perf/tests/event-times.c
+++ b/tools/perf/tests/event-times.c
@@ -37,7 +37,7 @@ static int attach__enable_on_exec(struct perf_evlist *evlist)
37 err = perf_evlist__open(evlist); 37 err = perf_evlist__open(evlist);
38 if (err < 0) { 38 if (err < 0) {
39 pr_debug("perf_evlist__open: %s\n", 39 pr_debug("perf_evlist__open: %s\n",
40 strerror_r(errno, sbuf, sizeof(sbuf))); 40 str_error_r(errno, sbuf, sizeof(sbuf)));
41 return err; 41 return err;
42 } 42 }
43 43
@@ -200,8 +200,7 @@ static int test_times(int (attach)(struct perf_evlist *),
200 count.ena, count.run); 200 count.ena, count.run);
201 201
202out_err: 202out_err:
203 if (evlist) 203 perf_evlist__delete(evlist);
204 perf_evlist__delete(evlist);
205 return !err ? TEST_OK : TEST_FAIL; 204 return !err ? TEST_OK : TEST_FAIL;
206} 205}
207 206
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_cumulate.c b/tools/perf/tests/hists_cumulate.c
index a9e3db3afac4..9fd54b79a788 100644
--- a/tools/perf/tests/hists_cumulate.c
+++ b/tools/perf/tests/hists_cumulate.c
@@ -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 e846f8c42013..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,
@@ -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 acf5a1301c07..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);
@@ -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/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/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 ad1cb63139a7..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) {
diff --git a/tools/perf/tests/openat-syscall-tp-fields.c b/tools/perf/tests/openat-syscall-tp-fields.c
index 4344fe482c1d..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 = {
@@ -51,14 +58,14 @@ int test__syscall_openat_tp_fields(int subtest __maybe_unused)
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 b836ee6a8d9b..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"
@@ -104,7 +107,7 @@ int test__PERF_RECORD(int subtest __maybe_unused)
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 39a689bf7574..7ddbe267d0ac 100644
--- a/tools/perf/tests/switch-tracking.c
+++ b/tools/perf/tests/switch-tracking.c
@@ -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 c57e72c826d2..7c196c585472 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -87,6 +87,10 @@ int test__synthesize_stat_round(int subtest);
87int test__event_update(int subtest); 87int test__event_update(int subtest);
88int test__event_times(int subtest); 88int test__event_times(int subtest);
89int test__backward_ring_buffer(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);
90 94
91#if defined(__arm__) || defined(__aarch64__) 95#if defined(__arm__) || defined(__aarch64__)
92#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 e63abab7d5a1..a5082331f246 100644
--- a/tools/perf/tests/vmlinux-kallsyms.c
+++ b/tools/perf/tests/vmlinux-kallsyms.c
@@ -8,14 +8,6 @@
8#include "debug.h" 8#include "debug.h"
9#include "machine.h" 9#include "machine.h"
10 10
11static int vmlinux_matches_kallsyms_filter(struct map *map __maybe_unused,
12 struct symbol *sym)
13{
14 bool *visited = symbol__priv(sym);
15 *visited = true;
16 return 0;
17}
18
19#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x)) 11#define UM(x) kallsyms_map->unmap_ip(kallsyms_map, (x))
20 12
21int test__vmlinux_matches_kallsyms(int subtest __maybe_unused) 13int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
@@ -28,6 +20,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
28 enum map_type type = MAP__FUNCTION; 20 enum map_type type = MAP__FUNCTION;
29 struct maps *maps = &vmlinux.kmaps.maps[type]; 21 struct maps *maps = &vmlinux.kmaps.maps[type];
30 u64 mem_start, mem_end; 22 u64 mem_start, mem_end;
23 bool header_printed;
31 24
32 /* 25 /*
33 * Step 1: 26 * Step 1:
@@ -61,7 +54,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
61 * be compacted against the list of modules found in the "vmlinux" 54 * 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. 55 * code and with the one got from /proc/modules from the "kallsyms" code.
63 */ 56 */
64 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true, NULL) <= 0) { 57 if (__machine__load_kallsyms(&kallsyms, "/proc/kallsyms", type, true) <= 0) {
65 pr_debug("dso__load_kallsyms "); 58 pr_debug("dso__load_kallsyms ");
66 goto out; 59 goto out;
67 } 60 }
@@ -99,8 +92,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
99 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines 92 * maps__reloc_vmlinux will notice and set proper ->[un]map_ip routines
100 * to fixup the symbols. 93 * to fixup the symbols.
101 */ 94 */
102 if (machine__load_vmlinux_path(&vmlinux, type, 95 if (machine__load_vmlinux_path(&vmlinux, type) <= 0) {
103 vmlinux_matches_kallsyms_filter) <= 0) {
104 pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n"); 96 pr_debug("Couldn't find a vmlinux that matches the kernel running on this machine, skipping test\n");
105 err = TEST_SKIP; 97 err = TEST_SKIP;
106 goto out; 98 goto out;
@@ -126,7 +118,7 @@ int test__vmlinux_matches_kallsyms(int subtest __maybe_unused)
126 mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end); 118 mem_end = vmlinux_map->unmap_ip(vmlinux_map, sym->end);
127 119
128 first_pair = machine__find_kernel_symbol(&kallsyms, type, 120 first_pair = machine__find_kernel_symbol(&kallsyms, type,
129 mem_start, NULL, NULL); 121 mem_start, NULL);
130 pair = first_pair; 122 pair = first_pair;
131 123
132 if (pair && UM(pair->start) == mem_start) { 124 if (pair && UM(pair->start) == mem_start) {
@@ -143,7 +135,7 @@ next_pair:
143 */ 135 */
144 s64 skew = mem_end - UM(pair->end); 136 s64 skew = mem_end - UM(pair->end);
145 if (llabs(skew) >= page_size) 137 if (llabs(skew) >= page_size)
146 pr_debug("%#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n", 138 pr_debug("WARN: %#" PRIx64 ": diff end addr for %s v: %#" PRIx64 " k: %#" PRIx64 "\n",
147 mem_start, sym->name, mem_end, 139 mem_start, sym->name, mem_end,
148 UM(pair->end)); 140 UM(pair->end));
149 141
@@ -154,22 +146,23 @@ next_pair:
154 * kallsyms. 146 * kallsyms.
155 */ 147 */
156 continue; 148 continue;
157
158 } else { 149 } else {
159 pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL, NULL); 150 pair = machine__find_kernel_symbol_by_name(&kallsyms, type, sym->name, NULL);
160 if (pair) { 151 if (pair) {
161 if (UM(pair->start) == mem_start) 152 if (UM(pair->start) == mem_start)
162 goto next_pair; 153 goto next_pair;
163 154
164 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", 155 pr_debug("WARN: %#" PRIx64 ": diff name v: %s k: %s\n",
165 mem_start, sym->name, pair->name); 156 mem_start, sym->name, pair->name);
166 } else { 157 } else {
167 pr_debug("%#" PRIx64 ": diff name v: %s k: %s\n", 158 pr_debug("WARN: %#" PRIx64 ": diff name v: %s k: %s\n",
168 mem_start, sym->name, first_pair->name); 159 mem_start, sym->name, first_pair->name);
169 } 160 }
161
162 continue;
170 } 163 }
171 } else 164 } else
172 pr_debug("%#" PRIx64 ": %s not on kallsyms\n", 165 pr_debug("ERR : %#" PRIx64 ": %s not on kallsyms\n",
173 mem_start, sym->name); 166 mem_start, sym->name);
174 167
175 err = -1; 168 err = -1;
@@ -178,7 +171,7 @@ next_pair:
178 if (!verbose) 171 if (!verbose)
179 goto out; 172 goto out;
180 173
181 pr_info("Maps only in vmlinux:\n"); 174 header_printed = false;
182 175
183 for (map = maps__first(maps); map; map = map__next(map)) { 176 for (map = maps__first(maps); map; map = map__next(map)) {
184 struct map * 177 struct map *
@@ -192,13 +185,18 @@ next_pair:
192 (map->dso->kernel ? 185 (map->dso->kernel ?
193 map->dso->short_name : 186 map->dso->short_name :
194 map->dso->name)); 187 map->dso->name));
195 if (pair) 188 if (pair) {
196 pair->priv = 1; 189 pair->priv = 1;
197 else 190 } else {
191 if (!header_printed) {
192 pr_info("WARN: Maps only in vmlinux:\n");
193 header_printed = true;
194 }
198 map__fprintf(map, stderr); 195 map__fprintf(map, stderr);
196 }
199 } 197 }
200 198
201 pr_info("Maps in vmlinux with a different name in kallsyms:\n"); 199 header_printed = false;
202 200
203 for (map = maps__first(maps); map; map = map__next(map)) { 201 for (map = maps__first(maps); map; map = map__next(map)) {
204 struct map *pair; 202 struct map *pair;
@@ -211,24 +209,33 @@ next_pair:
211 continue; 209 continue;
212 210
213 if (pair->start == mem_start) { 211 if (pair->start == mem_start) {
214 pair->priv = 1; 212 if (!header_printed) {
215 pr_info(" %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", 213 pr_info("WARN: Maps in vmlinux with a different name in kallsyms:\n");
214 header_printed = true;
215 }
216
217 pr_info("WARN: %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as",
216 map->start, map->end, map->pgoff, map->dso->name); 218 map->start, map->end, map->pgoff, map->dso->name);
217 if (mem_end != pair->end) 219 if (mem_end != pair->end)
218 pr_info(":\n*%" PRIx64 "-%" PRIx64 " %" PRIx64, 220 pr_info(":\nWARN: *%" PRIx64 "-%" PRIx64 " %" PRIx64,
219 pair->start, pair->end, pair->pgoff); 221 pair->start, pair->end, pair->pgoff);
220 pr_info(" %s\n", pair->dso->name); 222 pr_info(" %s\n", pair->dso->name);
221 pair->priv = 1; 223 pair->priv = 1;
222 } 224 }
223 } 225 }
224 226
225 pr_info("Maps only in kallsyms:\n"); 227 header_printed = false;
226 228
227 maps = &kallsyms.kmaps.maps[type]; 229 maps = &kallsyms.kmaps.maps[type];
228 230
229 for (map = maps__first(maps); map; map = map__next(map)) { 231 for (map = maps__first(maps); map; map = map__next(map)) {
230 if (!map->priv) 232 if (!map->priv) {
233 if (!header_printed) {
234 pr_info("WARN: Maps only in kallsyms:\n");
235 header_printed = true;
236 }
231 map__fprintf(map, stderr); 237 map__fprintf(map, stderr);
238 }
232 } 239 }
233out: 240out:
234 machine__exit(&kallsyms); 241 machine__exit(&kallsyms);
diff --git a/tools/perf/trace/beauty/eventfd.c b/tools/perf/trace/beauty/eventfd.c
index d64f4a9128a1..b08f21eb6f4d 100644
--- a/tools/perf/trace/beauty/eventfd.c
+++ b/tools/perf/trace/beauty/eventfd.c
@@ -1,5 +1,3 @@
1#include <sys/eventfd.h>
2
3#ifndef EFD_SEMAPHORE 1#ifndef EFD_SEMAPHORE
4#define EFD_SEMAPHORE 1 2#define EFD_SEMAPHORE 1
5#endif 3#endif
diff --git a/tools/perf/trace/beauty/flock.c b/tools/perf/trace/beauty/flock.c
index 021bb48c6336..74613703a14e 100644
--- a/tools/perf/trace/beauty/flock.c
+++ b/tools/perf/trace/beauty/flock.c
@@ -1,3 +1,20 @@
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
1 18
2static size_t syscall_arg__scnprintf_flock(char *bf, size_t size, 19static size_t syscall_arg__scnprintf_flock(char *bf, size_t size,
3 struct syscall_arg *arg) 20 struct syscall_arg *arg)
diff --git a/tools/perf/trace/beauty/futex_op.c b/tools/perf/trace/beauty/futex_op.c
index e2476211f22d..bfd3359b09b6 100644
--- a/tools/perf/trace/beauty/futex_op.c
+++ b/tools/perf/trace/beauty/futex_op.c
@@ -1,5 +1,21 @@
1#include <linux/futex.h> 1#include <linux/futex.h>
2 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
3static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg) 19static size_t syscall_arg__scnprintf_futex_op(char *bf, size_t size, struct syscall_arg *arg)
4{ 20{
5 enum syscall_futex_args { 21 enum syscall_futex_args {
diff --git a/tools/perf/trace/beauty/mmap.c b/tools/perf/trace/beauty/mmap.c
index 3444a4d5382d..fd710ab33684 100644
--- a/tools/perf/trace/beauty/mmap.c
+++ b/tools/perf/trace/beauty/mmap.c
@@ -1,4 +1,4 @@
1#include <sys/mman.h> 1#include <uapi/linux/mman.h>
2 2
3static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size, 3static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
4 struct syscall_arg *arg) 4 struct syscall_arg *arg)
@@ -16,9 +16,7 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
16 P_MMAP_PROT(EXEC); 16 P_MMAP_PROT(EXEC);
17 P_MMAP_PROT(READ); 17 P_MMAP_PROT(READ);
18 P_MMAP_PROT(WRITE); 18 P_MMAP_PROT(WRITE);
19#ifdef PROT_SEM
20 P_MMAP_PROT(SEM); 19 P_MMAP_PROT(SEM);
21#endif
22 P_MMAP_PROT(GROWSDOWN); 20 P_MMAP_PROT(GROWSDOWN);
23 P_MMAP_PROT(GROWSUP); 21 P_MMAP_PROT(GROWSUP);
24#undef P_MMAP_PROT 22#undef P_MMAP_PROT
@@ -31,10 +29,6 @@ static size_t syscall_arg__scnprintf_mmap_prot(char *bf, size_t size,
31 29
32#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot 30#define SCA_MMAP_PROT syscall_arg__scnprintf_mmap_prot
33 31
34#ifndef MAP_STACK
35# define MAP_STACK 0x20000
36#endif
37
38static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size, 32static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
39 struct syscall_arg *arg) 33 struct syscall_arg *arg)
40{ 34{
@@ -48,26 +42,20 @@ static size_t syscall_arg__scnprintf_mmap_flags(char *bf, size_t size,
48 42
49 P_MMAP_FLAG(SHARED); 43 P_MMAP_FLAG(SHARED);
50 P_MMAP_FLAG(PRIVATE); 44 P_MMAP_FLAG(PRIVATE);
51#ifdef MAP_32BIT
52 P_MMAP_FLAG(32BIT); 45 P_MMAP_FLAG(32BIT);
53#endif
54 P_MMAP_FLAG(ANONYMOUS); 46 P_MMAP_FLAG(ANONYMOUS);
55 P_MMAP_FLAG(DENYWRITE); 47 P_MMAP_FLAG(DENYWRITE);
56 P_MMAP_FLAG(EXECUTABLE); 48 P_MMAP_FLAG(EXECUTABLE);
57 P_MMAP_FLAG(FILE); 49 P_MMAP_FLAG(FILE);
58 P_MMAP_FLAG(FIXED); 50 P_MMAP_FLAG(FIXED);
59 P_MMAP_FLAG(GROWSDOWN); 51 P_MMAP_FLAG(GROWSDOWN);
60#ifdef MAP_HUGETLB
61 P_MMAP_FLAG(HUGETLB); 52 P_MMAP_FLAG(HUGETLB);
62#endif
63 P_MMAP_FLAG(LOCKED); 53 P_MMAP_FLAG(LOCKED);
64 P_MMAP_FLAG(NONBLOCK); 54 P_MMAP_FLAG(NONBLOCK);
65 P_MMAP_FLAG(NORESERVE); 55 P_MMAP_FLAG(NORESERVE);
66 P_MMAP_FLAG(POPULATE); 56 P_MMAP_FLAG(POPULATE);
67 P_MMAP_FLAG(STACK); 57 P_MMAP_FLAG(STACK);
68#ifdef MAP_UNINITIALIZED
69 P_MMAP_FLAG(UNINITIALIZED); 58 P_MMAP_FLAG(UNINITIALIZED);
70#endif
71#undef P_MMAP_FLAG 59#undef P_MMAP_FLAG
72 60
73 if (flags) 61 if (flags)
@@ -90,9 +78,7 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
90 } 78 }
91 79
92 P_MREMAP_FLAG(MAYMOVE); 80 P_MREMAP_FLAG(MAYMOVE);
93#ifdef MREMAP_FIXED
94 P_MREMAP_FLAG(FIXED); 81 P_MREMAP_FLAG(FIXED);
95#endif
96#undef P_MREMAP_FLAG 82#undef P_MREMAP_FLAG
97 83
98 if (flags) 84 if (flags)
@@ -103,18 +89,6 @@ static size_t syscall_arg__scnprintf_mremap_flags(char *bf, size_t size,
103 89
104#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags 90#define SCA_MREMAP_FLAGS syscall_arg__scnprintf_mremap_flags
105 91
106#ifndef MADV_HWPOISON
107#define MADV_HWPOISON 100
108#endif
109
110#ifndef MADV_MERGEABLE
111#define MADV_MERGEABLE 12
112#endif
113
114#ifndef MADV_UNMERGEABLE
115#define MADV_UNMERGEABLE 13
116#endif
117
118static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size, 92static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
119 struct syscall_arg *arg) 93 struct syscall_arg *arg)
120{ 94{
@@ -127,28 +101,19 @@ static size_t syscall_arg__scnprintf_madvise_behavior(char *bf, size_t size,
127 P_MADV_BHV(SEQUENTIAL); 101 P_MADV_BHV(SEQUENTIAL);
128 P_MADV_BHV(WILLNEED); 102 P_MADV_BHV(WILLNEED);
129 P_MADV_BHV(DONTNEED); 103 P_MADV_BHV(DONTNEED);
104 P_MADV_BHV(FREE);
130 P_MADV_BHV(REMOVE); 105 P_MADV_BHV(REMOVE);
131 P_MADV_BHV(DONTFORK); 106 P_MADV_BHV(DONTFORK);
132 P_MADV_BHV(DOFORK); 107 P_MADV_BHV(DOFORK);
133 P_MADV_BHV(HWPOISON); 108 P_MADV_BHV(HWPOISON);
134#ifdef MADV_SOFT_OFFLINE
135 P_MADV_BHV(SOFT_OFFLINE); 109 P_MADV_BHV(SOFT_OFFLINE);
136#endif
137 P_MADV_BHV(MERGEABLE); 110 P_MADV_BHV(MERGEABLE);
138 P_MADV_BHV(UNMERGEABLE); 111 P_MADV_BHV(UNMERGEABLE);
139#ifdef MADV_HUGEPAGE
140 P_MADV_BHV(HUGEPAGE); 112 P_MADV_BHV(HUGEPAGE);
141#endif
142#ifdef MADV_NOHUGEPAGE
143 P_MADV_BHV(NOHUGEPAGE); 113 P_MADV_BHV(NOHUGEPAGE);
144#endif
145#ifdef MADV_DONTDUMP
146 P_MADV_BHV(DONTDUMP); 114 P_MADV_BHV(DONTDUMP);
147#endif
148#ifdef MADV_DODUMP
149 P_MADV_BHV(DODUMP); 115 P_MADV_BHV(DODUMP);
150#endif 116#undef P_MADV_BHV
151#undef P_MADV_PHV
152 default: break; 117 default: break;
153 } 118 }
154 119
diff --git a/tools/perf/trace/beauty/msg_flags.c b/tools/perf/trace/beauty/msg_flags.c
index 07fa8a0acad6..1106c8960cc4 100644
--- a/tools/perf/trace/beauty/msg_flags.c
+++ b/tools/perf/trace/beauty/msg_flags.c
@@ -33,7 +33,6 @@ static size_t syscall_arg__scnprintf_msg_flags(char *bf, size_t size,
33 P_MSG_FLAG(OOB); 33 P_MSG_FLAG(OOB);
34 P_MSG_FLAG(PEEK); 34 P_MSG_FLAG(PEEK);
35 P_MSG_FLAG(DONTROUTE); 35 P_MSG_FLAG(DONTROUTE);
36 P_MSG_FLAG(TRYHARD);
37 P_MSG_FLAG(CTRUNC); 36 P_MSG_FLAG(CTRUNC);
38 P_MSG_FLAG(PROBE); 37 P_MSG_FLAG(PROBE);
39 P_MSG_FLAG(TRUNC); 38 P_MSG_FLAG(TRUNC);
diff --git a/tools/perf/trace/beauty/open_flags.c b/tools/perf/trace/beauty/open_flags.c
index 0f3679e0cdcf..f55a4597fc38 100644
--- a/tools/perf/trace/beauty/open_flags.c
+++ b/tools/perf/trace/beauty/open_flags.c
@@ -1,3 +1,18 @@
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
1 16
2static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size, 17static size_t syscall_arg__scnprintf_open_flags(char *bf, size_t size,
3 struct syscall_arg *arg) 18 struct syscall_arg *arg)
diff --git a/tools/perf/trace/beauty/sched_policy.c b/tools/perf/trace/beauty/sched_policy.c
index c205bc608b3c..34775295b9b3 100644
--- a/tools/perf/trace/beauty/sched_policy.c
+++ b/tools/perf/trace/beauty/sched_policy.c
@@ -9,6 +9,9 @@
9#ifndef SCHED_DEADLINE 9#ifndef SCHED_DEADLINE
10#define SCHED_DEADLINE 6 10#define SCHED_DEADLINE 6
11#endif 11#endif
12#ifndef SCHED_RESET_ON_FORK
13#define SCHED_RESET_ON_FORK 0x40000000
14#endif
12 15
13static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size, 16static size_t syscall_arg__scnprintf_sched_policy(char *bf, size_t size,
14 struct syscall_arg *arg) 17 struct syscall_arg *arg)
diff --git a/tools/perf/trace/beauty/seccomp.c b/tools/perf/trace/beauty/seccomp.c
index 213c5a7e3e92..356441bce27d 100644
--- a/tools/perf/trace/beauty/seccomp.c
+++ b/tools/perf/trace/beauty/seccomp.c
@@ -1,5 +1,3 @@
1#include <linux/seccomp.h>
2
3#ifndef SECCOMP_SET_MODE_STRICT 1#ifndef SECCOMP_SET_MODE_STRICT
4#define SECCOMP_SET_MODE_STRICT 0 2#define SECCOMP_SET_MODE_STRICT 0
5#endif 3#endif
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..4c18271c71c9 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);
@@ -496,7 +495,7 @@ static bool annotate_browser__callq(struct annotate_browser *browser,
496 if (!ins__is_call(dl->ins)) 495 if (!ins__is_call(dl->ins))
497 return false; 496 return false;
498 497
499 if (map_groups__find_ams(&target, NULL) || 498 if (map_groups__find_ams(&target) ||
500 map__rip_2objdump(target.map, target.map->map_ip(target.map, 499 map__rip_2objdump(target.map, target.map->map_ip(target.map,
501 target.addr)) != 500 target.addr)) !=
502 dl->ops.target.addr) { 501 dl->ops.target.addr) {
@@ -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 538bae880bfe..fb8e42c7507a 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,
@@ -87,8 +69,11 @@ static u32 hist_browser__nr_entries(struct hist_browser *hb)
87static void hist_browser__update_rows(struct hist_browser *hb) 69static void hist_browser__update_rows(struct hist_browser *hb)
88{ 70{
89 struct ui_browser *browser = &hb->b; 71 struct ui_browser *browser = &hb->b;
90 u16 header_offset = hb->show_headers ? 1 : 0, index_row; 72 struct hists *hists = hb->hists;
73 struct perf_hpp_list *hpp_list = hists->hpp_list;
74 u16 header_offset, index_row;
91 75
76 header_offset = hb->show_headers ? hpp_list->nr_header_lines : 0;
92 browser->rows = browser->height - header_offset; 77 browser->rows = browser->height - header_offset;
93 /* 78 /*
94 * Verify if we were at the last line and that line isn't 79 * Verify if we were at the last line and that line isn't
@@ -117,8 +102,11 @@ static void hist_browser__refresh_dimensions(struct ui_browser *browser)
117 102
118static void hist_browser__gotorc(struct hist_browser *browser, int row, int column) 103static void hist_browser__gotorc(struct hist_browser *browser, int row, int column)
119{ 104{
120 u16 header_offset = browser->show_headers ? 1 : 0; 105 struct hists *hists = browser->hists;
106 struct perf_hpp_list *hpp_list = hists->hpp_list;
107 u16 header_offset;
121 108
109 header_offset = browser->show_headers ? hpp_list->nr_header_lines : 0;
122 ui_browser__gotorc(&browser->b, row + header_offset, column); 110 ui_browser__gotorc(&browser->b, row + header_offset, column);
123} 111}
124 112
@@ -585,7 +573,12 @@ static void ui_browser__warn_lost_events(struct ui_browser *browser)
585 "Or reduce the sampling frequency."); 573 "Or reduce the sampling frequency.");
586} 574}
587 575
588static int hist_browser__run(struct hist_browser *browser, const char *help) 576static int hist_browser__title(struct hist_browser *browser, char *bf, size_t size)
577{
578 return browser->title ? browser->title(browser, bf, size) : 0;
579}
580
581int hist_browser__run(struct hist_browser *browser, const char *help)
589{ 582{
590 int key; 583 int key;
591 char title[160]; 584 char title[160];
@@ -595,7 +588,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help)
595 browser->b.entries = &browser->hists->entries; 588 browser->b.entries = &browser->hists->entries;
596 browser->b.nr_entries = hist_browser__nr_entries(browser); 589 browser->b.nr_entries = hist_browser__nr_entries(browser);
597 590
598 hists__browser_title(browser->hists, hbt, title, sizeof(title)); 591 hist_browser__title(browser, title, sizeof(title));
599 592
600 if (ui_browser__show(&browser->b, title, "%s", help) < 0) 593 if (ui_browser__show(&browser->b, title, "%s", help) < 0)
601 return -1; 594 return -1;
@@ -621,8 +614,7 @@ static int hist_browser__run(struct hist_browser *browser, const char *help)
621 ui_browser__warn_lost_events(&browser->b); 614 ui_browser__warn_lost_events(&browser->b);
622 } 615 }
623 616
624 hists__browser_title(browser->hists, 617 hist_browser__title(browser, title, sizeof(title));
625 hbt, title, sizeof(title));
626 ui_browser__show_title(&browser->b, title); 618 ui_browser__show_title(&browser->b, title);
627 continue; 619 continue;
628 } 620 }
@@ -1088,7 +1080,7 @@ struct hpp_arg {
1088 bool current_entry; 1080 bool current_entry;
1089}; 1081};
1090 1082
1091static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...) 1083int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
1092{ 1084{
1093 struct hpp_arg *arg = hpp->ptr; 1085 struct hpp_arg *arg = hpp->ptr;
1094 int ret, len; 1086 int ret, len;
@@ -1105,7 +1097,6 @@ static int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...)
1105 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent); 1097 ret = scnprintf(hpp->buf, hpp->size, fmt, len, percent);
1106 ui_browser__printf(arg->b, "%s", hpp->buf); 1098 ui_browser__printf(arg->b, "%s", hpp->buf);
1107 1099
1108 advance_hpp(hpp, ret);
1109 return ret; 1100 return ret;
1110} 1101}
1111 1102
@@ -1470,7 +1461,7 @@ static int hist_browser__show_no_entry(struct hist_browser *browser,
1470 column++ < browser->b.horiz_scroll) 1461 column++ < browser->b.horiz_scroll)
1471 continue; 1462 continue;
1472 1463
1473 ret = fmt->width(fmt, NULL, hists_to_evsel(browser->hists)); 1464 ret = fmt->width(fmt, NULL, browser->hists);
1474 1465
1475 if (first) { 1466 if (first) {
1476 /* for folded sign */ 1467 /* for folded sign */
@@ -1510,7 +1501,9 @@ static int advance_hpp_check(struct perf_hpp *hpp, int inc)
1510 return hpp->size <= 0; 1501 return hpp->size <= 0;
1511} 1502}
1512 1503
1513static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf, size_t size) 1504static int
1505hists_browser__scnprintf_headers(struct hist_browser *browser, char *buf,
1506 size_t size, int line)
1514{ 1507{
1515 struct hists *hists = browser->hists; 1508 struct hists *hists = browser->hists;
1516 struct perf_hpp dummy_hpp = { 1509 struct perf_hpp dummy_hpp = {
@@ -1520,6 +1513,7 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
1520 struct perf_hpp_fmt *fmt; 1513 struct perf_hpp_fmt *fmt;
1521 size_t ret = 0; 1514 size_t ret = 0;
1522 int column = 0; 1515 int column = 0;
1516 int span = 0;
1523 1517
1524 if (symbol_conf.use_callchain) { 1518 if (symbol_conf.use_callchain) {
1525 ret = scnprintf(buf, size, " "); 1519 ret = scnprintf(buf, size, " ");
@@ -1531,10 +1525,13 @@ static int hists_browser__scnprintf_headers(struct hist_browser *browser, char *
1531 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll) 1525 if (perf_hpp__should_skip(fmt, hists) || column++ < browser->b.horiz_scroll)
1532 continue; 1526 continue;
1533 1527
1534 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1528 ret = fmt->header(fmt, &dummy_hpp, hists, line, &span);
1535 if (advance_hpp_check(&dummy_hpp, ret)) 1529 if (advance_hpp_check(&dummy_hpp, ret))
1536 break; 1530 break;
1537 1531
1532 if (span)
1533 continue;
1534
1538 ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " "); 1535 ret = scnprintf(dummy_hpp.buf, dummy_hpp.size, " ");
1539 if (advance_hpp_check(&dummy_hpp, ret)) 1536 if (advance_hpp_check(&dummy_hpp, ret))
1540 break; 1537 break;
@@ -1568,7 +1565,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1568 if (column++ < browser->b.horiz_scroll) 1565 if (column++ < browser->b.horiz_scroll)
1569 continue; 1566 continue;
1570 1567
1571 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1568 ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL);
1572 if (advance_hpp_check(&dummy_hpp, ret)) 1569 if (advance_hpp_check(&dummy_hpp, ret))
1573 break; 1570 break;
1574 1571
@@ -1605,7 +1602,7 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1605 } 1602 }
1606 first_col = false; 1603 first_col = false;
1607 1604
1608 ret = fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 1605 ret = fmt->header(fmt, &dummy_hpp, hists, 0, NULL);
1609 dummy_hpp.buf[ret] = '\0'; 1606 dummy_hpp.buf[ret] = '\0';
1610 1607
1611 start = trim(dummy_hpp.buf); 1608 start = trim(dummy_hpp.buf);
@@ -1622,21 +1619,45 @@ static int hists_browser__scnprintf_hierarchy_headers(struct hist_browser *brows
1622 return ret; 1619 return ret;
1623} 1620}
1624 1621
1625static void hist_browser__show_headers(struct hist_browser *browser) 1622static void hists_browser__hierarchy_headers(struct hist_browser *browser)
1626{ 1623{
1627 char headers[1024]; 1624 char headers[1024];
1628 1625
1629 if (symbol_conf.report_hierarchy) 1626 hists_browser__scnprintf_hierarchy_headers(browser, headers,
1630 hists_browser__scnprintf_hierarchy_headers(browser, headers, 1627 sizeof(headers));
1631 sizeof(headers)); 1628
1632 else
1633 hists_browser__scnprintf_headers(browser, headers,
1634 sizeof(headers));
1635 ui_browser__gotorc(&browser->b, 0, 0); 1629 ui_browser__gotorc(&browser->b, 0, 0);
1636 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT); 1630 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
1637 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1); 1631 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
1638} 1632}
1639 1633
1634static void hists_browser__headers(struct hist_browser *browser)
1635{
1636 struct hists *hists = browser->hists;
1637 struct perf_hpp_list *hpp_list = hists->hpp_list;
1638
1639 int line;
1640
1641 for (line = 0; line < hpp_list->nr_header_lines; line++) {
1642 char headers[1024];
1643
1644 hists_browser__scnprintf_headers(browser, headers,
1645 sizeof(headers), line);
1646
1647 ui_browser__gotorc(&browser->b, line, 0);
1648 ui_browser__set_color(&browser->b, HE_COLORSET_ROOT);
1649 ui_browser__write_nstring(&browser->b, headers, browser->b.width + 1);
1650 }
1651}
1652
1653static void hist_browser__show_headers(struct hist_browser *browser)
1654{
1655 if (symbol_conf.report_hierarchy)
1656 hists_browser__hierarchy_headers(browser);
1657 else
1658 hists_browser__headers(browser);
1659}
1660
1640static void ui_browser__hists_init_top(struct ui_browser *browser) 1661static void ui_browser__hists_init_top(struct ui_browser *browser)
1641{ 1662{
1642 if (browser->top == NULL) { 1663 if (browser->top == NULL) {
@@ -1653,10 +1674,13 @@ static unsigned int hist_browser__refresh(struct ui_browser *browser)
1653 u16 header_offset = 0; 1674 u16 header_offset = 0;
1654 struct rb_node *nd; 1675 struct rb_node *nd;
1655 struct hist_browser *hb = container_of(browser, struct hist_browser, b); 1676 struct hist_browser *hb = container_of(browser, struct hist_browser, b);
1677 struct hists *hists = hb->hists;
1656 1678
1657 if (hb->show_headers) { 1679 if (hb->show_headers) {
1680 struct perf_hpp_list *hpp_list = hists->hpp_list;
1681
1658 hist_browser__show_headers(hb); 1682 hist_browser__show_headers(hb);
1659 header_offset = 1; 1683 header_offset = hpp_list->nr_header_lines;
1660 } 1684 }
1661 1685
1662 ui_browser__hists_init_top(browser); 1686 ui_browser__hists_init_top(browser);
@@ -2026,7 +2050,7 @@ static int hist_browser__dump(struct hist_browser *browser)
2026 fp = fopen(filename, "w"); 2050 fp = fopen(filename, "w");
2027 if (fp == NULL) { 2051 if (fp == NULL) {
2028 char bf[64]; 2052 char bf[64];
2029 const char *err = strerror_r(errno, bf, sizeof(bf)); 2053 const char *err = str_error_r(errno, bf, sizeof(bf));
2030 ui_helpline__fpush("Couldn't write to %s: %s", filename, err); 2054 ui_helpline__fpush("Couldn't write to %s: %s", filename, err);
2031 return -1; 2055 return -1;
2032 } 2056 }
@@ -2039,27 +2063,50 @@ static int hist_browser__dump(struct hist_browser *browser)
2039 return 0; 2063 return 0;
2040} 2064}
2041 2065
2042static struct hist_browser *hist_browser__new(struct hists *hists, 2066void hist_browser__init(struct hist_browser *browser,
2043 struct hist_browser_timer *hbt, 2067 struct hists *hists)
2044 struct perf_env *env) 2068{
2069 struct perf_hpp_fmt *fmt;
2070
2071 browser->hists = hists;
2072 browser->b.refresh = hist_browser__refresh;
2073 browser->b.refresh_dimensions = hist_browser__refresh_dimensions;
2074 browser->b.seek = ui_browser__hists_seek;
2075 browser->b.use_navkeypressed = true;
2076 browser->show_headers = symbol_conf.show_hist_headers;
2077
2078 hists__for_each_format(hists, fmt)
2079 ++browser->b.columns;
2080
2081 hists__reset_column_width(hists);
2082}
2083
2084struct hist_browser *hist_browser__new(struct hists *hists)
2045{ 2085{
2046 struct hist_browser *browser = zalloc(sizeof(*browser)); 2086 struct hist_browser *browser = zalloc(sizeof(*browser));
2047 2087
2088 if (browser)
2089 hist_browser__init(browser, hists);
2090
2091 return browser;
2092}
2093
2094static struct hist_browser *
2095perf_evsel_browser__new(struct perf_evsel *evsel,
2096 struct hist_browser_timer *hbt,
2097 struct perf_env *env)
2098{
2099 struct hist_browser *browser = hist_browser__new(evsel__hists(evsel));
2100
2048 if (browser) { 2101 if (browser) {
2049 browser->hists = hists; 2102 browser->hbt = hbt;
2050 browser->b.refresh = hist_browser__refresh; 2103 browser->env = env;
2051 browser->b.refresh_dimensions = hist_browser__refresh_dimensions; 2104 browser->title = perf_evsel_browser_title;
2052 browser->b.seek = ui_browser__hists_seek;
2053 browser->b.use_navkeypressed = true;
2054 browser->show_headers = symbol_conf.show_hist_headers;
2055 browser->hbt = hbt;
2056 browser->env = env;
2057 } 2105 }
2058
2059 return browser; 2106 return browser;
2060} 2107}
2061 2108
2062static void hist_browser__delete(struct hist_browser *browser) 2109void hist_browser__delete(struct hist_browser *browser)
2063{ 2110{
2064 free(browser); 2111 free(browser);
2065} 2112}
@@ -2080,10 +2127,11 @@ static inline bool is_report_browser(void *timer)
2080 return timer == NULL; 2127 return timer == NULL;
2081} 2128}
2082 2129
2083static int hists__browser_title(struct hists *hists, 2130static int perf_evsel_browser_title(struct hist_browser *browser,
2084 struct hist_browser_timer *hbt,
2085 char *bf, size_t size) 2131 char *bf, size_t size)
2086{ 2132{
2133 struct hist_browser_timer *hbt = browser->hbt;
2134 struct hists *hists = browser->hists;
2087 char unit; 2135 char unit;
2088 int printed; 2136 int printed;
2089 const struct dso *dso = hists->dso_filter; 2137 const struct dso *dso = hists->dso_filter;
@@ -2391,8 +2439,6 @@ do_zoom_dso(struct hist_browser *browser, struct popup_action *act)
2391 browser->hists->dso_filter = NULL; 2439 browser->hists->dso_filter = NULL;
2392 ui_helpline__pop(); 2440 ui_helpline__pop();
2393 } else { 2441 } else {
2394 if (map == NULL)
2395 return 0;
2396 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s DSO\"", 2442 ui_helpline__fpush("To zoom out press ESC or ENTER + \"Zoom out of %s DSO\"",
2397 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name); 2443 __map__is_kernel(map) ? "the Kernel" : map->dso->short_name);
2398 browser->hists->dso_filter = map->dso; 2444 browser->hists->dso_filter = map->dso;
@@ -2640,7 +2686,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2640 struct perf_env *env) 2686 struct perf_env *env)
2641{ 2687{
2642 struct hists *hists = evsel__hists(evsel); 2688 struct hists *hists = evsel__hists(evsel);
2643 struct hist_browser *browser = hist_browser__new(hists, hbt, env); 2689 struct hist_browser *browser = perf_evsel_browser__new(evsel, hbt, env);
2644 struct branch_info *bi; 2690 struct branch_info *bi;
2645#define MAX_OPTIONS 16 2691#define MAX_OPTIONS 16
2646 char *options[MAX_OPTIONS]; 2692 char *options[MAX_OPTIONS];
@@ -2649,7 +2695,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2649 int key = -1; 2695 int key = -1;
2650 char buf[64]; 2696 char buf[64];
2651 int delay_secs = hbt ? hbt->refresh : 0; 2697 int delay_secs = hbt ? hbt->refresh : 0;
2652 struct perf_hpp_fmt *fmt;
2653 2698
2654#define HIST_BROWSER_HELP_COMMON \ 2699#define HIST_BROWSER_HELP_COMMON \
2655 "h/?/F1 Show this window\n" \ 2700 "h/?/F1 Show this window\n" \
@@ -2708,18 +2753,6 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel, int nr_events,
2708 memset(options, 0, sizeof(options)); 2753 memset(options, 0, sizeof(options));
2709 memset(actions, 0, sizeof(actions)); 2754 memset(actions, 0, sizeof(actions));
2710 2755
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) 2756 if (symbol_conf.col_width_list_str)
2724 perf_hpp__set_user_width(symbol_conf.col_width_list_str); 2757 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
2725 2758
@@ -3185,7 +3218,7 @@ static int __perf_evlist__tui_browse_hists(struct perf_evlist *evlist,
3185 3218
3186 ui_helpline__push("Press ESC to exit"); 3219 ui_helpline__push("Press ESC to exit");
3187 3220
3188 evlist__for_each(evlist, pos) { 3221 evlist__for_each_entry(evlist, pos) {
3189 const char *ev_name = perf_evsel__name(pos); 3222 const char *ev_name = perf_evsel__name(pos);
3190 size_t line_len = strlen(ev_name) + 7; 3223 size_t line_len = strlen(ev_name) + 7;
3191 3224
@@ -3216,7 +3249,7 @@ single_entry:
3216 struct perf_evsel *pos; 3249 struct perf_evsel *pos;
3217 3250
3218 nr_entries = 0; 3251 nr_entries = 0;
3219 evlist__for_each(evlist, pos) { 3252 evlist__for_each_entry(evlist, pos) {
3220 if (perf_evsel__is_group_leader(pos)) 3253 if (perf_evsel__is_group_leader(pos))
3221 nr_entries++; 3254 nr_entries++;
3222 } 3255 }
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/browsers/map.c b/tools/perf/ui/browsers/map.c
index 80912778bb6d..98a34664bb7e 100644
--- a/tools/perf/ui/browsers/map.c
+++ b/tools/perf/ui/browsers/map.c
@@ -52,9 +52,9 @@ static int map_browser__search(struct map_browser *browser)
52 52
53 if (target[0] == '0' && tolower(target[1]) == 'x') { 53 if (target[0] == '0' && tolower(target[1]) == 'x') {
54 u64 addr = strtoull(target, NULL, 16); 54 u64 addr = strtoull(target, NULL, 16);
55 sym = map__find_symbol(browser->map, addr, NULL); 55 sym = map__find_symbol(browser->map, addr);
56 } else 56 } else
57 sym = map__find_symbol_by_name(browser->map, target, NULL); 57 sym = map__find_symbol_by_name(browser->map, target);
58 58
59 if (sym != NULL) { 59 if (sym != NULL) {
60 u32 *idx = symbol__browser_index(sym); 60 u32 *idx = symbol__browser_index(sym);
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 932adfaa05af..a4f02de7c1b5 100644
--- a/tools/perf/ui/gtk/hists.c
+++ b/tools/perf/ui/gtk/hists.c
@@ -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, 0, NULL);
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 af07ffb129ca..37388397b5bc 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,13 +230,14 @@ 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, int line __maybe_unused,
234 int *span __maybe_unused)
233{ 235{
234 int len = hpp__width_fn(fmt, hpp, evsel); 236 int len = hpp__width_fn(fmt, hpp, hists);
235 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name); 237 return scnprintf(hpp->buf, hpp->size, "%*s", len, fmt->name);
236} 238}
237 239
238static int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...) 240int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...)
239{ 241{
240 va_list args; 242 va_list args;
241 ssize_t ssize = hpp->size; 243 ssize_t ssize = hpp->size;
@@ -440,6 +442,7 @@ struct perf_hpp_fmt perf_hpp__format[] = {
440struct perf_hpp_list perf_hpp_list = { 442struct perf_hpp_list perf_hpp_list = {
441 .fields = LIST_HEAD_INIT(perf_hpp_list.fields), 443 .fields = LIST_HEAD_INIT(perf_hpp_list.fields),
442 .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts), 444 .sorts = LIST_HEAD_INIT(perf_hpp_list.sorts),
445 .nr_header_lines = 1,
443}; 446};
444 447
445#undef HPP__COLOR_PRINT_FNS 448#undef HPP__COLOR_PRINT_FNS
@@ -632,7 +635,7 @@ unsigned int hists__sort_list_width(struct hists *hists)
632 else 635 else
633 ret += 2; 636 ret += 2;
634 637
635 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); 638 ret += fmt->width(fmt, &dummy_hpp, hists);
636 } 639 }
637 640
638 if (verbose && hists__has(hists, sym)) /* Addr + origin */ 641 if (verbose && hists__has(hists, sym)) /* Addr + origin */
@@ -657,7 +660,7 @@ unsigned int hists__overhead_width(struct hists *hists)
657 else 660 else
658 ret += 2; 661 ret += 2;
659 662
660 ret += fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); 663 ret += fmt->width(fmt, &dummy_hpp, hists);
661 } 664 }
662 665
663 return ret; 666 return ret;
@@ -696,6 +699,21 @@ void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists)
696 } 699 }
697} 700}
698 701
702void hists__reset_column_width(struct hists *hists)
703{
704 struct perf_hpp_fmt *fmt;
705 struct perf_hpp_list_node *node;
706
707 hists__for_each_format(hists, fmt)
708 perf_hpp__reset_width(fmt, hists);
709
710 /* hierarchy entries have their own hpp list */
711 list_for_each_entry(node, &hists->hpp_formats, list) {
712 perf_hpp_list__for_each_format(&node->hpp, fmt)
713 perf_hpp__reset_width(fmt, hists);
714 }
715}
716
699void perf_hpp__set_user_width(const char *width_list_str) 717void perf_hpp__set_user_width(const char *width_list_str)
700{ 718{
701 struct perf_hpp_fmt *fmt; 719 struct perf_hpp_fmt *fmt;
@@ -765,7 +783,7 @@ int perf_hpp__setup_hists_formats(struct perf_hpp_list *list,
765 if (!symbol_conf.report_hierarchy) 783 if (!symbol_conf.report_hierarchy)
766 return 0; 784 return 0;
767 785
768 evlist__for_each(evlist, evsel) { 786 evlist__for_each_entry(evlist, evsel) {
769 hists = evsel__hists(evsel); 787 hists = evsel__hists(evsel);
770 788
771 perf_hpp_list__for_each_sort_list(list, fmt) { 789 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 560eb47d56f9..89d8441f9890 100644
--- a/tools/perf/ui/stdio/hist.c
+++ b/tools/perf/ui/stdio/hist.c
@@ -373,7 +373,8 @@ static size_t hist_entry_callchain__fprintf(struct hist_entry *he,
373 return 0; 373 return 0;
374} 374}
375 375
376static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp) 376int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp,
377 struct perf_hpp_list *hpp_list)
377{ 378{
378 const char *sep = symbol_conf.field_sep; 379 const char *sep = symbol_conf.field_sep;
379 struct perf_hpp_fmt *fmt; 380 struct perf_hpp_fmt *fmt;
@@ -384,7 +385,7 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
384 if (symbol_conf.exclude_other && !he->parent) 385 if (symbol_conf.exclude_other && !he->parent)
385 return 0; 386 return 0;
386 387
387 hists__for_each_format(he->hists, fmt) { 388 perf_hpp_list__for_each_format(hpp_list, fmt) {
388 if (perf_hpp__should_skip(fmt, he->hists)) 389 if (perf_hpp__should_skip(fmt, he->hists))
389 continue; 390 continue;
390 391
@@ -410,6 +411,11 @@ static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
410 return hpp->buf - start; 411 return hpp->buf - start;
411} 412}
412 413
414static int hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp)
415{
416 return __hist_entry__snprintf(he, hpp, he->hists->hpp_list);
417}
418
413static int hist_entry__hierarchy_fprintf(struct hist_entry *he, 419static int hist_entry__hierarchy_fprintf(struct hist_entry *he,
414 struct perf_hpp *hpp, 420 struct perf_hpp *hpp,
415 struct hists *hists, 421 struct hists *hists,
@@ -492,14 +498,15 @@ out:
492} 498}
493 499
494static int hist_entry__fprintf(struct hist_entry *he, size_t size, 500static int hist_entry__fprintf(struct hist_entry *he, size_t size,
495 struct hists *hists, 501 char *bf, size_t bfsz, FILE *fp,
496 char *bf, size_t bfsz, FILE *fp) 502 bool use_callchain)
497{ 503{
498 int ret; 504 int ret;
499 struct perf_hpp hpp = { 505 struct perf_hpp hpp = {
500 .buf = bf, 506 .buf = bf,
501 .size = size, 507 .size = size,
502 }; 508 };
509 struct hists *hists = he->hists;
503 u64 total_period = hists->stats.total_period; 510 u64 total_period = hists->stats.total_period;
504 511
505 if (size == 0 || size > bfsz) 512 if (size == 0 || size > bfsz)
@@ -512,7 +519,7 @@ static int hist_entry__fprintf(struct hist_entry *he, size_t size,
512 519
513 ret = fprintf(fp, "%s\n", bf); 520 ret = fprintf(fp, "%s\n", bf);
514 521
515 if (symbol_conf.use_callchain) 522 if (use_callchain)
516 ret += hist_entry_callchain__fprintf(he, total_period, 0, fp); 523 ret += hist_entry_callchain__fprintf(he, total_period, 0, fp);
517 524
518 return ret; 525 return ret;
@@ -527,8 +534,8 @@ static int print_hierarchy_indent(const char *sep, int indent,
527 return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line); 534 return fprintf(fp, "%-.*s", (indent - 2) * HIERARCHY_INDENT, line);
528} 535}
529 536
530static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp, 537static int hists__fprintf_hierarchy_headers(struct hists *hists,
531 const char *sep, FILE *fp) 538 struct perf_hpp *hpp, FILE *fp)
532{ 539{
533 bool first_node, first_col; 540 bool first_node, first_col;
534 int indent; 541 int indent;
@@ -537,6 +544,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
537 unsigned header_width = 0; 544 unsigned header_width = 0;
538 struct perf_hpp_fmt *fmt; 545 struct perf_hpp_fmt *fmt;
539 struct perf_hpp_list_node *fmt_node; 546 struct perf_hpp_list_node *fmt_node;
547 const char *sep = symbol_conf.field_sep;
540 548
541 indent = hists->nr_hpp_node; 549 indent = hists->nr_hpp_node;
542 550
@@ -548,7 +556,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
548 struct perf_hpp_list_node, list); 556 struct perf_hpp_list_node, list);
549 557
550 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) { 558 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt) {
551 fmt->header(fmt, hpp, hists_to_evsel(hists)); 559 fmt->header(fmt, hpp, hists, 0, NULL);
552 fprintf(fp, "%s%s", hpp->buf, sep ?: " "); 560 fprintf(fp, "%s%s", hpp->buf, sep ?: " ");
553 } 561 }
554 562
@@ -568,7 +576,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
568 header_width += fprintf(fp, "+"); 576 header_width += fprintf(fp, "+");
569 first_col = false; 577 first_col = false;
570 578
571 fmt->header(fmt, hpp, hists_to_evsel(hists)); 579 fmt->header(fmt, hpp, hists, 0, NULL);
572 580
573 header_width += fprintf(fp, "%s", trim(hpp->buf)); 581 header_width += fprintf(fp, "%s", trim(hpp->buf));
574 } 582 }
@@ -589,7 +597,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
589 fprintf(fp, "%s", sep ?: ".."); 597 fprintf(fp, "%s", sep ?: "..");
590 first_col = false; 598 first_col = false;
591 599
592 width = fmt->width(fmt, hpp, hists_to_evsel(hists)); 600 width = fmt->width(fmt, hpp, hists);
593 fprintf(fp, "%.*s", width, dots); 601 fprintf(fp, "%.*s", width, dots);
594 } 602 }
595 603
@@ -606,7 +614,7 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
606 width++; /* for '+' sign between column header */ 614 width++; /* for '+' sign between column header */
607 first_col = false; 615 first_col = false;
608 616
609 width += fmt->width(fmt, hpp, hists_to_evsel(hists)); 617 width += fmt->width(fmt, hpp, hists);
610 } 618 }
611 619
612 if (width > header_width) 620 if (width > header_width)
@@ -622,67 +630,52 @@ static int print_hierarchy_header(struct hists *hists, struct perf_hpp *hpp,
622 return 2; 630 return 2;
623} 631}
624 632
625size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows, 633static void fprintf_line(struct hists *hists, struct perf_hpp *hpp,
626 int max_cols, float min_pcnt, FILE *fp) 634 int line, FILE *fp)
627{ 635{
628 struct perf_hpp_fmt *fmt; 636 struct perf_hpp_fmt *fmt;
629 struct perf_hpp_list_node *fmt_node;
630 struct rb_node *nd;
631 size_t ret = 0;
632 unsigned int width;
633 const char *sep = symbol_conf.field_sep; 637 const char *sep = symbol_conf.field_sep;
634 int nr_rows = 0;
635 char bf[96];
636 struct perf_hpp dummy_hpp = {
637 .buf = bf,
638 .size = sizeof(bf),
639 };
640 bool first = true; 638 bool first = true;
641 size_t linesz; 639 int span = 0;
642 char *line = NULL;
643 unsigned indent;
644
645 init_rem_hits();
646
647 hists__for_each_format(hists, fmt)
648 perf_hpp__reset_width(fmt, hists);
649
650 if (symbol_conf.col_width_list_str)
651 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
652
653 if (!show_header)
654 goto print_entries;
655
656 fprintf(fp, "# ");
657
658 if (symbol_conf.report_hierarchy) {
659 list_for_each_entry(fmt_node, &hists->hpp_formats, list) {
660 perf_hpp_list__for_each_format(&fmt_node->hpp, fmt)
661 perf_hpp__reset_width(fmt, hists);
662 }
663 nr_rows += print_hierarchy_header(hists, &dummy_hpp, sep, fp);
664 goto print_entries;
665 }
666 640
667 hists__for_each_format(hists, fmt) { 641 hists__for_each_format(hists, fmt) {
668 if (perf_hpp__should_skip(fmt, hists)) 642 if (perf_hpp__should_skip(fmt, hists))
669 continue; 643 continue;
670 644
671 if (!first) 645 if (!first && !span)
672 fprintf(fp, "%s", sep ?: " "); 646 fprintf(fp, "%s", sep ?: " ");
673 else 647 else
674 first = false; 648 first = false;
675 649
676 fmt->header(fmt, &dummy_hpp, hists_to_evsel(hists)); 650 fmt->header(fmt, hpp, hists, line, &span);
677 fprintf(fp, "%s", bf); 651
652 if (!span)
653 fprintf(fp, "%s", hpp->buf);
678 } 654 }
655}
679 656
680 fprintf(fp, "\n"); 657static int
681 if (max_rows && ++nr_rows >= max_rows) 658hists__fprintf_standard_headers(struct hists *hists,
682 goto out; 659 struct perf_hpp *hpp,
660 FILE *fp)
661{
662 struct perf_hpp_list *hpp_list = hists->hpp_list;
663 struct perf_hpp_fmt *fmt;
664 unsigned int width;
665 const char *sep = symbol_conf.field_sep;
666 bool first = true;
667 int line;
668
669 for (line = 0; line < hpp_list->nr_header_lines; line++) {
670 /* first # is displayed one level up */
671 if (line)
672 fprintf(fp, "# ");
673 fprintf_line(hists, hpp, line, fp);
674 fprintf(fp, "\n");
675 }
683 676
684 if (sep) 677 if (sep)
685 goto print_entries; 678 return hpp_list->nr_header_lines;
686 679
687 first = true; 680 first = true;
688 681
@@ -699,20 +692,58 @@ size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
699 else 692 else
700 first = false; 693 first = false;
701 694
702 width = fmt->width(fmt, &dummy_hpp, hists_to_evsel(hists)); 695 width = fmt->width(fmt, hpp, hists);
703 for (i = 0; i < width; i++) 696 for (i = 0; i < width; i++)
704 fprintf(fp, "."); 697 fprintf(fp, ".");
705 } 698 }
706 699
707 fprintf(fp, "\n"); 700 fprintf(fp, "\n");
708 if (max_rows && ++nr_rows >= max_rows)
709 goto out;
710
711 fprintf(fp, "#\n"); 701 fprintf(fp, "#\n");
712 if (max_rows && ++nr_rows >= max_rows) 702 return hpp_list->nr_header_lines + 2;
703}
704
705int hists__fprintf_headers(struct hists *hists, FILE *fp)
706{
707 char bf[1024];
708 struct perf_hpp dummy_hpp = {
709 .buf = bf,
710 .size = sizeof(bf),
711 };
712
713 fprintf(fp, "# ");
714
715 if (symbol_conf.report_hierarchy)
716 return hists__fprintf_hierarchy_headers(hists, &dummy_hpp, fp);
717 else
718 return hists__fprintf_standard_headers(hists, &dummy_hpp, fp);
719
720}
721
722size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,
723 int max_cols, float min_pcnt, FILE *fp,
724 bool use_callchain)
725{
726 struct rb_node *nd;
727 size_t ret = 0;
728 const char *sep = symbol_conf.field_sep;
729 int nr_rows = 0;
730 size_t linesz;
731 char *line = NULL;
732 unsigned indent;
733
734 init_rem_hits();
735
736 hists__reset_column_width(hists);
737
738 if (symbol_conf.col_width_list_str)
739 perf_hpp__set_user_width(symbol_conf.col_width_list_str);
740
741 if (show_header)
742 nr_rows += hists__fprintf_headers(hists, fp);
743
744 if (max_rows && nr_rows >= max_rows)
713 goto out; 745 goto out;
714 746
715print_entries:
716 linesz = hists__sort_list_width(hists) + 3 + 1; 747 linesz = hists__sort_list_width(hists) + 3 + 1;
717 linesz += perf_hpp__color_overhead(); 748 linesz += perf_hpp__color_overhead();
718 line = malloc(linesz); 749 line = malloc(linesz);
@@ -734,7 +765,7 @@ print_entries:
734 if (percent < min_pcnt) 765 if (percent < min_pcnt)
735 continue; 766 continue;
736 767
737 ret += hist_entry__fprintf(h, max_cols, hists, line, linesz, fp); 768 ret += hist_entry__fprintf(h, max_cols, line, linesz, fp, use_callchain);
738 769
739 if (max_rows && ++nr_rows >= max_rows) 770 if (max_rows && ++nr_rows >= max_rows)
740 break; 771 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 8c6c8a0ca642..eb60e613d795 100644
--- a/tools/perf/util/Build
+++ b/tools/perf/util/Build
@@ -1,5 +1,6 @@
1libperf-y += alias.o 1libperf-y += alias.o
2libperf-y += annotate.o 2libperf-y += annotate.o
3libperf-y += block-range.o
3libperf-y += build-id.o 4libperf-y += build-id.o
4libperf-y += config.o 5libperf-y += config.o
5libperf-y += ctype.o 6libperf-y += ctype.o
@@ -84,6 +85,8 @@ libperf-y += parse-regs-options.o
84libperf-y += term.o 85libperf-y += term.o
85libperf-y += help-unknown-cmd.o 86libperf-y += help-unknown-cmd.o
86libperf-y += mem-events.o 87libperf-y += mem-events.o
88libperf-y += vsprintf.o
89libperf-y += drv_configs.o
87 90
88libperf-$(CONFIG_LIBBPF) += bpf-loader.o 91libperf-$(CONFIG_LIBBPF) += bpf-loader.o
89libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o 92libperf-$(CONFIG_BPF_PROLOGUE) += bpf-prologue.o
@@ -97,9 +100,13 @@ endif
97 100
98libperf-$(CONFIG_DWARF) += probe-finder.o 101libperf-$(CONFIG_DWARF) += probe-finder.o
99libperf-$(CONFIG_DWARF) += dwarf-aux.o 102libperf-$(CONFIG_DWARF) += dwarf-aux.o
103libperf-$(CONFIG_DWARF) += dwarf-regs.o
100 104
101libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o 105libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
106libperf-$(CONFIG_LOCAL_LIBUNWIND) += unwind-libunwind-local.o
102libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o 107libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o
108libperf-$(CONFIG_LIBUNWIND_X86) += libunwind/x86_32.o
109libperf-$(CONFIG_LIBUNWIND_AARCH64) += libunwind/arm64.o
103 110
104libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o 111libperf-$(CONFIG_LIBBABELTRACE) += data-convert-bt.o
105 112
@@ -108,6 +115,7 @@ libperf-y += scripting-engines/
108libperf-$(CONFIG_ZLIB) += zlib.o 115libperf-$(CONFIG_ZLIB) += zlib.o
109libperf-$(CONFIG_LZMA) += lzma.o 116libperf-$(CONFIG_LZMA) += lzma.o
110libperf-y += demangle-java.o 117libperf-y += demangle-java.o
118libperf-y += demangle-rust.o
111 119
112ifdef CONFIG_JITDUMP 120ifdef CONFIG_JITDUMP
113libperf-$(CONFIG_LIBELF) += jitdump.o 121libperf-$(CONFIG_LIBELF) += jitdump.o
@@ -173,3 +181,7 @@ $(OUTPUT)util/libstring.o: ../lib/string.c FORCE
173$(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE 181$(OUTPUT)util/hweight.o: ../lib/hweight.c FORCE
174 $(call rule_mkdir) 182 $(call rule_mkdir)
175 $(call if_changed_dep,cc_o_c) 183 $(call if_changed_dep,cc_o_c)
184
185$(OUTPUT)util/vsprintf.o: ../lib/vsprintf.c FORCE
186 $(call rule_mkdir)
187 $(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 7e5a1e8874ce..aeb5a441bd74 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -17,6 +17,7 @@
17#include "debug.h" 17#include "debug.h"
18#include "annotate.h" 18#include "annotate.h"
19#include "evsel.h" 19#include "evsel.h"
20#include "block-range.h"
20#include <regex.h> 21#include <regex.h>
21#include <pthread.h> 22#include <pthread.h>
22#include <linux/bitops.h> 23#include <linux/bitops.h>
@@ -53,7 +54,7 @@ int ins__scnprintf(struct ins *ins, char *bf, size_t size,
53 return ins__raw_scnprintf(ins, bf, size, ops); 54 return ins__raw_scnprintf(ins, bf, size, ops);
54} 55}
55 56
56static int call__parse(struct ins_operands *ops) 57static int call__parse(struct ins_operands *ops, struct map *map)
57{ 58{
58 char *endptr, *tok, *name; 59 char *endptr, *tok, *name;
59 60
@@ -81,16 +82,16 @@ static int call__parse(struct ins_operands *ops)
81 return ops->target.name == NULL ? -1 : 0; 82 return ops->target.name == NULL ? -1 : 0;
82 83
83indirect_call: 84indirect_call:
84 tok = strchr(endptr, '('); 85 tok = strchr(endptr, '*');
85 if (tok != NULL) { 86 if (tok == NULL) {
86 ops->target.addr = 0; 87 struct symbol *sym = map__find_symbol(map, map->map_ip(map, ops->target.addr));
88 if (sym != NULL)
89 ops->target.name = strdup(sym->name);
90 else
91 ops->target.addr = 0;
87 return 0; 92 return 0;
88 } 93 }
89 94
90 tok = strchr(endptr, '*');
91 if (tok == NULL)
92 return -1;
93
94 ops->target.addr = strtoull(tok + 1, NULL, 16); 95 ops->target.addr = strtoull(tok + 1, NULL, 16);
95 return 0; 96 return 0;
96} 97}
@@ -117,7 +118,7 @@ bool ins__is_call(const struct ins *ins)
117 return ins->ops == &call_ops; 118 return ins->ops == &call_ops;
118} 119}
119 120
120static int jump__parse(struct ins_operands *ops) 121static int jump__parse(struct ins_operands *ops, struct map *map __maybe_unused)
121{ 122{
122 const char *s = strchr(ops->raw, '+'); 123 const char *s = strchr(ops->raw, '+');
123 124
@@ -172,7 +173,7 @@ static int comment__symbol(char *raw, char *comment, u64 *addrp, char **namep)
172 return 0; 173 return 0;
173} 174}
174 175
175static int lock__parse(struct ins_operands *ops) 176static int lock__parse(struct ins_operands *ops, struct map *map)
176{ 177{
177 char *name; 178 char *name;
178 179
@@ -193,7 +194,7 @@ static int lock__parse(struct ins_operands *ops)
193 return 0; 194 return 0;
194 195
195 if (ops->locked.ins->ops->parse && 196 if (ops->locked.ins->ops->parse &&
196 ops->locked.ins->ops->parse(ops->locked.ops) < 0) 197 ops->locked.ins->ops->parse(ops->locked.ops, map) < 0)
197 goto out_free_ops; 198 goto out_free_ops;
198 199
199 return 0; 200 return 0;
@@ -236,7 +237,7 @@ static struct ins_ops lock_ops = {
236 .scnprintf = lock__scnprintf, 237 .scnprintf = lock__scnprintf,
237}; 238};
238 239
239static int mov__parse(struct ins_operands *ops) 240static int mov__parse(struct ins_operands *ops, struct map *map __maybe_unused)
240{ 241{
241 char *s = strchr(ops->raw, ','), *target, *comment, prev; 242 char *s = strchr(ops->raw, ','), *target, *comment, prev;
242 243
@@ -303,7 +304,7 @@ static struct ins_ops mov_ops = {
303 .scnprintf = mov__scnprintf, 304 .scnprintf = mov__scnprintf,
304}; 305};
305 306
306static int dec__parse(struct ins_operands *ops) 307static int dec__parse(struct ins_operands *ops, struct map *map __maybe_unused)
307{ 308{
308 char *target, *comment, *s, prev; 309 char *target, *comment, *s, prev;
309 310
@@ -354,6 +355,15 @@ static struct ins_ops nop_ops = {
354 .scnprintf = nop__scnprintf, 355 .scnprintf = nop__scnprintf,
355}; 356};
356 357
358static struct ins_ops ret_ops = {
359 .scnprintf = ins__raw_scnprintf,
360};
361
362bool ins__is_ret(const struct ins *ins)
363{
364 return ins->ops == &ret_ops;
365}
366
357static struct ins instructions[] = { 367static struct ins instructions[] = {
358 { .name = "add", .ops = &mov_ops, }, 368 { .name = "add", .ops = &mov_ops, },
359 { .name = "addl", .ops = &mov_ops, }, 369 { .name = "addl", .ops = &mov_ops, },
@@ -444,6 +454,7 @@ static struct ins instructions[] = {
444 { .name = "xadd", .ops = &mov_ops, }, 454 { .name = "xadd", .ops = &mov_ops, },
445 { .name = "xbeginl", .ops = &jump_ops, }, 455 { .name = "xbeginl", .ops = &jump_ops, },
446 { .name = "xbeginq", .ops = &jump_ops, }, 456 { .name = "xbeginq", .ops = &jump_ops, },
457 { .name = "retq", .ops = &ret_ops, },
447}; 458};
448 459
449static int ins__key_cmp(const void *name, const void *insp) 460static int ins__key_cmp(const void *name, const void *insp)
@@ -481,13 +492,6 @@ static struct ins *ins__find(const char *name)
481 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp); 492 return bsearch(name, instructions, nmemb, sizeof(struct ins), ins__key_cmp);
482} 493}
483 494
484int symbol__annotate_init(struct map *map __maybe_unused, struct symbol *sym)
485{
486 struct annotation *notes = symbol__annotation(sym);
487 pthread_mutex_init(&notes->lock, NULL);
488 return 0;
489}
490
491int symbol__alloc_hist(struct symbol *sym) 495int symbol__alloc_hist(struct symbol *sym)
492{ 496{
493 struct annotation *notes = symbol__annotation(sym); 497 struct annotation *notes = symbol__annotation(sym);
@@ -705,7 +709,7 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 ip)
705 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip); 709 return symbol__inc_addr_samples(he->ms.sym, he->ms.map, evidx, ip);
706} 710}
707 711
708static void disasm_line__init_ins(struct disasm_line *dl) 712static void disasm_line__init_ins(struct disasm_line *dl, struct map *map)
709{ 713{
710 dl->ins = ins__find(dl->name); 714 dl->ins = ins__find(dl->name);
711 715
@@ -715,7 +719,7 @@ static void disasm_line__init_ins(struct disasm_line *dl)
715 if (!dl->ins->ops) 719 if (!dl->ins->ops)
716 return; 720 return;
717 721
718 if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops) < 0) 722 if (dl->ins->ops->parse && dl->ins->ops->parse(&dl->ops, map) < 0)
719 dl->ins = NULL; 723 dl->ins = NULL;
720} 724}
721 725
@@ -757,7 +761,8 @@ out_free_name:
757} 761}
758 762
759static struct disasm_line *disasm_line__new(s64 offset, char *line, 763static struct disasm_line *disasm_line__new(s64 offset, char *line,
760 size_t privsize, int line_nr) 764 size_t privsize, int line_nr,
765 struct map *map)
761{ 766{
762 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize); 767 struct disasm_line *dl = zalloc(sizeof(*dl) + privsize);
763 768
@@ -772,7 +777,7 @@ static struct disasm_line *disasm_line__new(s64 offset, char *line,
772 if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0) 777 if (disasm_line__parse(dl->line, &dl->name, &dl->ops.raw) < 0)
773 goto out_free_line; 778 goto out_free_line;
774 779
775 disasm_line__init_ins(dl); 780 disasm_line__init_ins(dl, map);
776 } 781 }
777 } 782 }
778 783
@@ -856,6 +861,89 @@ double disasm__calc_percent(struct annotation *notes, int evidx, s64 offset,
856 return percent; 861 return percent;
857} 862}
858 863
864static const char *annotate__address_color(struct block_range *br)
865{
866 double cov = block_range__coverage(br);
867
868 if (cov >= 0) {
869 /* mark red for >75% coverage */
870 if (cov > 0.75)
871 return PERF_COLOR_RED;
872
873 /* mark dull for <1% coverage */
874 if (cov < 0.01)
875 return PERF_COLOR_NORMAL;
876 }
877
878 return PERF_COLOR_MAGENTA;
879}
880
881static const char *annotate__asm_color(struct block_range *br)
882{
883 double cov = block_range__coverage(br);
884
885 if (cov >= 0) {
886 /* mark dull for <1% coverage */
887 if (cov < 0.01)
888 return PERF_COLOR_NORMAL;
889 }
890
891 return PERF_COLOR_BLUE;
892}
893
894static void annotate__branch_printf(struct block_range *br, u64 addr)
895{
896 bool emit_comment = true;
897
898 if (!br)
899 return;
900
901#if 1
902 if (br->is_target && br->start == addr) {
903 struct block_range *branch = br;
904 double p;
905
906 /*
907 * Find matching branch to our target.
908 */
909 while (!branch->is_branch)
910 branch = block_range__next(branch);
911
912 p = 100 *(double)br->entry / branch->coverage;
913
914 if (p > 0.1) {
915 if (emit_comment) {
916 emit_comment = false;
917 printf("\t#");
918 }
919
920 /*
921 * The percentage of coverage joined at this target in relation
922 * to the next branch.
923 */
924 printf(" +%.2f%%", p);
925 }
926 }
927#endif
928 if (br->is_branch && br->end == addr) {
929 double p = 100*(double)br->taken / br->coverage;
930
931 if (p > 0.1) {
932 if (emit_comment) {
933 emit_comment = false;
934 printf("\t#");
935 }
936
937 /*
938 * The percentage of coverage leaving at this branch, and
939 * its prediction ratio.
940 */
941 printf(" -%.2f%% (p:%.2f%%)", p, 100*(double)br->pred / br->taken);
942 }
943 }
944}
945
946
859static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start, 947static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 start,
860 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed, 948 struct perf_evsel *evsel, u64 len, int min_pcnt, int printed,
861 int max_lines, struct disasm_line *queue) 949 int max_lines, struct disasm_line *queue)
@@ -875,6 +963,7 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
875 s64 offset = dl->offset; 963 s64 offset = dl->offset;
876 const u64 addr = start + offset; 964 const u64 addr = start + offset;
877 struct disasm_line *next; 965 struct disasm_line *next;
966 struct block_range *br;
878 967
879 next = disasm__get_next_ip_line(&notes->src->source, dl); 968 next = disasm__get_next_ip_line(&notes->src->source, dl);
880 969
@@ -944,8 +1033,12 @@ static int disasm_line__print(struct disasm_line *dl, struct symbol *sym, u64 st
944 } 1033 }
945 1034
946 printf(" : "); 1035 printf(" : ");
947 color_fprintf(stdout, PERF_COLOR_MAGENTA, " %" PRIx64 ":", addr); 1036
948 color_fprintf(stdout, PERF_COLOR_BLUE, "%s\n", dl->line); 1037 br = block_range__find(addr);
1038 color_fprintf(stdout, annotate__address_color(br), " %" PRIx64 ":", addr);
1039 color_fprintf(stdout, annotate__asm_color(br), "%s", dl->line);
1040 annotate__branch_printf(br, addr);
1041 printf("\n");
949 1042
950 if (ppercents != &percent) 1043 if (ppercents != &percent)
951 free(ppercents); 1044 free(ppercents);
@@ -1056,7 +1149,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1056 parsed_line = tmp2 + 1; 1149 parsed_line = tmp2 + 1;
1057 } 1150 }
1058 1151
1059 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr); 1152 dl = disasm_line__new(offset, parsed_line, privsize, *line_nr, map);
1060 free(line); 1153 free(line);
1061 (*line_nr)++; 1154 (*line_nr)++;
1062 1155
@@ -1074,7 +1167,7 @@ static int symbol__parse_objdump_line(struct symbol *sym, struct map *map,
1074 .addr = dl->ops.target.addr, 1167 .addr = dl->ops.target.addr,
1075 }; 1168 };
1076 1169
1077 if (!map_groups__find_ams(&target, NULL) && 1170 if (!map_groups__find_ams(&target) &&
1078 target.sym->start == target.al_addr) 1171 target.sym->start == target.al_addr)
1079 dl->ops.target.name = strdup(target.sym->name); 1172 dl->ops.target.name = strdup(target.sym->name);
1080 } 1173 }
@@ -1113,75 +1206,99 @@ static void delete_last_nop(struct symbol *sym)
1113 } 1206 }
1114} 1207}
1115 1208
1116int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize) 1209int symbol__strerror_disassemble(struct symbol *sym __maybe_unused, struct map *map,
1210 int errnum, char *buf, size_t buflen)
1117{ 1211{
1118 struct dso *dso = map->dso; 1212 struct dso *dso = map->dso;
1119 char *filename = dso__build_id_filename(dso, NULL, 0);
1120 bool free_filename = true;
1121 char command[PATH_MAX * 2];
1122 FILE *file;
1123 int err = 0;
1124 char symfs_filename[PATH_MAX];
1125 struct kcore_extract kce;
1126 bool delete_extract = false;
1127 int lineno = 0;
1128 int nline;
1129 1213
1130 if (filename) 1214 BUG_ON(buflen == 0);
1131 symbol__join_symfs(symfs_filename, filename); 1215
1216 if (errnum >= 0) {
1217 str_error_r(errnum, buf, buflen);
1218 return 0;
1219 }
1220
1221 switch (errnum) {
1222 case SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX: {
1223 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1224 char *build_id_msg = NULL;
1132 1225
1133 if (filename == NULL) {
1134 if (dso->has_build_id) { 1226 if (dso->has_build_id) {
1135 pr_err("Can't annotate %s: not enough memory\n", 1227 build_id__sprintf(dso->build_id,
1136 sym->name); 1228 sizeof(dso->build_id), bf + 15);
1137 return -ENOMEM; 1229 build_id_msg = bf;
1138 } 1230 }
1231 scnprintf(buf, buflen,
1232 "No vmlinux file%s\nwas found in the path.\n\n"
1233 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1234 "Please use:\n\n"
1235 " perf buildid-cache -vu vmlinux\n\n"
1236 "or:\n\n"
1237 " --vmlinux vmlinux\n", build_id_msg ?: "");
1238 }
1239 break;
1240 default:
1241 scnprintf(buf, buflen, "Internal error: Invalid %d error code\n", errnum);
1242 break;
1243 }
1244
1245 return 0;
1246}
1247
1248static int dso__disassemble_filename(struct dso *dso, char *filename, size_t filename_size)
1249{
1250 char linkname[PATH_MAX];
1251 char *build_id_filename;
1252
1253 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
1254 !dso__is_kcore(dso))
1255 return SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX;
1256
1257 build_id_filename = dso__build_id_filename(dso, NULL, 0);
1258 if (build_id_filename) {
1259 __symbol__join_symfs(filename, filename_size, build_id_filename);
1260 free(build_id_filename);
1261 } else {
1262 if (dso->has_build_id)
1263 return ENOMEM;
1139 goto fallback; 1264 goto fallback;
1140 } else if (dso__is_kcore(dso)) { 1265 }
1141 goto fallback; 1266
1142 } else if (readlink(symfs_filename, command, sizeof(command)) < 0 || 1267 if (dso__is_kcore(dso) ||
1143 strstr(command, DSO__NAME_KALLSYMS) || 1268 readlink(filename, linkname, sizeof(linkname)) < 0 ||
1144 access(symfs_filename, R_OK)) { 1269 strstr(linkname, DSO__NAME_KALLSYMS) ||
1145 free(filename); 1270 access(filename, R_OK)) {
1146fallback: 1271fallback:
1147 /* 1272 /*
1148 * If we don't have build-ids or the build-id file isn't in the 1273 * If we don't have build-ids or the build-id file isn't in the
1149 * cache, or is just a kallsyms file, well, lets hope that this 1274 * cache, or is just a kallsyms file, well, lets hope that this
1150 * DSO is the same as when 'perf record' ran. 1275 * DSO is the same as when 'perf record' ran.
1151 */ 1276 */
1152 filename = (char *)dso->long_name; 1277 __symbol__join_symfs(filename, filename_size, dso->long_name);
1153 symbol__join_symfs(symfs_filename, filename);
1154 free_filename = false;
1155 } 1278 }
1156 1279
1157 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS && 1280 return 0;
1158 !dso__is_kcore(dso)) { 1281}
1159 char bf[SBUILD_ID_SIZE + 15] = " with build id ";
1160 char *build_id_msg = NULL;
1161 1282
1162 if (dso->annotate_warned) 1283int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize)
1163 goto out_free_filename; 1284{
1285 struct dso *dso = map->dso;
1286 char command[PATH_MAX * 2];
1287 FILE *file;
1288 char symfs_filename[PATH_MAX];
1289 struct kcore_extract kce;
1290 bool delete_extract = false;
1291 int stdout_fd[2];
1292 int lineno = 0;
1293 int nline;
1294 pid_t pid;
1295 int err = dso__disassemble_filename(dso, symfs_filename, sizeof(symfs_filename));
1164 1296
1165 if (dso->has_build_id) { 1297 if (err)
1166 build_id__sprintf(dso->build_id, 1298 return err;
1167 sizeof(dso->build_id), bf + 15);
1168 build_id_msg = bf;
1169 }
1170 err = -ENOENT;
1171 dso->annotate_warned = 1;
1172 pr_err("Can't annotate %s:\n\n"
1173 "No vmlinux file%s\nwas found in the path.\n\n"
1174 "Note that annotation using /proc/kcore requires CAP_SYS_RAWIO capability.\n\n"
1175 "Please use:\n\n"
1176 " perf buildid-cache -vu vmlinux\n\n"
1177 "or:\n\n"
1178 " --vmlinux vmlinux\n",
1179 sym->name, build_id_msg ?: "");
1180 goto out_free_filename;
1181 }
1182 1299
1183 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__, 1300 pr_debug("%s: filename=%s, sym=%s, start=%#" PRIx64 ", end=%#" PRIx64 "\n", __func__,
1184 filename, sym->name, map->unmap_ip(map, sym->start), 1301 symfs_filename, sym->name, map->unmap_ip(map, sym->start),
1185 map->unmap_ip(map, sym->end)); 1302 map->unmap_ip(map, sym->end));
1186 1303
1187 pr_debug("annotating [%p] %30s : [%p] %30s\n", 1304 pr_debug("annotating [%p] %30s : [%p] %30s\n",
@@ -1196,11 +1313,6 @@ fallback:
1196 delete_extract = true; 1313 delete_extract = true;
1197 strlcpy(symfs_filename, kce.extract_filename, 1314 strlcpy(symfs_filename, kce.extract_filename,
1198 sizeof(symfs_filename)); 1315 sizeof(symfs_filename));
1199 if (free_filename) {
1200 free(filename);
1201 free_filename = false;
1202 }
1203 filename = symfs_filename;
1204 } 1316 }
1205 } else if (dso__needs_decompress(dso)) { 1317 } else if (dso__needs_decompress(dso)) {
1206 char tmp[PATH_MAX]; 1318 char tmp[PATH_MAX];
@@ -1209,14 +1321,14 @@ fallback:
1209 bool ret; 1321 bool ret;
1210 1322
1211 if (kmod_path__parse_ext(&m, symfs_filename)) 1323 if (kmod_path__parse_ext(&m, symfs_filename))
1212 goto out_free_filename; 1324 goto out;
1213 1325
1214 snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX"); 1326 snprintf(tmp, PATH_MAX, "/tmp/perf-kmod-XXXXXX");
1215 1327
1216 fd = mkstemp(tmp); 1328 fd = mkstemp(tmp);
1217 if (fd < 0) { 1329 if (fd < 0) {
1218 free(m.ext); 1330 free(m.ext);
1219 goto out_free_filename; 1331 goto out;
1220 } 1332 }
1221 1333
1222 ret = decompress_to_file(m.ext, symfs_filename, fd); 1334 ret = decompress_to_file(m.ext, symfs_filename, fd);
@@ -1228,7 +1340,7 @@ fallback:
1228 close(fd); 1340 close(fd);
1229 1341
1230 if (!ret) 1342 if (!ret)
1231 goto out_free_filename; 1343 goto out;
1232 1344
1233 strcpy(symfs_filename, tmp); 1345 strcpy(symfs_filename, tmp);
1234 } 1346 }
@@ -1244,13 +1356,36 @@ fallback:
1244 map__rip_2objdump(map, sym->end), 1356 map__rip_2objdump(map, sym->end),
1245 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw", 1357 symbol_conf.annotate_asm_raw ? "" : "--no-show-raw",
1246 symbol_conf.annotate_src ? "-S" : "", 1358 symbol_conf.annotate_src ? "-S" : "",
1247 symfs_filename, filename); 1359 symfs_filename, symfs_filename);
1248 1360
1249 pr_debug("Executing: %s\n", command); 1361 pr_debug("Executing: %s\n", command);
1250 1362
1251 file = popen(command, "r"); 1363 err = -1;
1364 if (pipe(stdout_fd) < 0) {
1365 pr_err("Failure creating the pipe to run %s\n", command);
1366 goto out_remove_tmp;
1367 }
1368
1369 pid = fork();
1370 if (pid < 0) {
1371 pr_err("Failure forking to run %s\n", command);
1372 goto out_close_stdout;
1373 }
1374
1375 if (pid == 0) {
1376 close(stdout_fd[0]);
1377 dup2(stdout_fd[1], 1);
1378 close(stdout_fd[1]);
1379 execl("/bin/sh", "sh", "-c", command, NULL);
1380 perror(command);
1381 exit(-1);
1382 }
1383
1384 close(stdout_fd[1]);
1385
1386 file = fdopen(stdout_fd[0], "r");
1252 if (!file) { 1387 if (!file) {
1253 pr_err("Failure running %s\n", command); 1388 pr_err("Failure creating FILE stream for %s\n", command);
1254 /* 1389 /*
1255 * If we were using debug info should retry with 1390 * If we were using debug info should retry with
1256 * original binary. 1391 * original binary.
@@ -1276,17 +1411,22 @@ fallback:
1276 if (dso__is_kcore(dso)) 1411 if (dso__is_kcore(dso))
1277 delete_last_nop(sym); 1412 delete_last_nop(sym);
1278 1413
1279 pclose(file); 1414 fclose(file);
1280 1415 err = 0;
1281out_remove_tmp: 1416out_remove_tmp:
1417 close(stdout_fd[0]);
1418
1282 if (dso__needs_decompress(dso)) 1419 if (dso__needs_decompress(dso))
1283 unlink(symfs_filename); 1420 unlink(symfs_filename);
1284out_free_filename: 1421
1285 if (delete_extract) 1422 if (delete_extract)
1286 kcore_extract__delete(&kce); 1423 kcore_extract__delete(&kce);
1287 if (free_filename) 1424out:
1288 free(filename);
1289 return err; 1425 return err;
1426
1427out_close_stdout:
1428 close(stdout_fd[1]);
1429 goto out_remove_tmp;
1290} 1430}
1291 1431
1292static void insert_source_line(struct rb_root *root, struct source_line *src_line) 1432static void insert_source_line(struct rb_root *root, struct source_line *src_line)
@@ -1512,13 +1652,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1512 const char *d_filename; 1652 const char *d_filename;
1513 const char *evsel_name = perf_evsel__name(evsel); 1653 const char *evsel_name = perf_evsel__name(evsel);
1514 struct annotation *notes = symbol__annotation(sym); 1654 struct annotation *notes = symbol__annotation(sym);
1655 struct sym_hist *h = annotation__histogram(notes, evsel->idx);
1515 struct disasm_line *pos, *queue = NULL; 1656 struct disasm_line *pos, *queue = NULL;
1516 u64 start = map__rip_2objdump(map, sym->start); 1657 u64 start = map__rip_2objdump(map, sym->start);
1517 int printed = 2, queue_len = 0; 1658 int printed = 2, queue_len = 0;
1518 int more = 0; 1659 int more = 0;
1519 u64 len; 1660 u64 len;
1520 int width = 8; 1661 int width = 8;
1521 int namelen, evsel_name_len, graph_dotted_len; 1662 int graph_dotted_len;
1522 1663
1523 filename = strdup(dso->long_name); 1664 filename = strdup(dso->long_name);
1524 if (!filename) 1665 if (!filename)
@@ -1530,17 +1671,14 @@ int symbol__annotate_printf(struct symbol *sym, struct map *map,
1530 d_filename = basename(filename); 1671 d_filename = basename(filename);
1531 1672
1532 len = symbol__size(sym); 1673 len = symbol__size(sym);
1533 namelen = strlen(d_filename);
1534 evsel_name_len = strlen(evsel_name);
1535 1674
1536 if (perf_evsel__is_group_event(evsel)) 1675 if (perf_evsel__is_group_event(evsel))
1537 width *= evsel->nr_members; 1676 width *= evsel->nr_members;
1538 1677
1539 printf(" %-*.*s| Source code & Disassembly of %s for %s\n", 1678 graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples)\n",
1540 width, width, "Percent", d_filename, evsel_name); 1679 width, width, "Percent", d_filename, evsel_name, h->sum);
1541 1680
1542 graph_dotted_len = width + namelen + evsel_name_len; 1681 printf("%-*.*s----\n",
1543 printf("-%-*.*s-----------------------------------------\n",
1544 graph_dotted_len, graph_dotted_len, graph_dotted_line); 1682 graph_dotted_len, graph_dotted_len, graph_dotted_line);
1545 1683
1546 if (verbose) 1684 if (verbose)
@@ -1655,7 +1793,7 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1655 struct rb_root source_line = RB_ROOT; 1793 struct rb_root source_line = RB_ROOT;
1656 u64 len; 1794 u64 len;
1657 1795
1658 if (symbol__annotate(sym, map, 0) < 0) 1796 if (symbol__disassemble(sym, map, 0) < 0)
1659 return -1; 1797 return -1;
1660 1798
1661 len = symbol__size(sym); 1799 len = symbol__size(sym);
@@ -1676,11 +1814,6 @@ int symbol__tty_annotate(struct symbol *sym, struct map *map,
1676 return 0; 1814 return 0;
1677} 1815}
1678 1816
1679int hist_entry__annotate(struct hist_entry *he, size_t privsize)
1680{
1681 return symbol__annotate(he->ms.sym, he->ms.map, privsize);
1682}
1683
1684bool ui__has_annotation(void) 1817bool ui__has_annotation(void)
1685{ 1818{
1686 return use_browser == 1 && perf_hpp_list.sym; 1819 return use_browser == 1 && perf_hpp_list.sym;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index 9241f8c2b7e1..5bbcec173b82 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -36,7 +36,7 @@ struct ins_operands {
36 36
37struct ins_ops { 37struct ins_ops {
38 void (*free)(struct ins_operands *ops); 38 void (*free)(struct ins_operands *ops);
39 int (*parse)(struct ins_operands *ops); 39 int (*parse)(struct ins_operands *ops, struct map *map);
40 int (*scnprintf)(struct ins *ins, char *bf, size_t size, 40 int (*scnprintf)(struct ins *ins, char *bf, size_t size,
41 struct ins_operands *ops); 41 struct ins_operands *ops);
42}; 42};
@@ -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;
@@ -129,6 +130,7 @@ struct annotated_source {
129 130
130struct annotation { 131struct annotation {
131 pthread_mutex_t lock; 132 pthread_mutex_t lock;
133 u64 max_coverage;
132 struct annotated_source *src; 134 struct annotated_source *src;
133}; 135};
134 136
@@ -154,11 +156,28 @@ int hist_entry__inc_addr_samples(struct hist_entry *he, int evidx, u64 addr);
154int symbol__alloc_hist(struct symbol *sym); 156int symbol__alloc_hist(struct symbol *sym);
155void symbol__annotate_zero_histograms(struct symbol *sym); 157void symbol__annotate_zero_histograms(struct symbol *sym);
156 158
157int symbol__annotate(struct symbol *sym, struct map *map, size_t privsize); 159int symbol__disassemble(struct symbol *sym, struct map *map, size_t privsize);
158 160
159int hist_entry__annotate(struct hist_entry *he, size_t privsize); 161enum symbol_disassemble_errno {
162 SYMBOL_ANNOTATE_ERRNO__SUCCESS = 0,
163
164 /*
165 * Choose an arbitrary negative big number not to clash with standard
166 * errno since SUS requires the errno has distinct positive values.
167 * See 'Issue 6' in the link below.
168 *
169 * http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html
170 */
171 __SYMBOL_ANNOTATE_ERRNO__START = -10000,
172
173 SYMBOL_ANNOTATE_ERRNO__NO_VMLINUX = __SYMBOL_ANNOTATE_ERRNO__START,
174
175 __SYMBOL_ANNOTATE_ERRNO__END,
176};
177
178int symbol__strerror_disassemble(struct symbol *sym, struct map *map,
179 int errnum, char *buf, size_t buflen);
160 180
161int 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,
163 struct perf_evsel *evsel, bool full_paths, 182 struct perf_evsel *evsel, bool full_paths,
164 int min_pcnt, int max_lines, int context); 183 int min_pcnt, int max_lines, int context);
diff --git a/tools/perf/util/auxtrace.c b/tools/perf/util/auxtrace.c
index c9169011e55e..c5a6e0b12452 100644
--- a/tools/perf/util/auxtrace.c
+++ b/tools/perf/util/auxtrace.c
@@ -16,6 +16,10 @@
16#include <sys/types.h> 16#include <sys/types.h>
17#include <sys/mman.h> 17#include <sys/mman.h>
18#include <stdbool.h> 18#include <stdbool.h>
19#include <ctype.h>
20#include <string.h>
21#include <limits.h>
22#include <errno.h>
19 23
20#include <linux/kernel.h> 24#include <linux/kernel.h>
21#include <linux/perf_event.h> 25#include <linux/perf_event.h>
@@ -35,9 +39,14 @@
35#include "../perf.h" 39#include "../perf.h"
36#include "util.h" 40#include "util.h"
37#include "evlist.h" 41#include "evlist.h"
42#include "dso.h"
43#include "map.h"
44#include "pmu.h"
45#include "evsel.h"
38#include "cpumap.h" 46#include "cpumap.h"
39#include "thread_map.h" 47#include "thread_map.h"
40#include "asm/bug.h" 48#include "asm/bug.h"
49#include "symbol/kallsyms.h"
41#include "auxtrace.h" 50#include "auxtrace.h"
42 51
43#include <linux/hash.h> 52#include <linux/hash.h>
@@ -892,6 +901,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,
892 return intel_pt_process_auxtrace_info(event, session); 901 return intel_pt_process_auxtrace_info(event, session);
893 case PERF_AUXTRACE_INTEL_BTS: 902 case PERF_AUXTRACE_INTEL_BTS:
894 return intel_bts_process_auxtrace_info(event, session); 903 return intel_bts_process_auxtrace_info(event, session);
904 case PERF_AUXTRACE_CS_ETM:
895 case PERF_AUXTRACE_UNKNOWN: 905 case PERF_AUXTRACE_UNKNOWN:
896 default: 906 default:
897 return -EINVAL; 907 return -EINVAL;
@@ -1398,3 +1408,731 @@ void *auxtrace_cache__lookup(struct auxtrace_cache *c, u32 key)
1398 1408
1399 return NULL; 1409 return NULL;
1400} 1410}
1411
1412static void addr_filter__free_str(struct addr_filter *filt)
1413{
1414 free(filt->str);
1415 filt->action = NULL;
1416 filt->sym_from = NULL;
1417 filt->sym_to = NULL;
1418 filt->filename = NULL;
1419 filt->str = NULL;
1420}
1421
1422static struct addr_filter *addr_filter__new(void)
1423{
1424 struct addr_filter *filt = zalloc(sizeof(*filt));
1425
1426 if (filt)
1427 INIT_LIST_HEAD(&filt->list);
1428
1429 return filt;
1430}
1431
1432static void addr_filter__free(struct addr_filter *filt)
1433{
1434 if (filt)
1435 addr_filter__free_str(filt);
1436 free(filt);
1437}
1438
1439static void addr_filters__add(struct addr_filters *filts,
1440 struct addr_filter *filt)
1441{
1442 list_add_tail(&filt->list, &filts->head);
1443 filts->cnt += 1;
1444}
1445
1446static void addr_filters__del(struct addr_filters *filts,
1447 struct addr_filter *filt)
1448{
1449 list_del_init(&filt->list);
1450 filts->cnt -= 1;
1451}
1452
1453void addr_filters__init(struct addr_filters *filts)
1454{
1455 INIT_LIST_HEAD(&filts->head);
1456 filts->cnt = 0;
1457}
1458
1459void addr_filters__exit(struct addr_filters *filts)
1460{
1461 struct addr_filter *filt, *n;
1462
1463 list_for_each_entry_safe(filt, n, &filts->head, list) {
1464 addr_filters__del(filts, filt);
1465 addr_filter__free(filt);
1466 }
1467}
1468
1469static int parse_num_or_str(char **inp, u64 *num, const char **str,
1470 const char *str_delim)
1471{
1472 *inp += strspn(*inp, " ");
1473
1474 if (isdigit(**inp)) {
1475 char *endptr;
1476
1477 if (!num)
1478 return -EINVAL;
1479 errno = 0;
1480 *num = strtoull(*inp, &endptr, 0);
1481 if (errno)
1482 return -errno;
1483 if (endptr == *inp)
1484 return -EINVAL;
1485 *inp = endptr;
1486 } else {
1487 size_t n;
1488
1489 if (!str)
1490 return -EINVAL;
1491 *inp += strspn(*inp, " ");
1492 *str = *inp;
1493 n = strcspn(*inp, str_delim);
1494 if (!n)
1495 return -EINVAL;
1496 *inp += n;
1497 if (**inp) {
1498 **inp = '\0';
1499 *inp += 1;
1500 }
1501 }
1502 return 0;
1503}
1504
1505static int parse_action(struct addr_filter *filt)
1506{
1507 if (!strcmp(filt->action, "filter")) {
1508 filt->start = true;
1509 filt->range = true;
1510 } else if (!strcmp(filt->action, "start")) {
1511 filt->start = true;
1512 } else if (!strcmp(filt->action, "stop")) {
1513 filt->start = false;
1514 } else if (!strcmp(filt->action, "tracestop")) {
1515 filt->start = false;
1516 filt->range = true;
1517 filt->action += 5; /* Change 'tracestop' to 'stop' */
1518 } else {
1519 return -EINVAL;
1520 }
1521 return 0;
1522}
1523
1524static int parse_sym_idx(char **inp, int *idx)
1525{
1526 *idx = -1;
1527
1528 *inp += strspn(*inp, " ");
1529
1530 if (**inp != '#')
1531 return 0;
1532
1533 *inp += 1;
1534
1535 if (**inp == 'g' || **inp == 'G') {
1536 *inp += 1;
1537 *idx = 0;
1538 } else {
1539 unsigned long num;
1540 char *endptr;
1541
1542 errno = 0;
1543 num = strtoul(*inp, &endptr, 0);
1544 if (errno)
1545 return -errno;
1546 if (endptr == *inp || num > INT_MAX)
1547 return -EINVAL;
1548 *inp = endptr;
1549 *idx = num;
1550 }
1551
1552 return 0;
1553}
1554
1555static int parse_addr_size(char **inp, u64 *num, const char **str, int *idx)
1556{
1557 int err = parse_num_or_str(inp, num, str, " ");
1558
1559 if (!err && *str)
1560 err = parse_sym_idx(inp, idx);
1561
1562 return err;
1563}
1564
1565static int parse_one_filter(struct addr_filter *filt, const char **filter_inp)
1566{
1567 char *fstr;
1568 int err;
1569
1570 filt->str = fstr = strdup(*filter_inp);
1571 if (!fstr)
1572 return -ENOMEM;
1573
1574 err = parse_num_or_str(&fstr, NULL, &filt->action, " ");
1575 if (err)
1576 goto out_err;
1577
1578 err = parse_action(filt);
1579 if (err)
1580 goto out_err;
1581
1582 err = parse_addr_size(&fstr, &filt->addr, &filt->sym_from,
1583 &filt->sym_from_idx);
1584 if (err)
1585 goto out_err;
1586
1587 fstr += strspn(fstr, " ");
1588
1589 if (*fstr == '/') {
1590 fstr += 1;
1591 err = parse_addr_size(&fstr, &filt->size, &filt->sym_to,
1592 &filt->sym_to_idx);
1593 if (err)
1594 goto out_err;
1595 filt->range = true;
1596 }
1597
1598 fstr += strspn(fstr, " ");
1599
1600 if (*fstr == '@') {
1601 fstr += 1;
1602 err = parse_num_or_str(&fstr, NULL, &filt->filename, " ,");
1603 if (err)
1604 goto out_err;
1605 }
1606
1607 fstr += strspn(fstr, " ,");
1608
1609 *filter_inp += fstr - filt->str;
1610
1611 return 0;
1612
1613out_err:
1614 addr_filter__free_str(filt);
1615
1616 return err;
1617}
1618
1619int addr_filters__parse_bare_filter(struct addr_filters *filts,
1620 const char *filter)
1621{
1622 struct addr_filter *filt;
1623 const char *fstr = filter;
1624 int err;
1625
1626 while (*fstr) {
1627 filt = addr_filter__new();
1628 err = parse_one_filter(filt, &fstr);
1629 if (err) {
1630 addr_filter__free(filt);
1631 addr_filters__exit(filts);
1632 return err;
1633 }
1634 addr_filters__add(filts, filt);
1635 }
1636
1637 return 0;
1638}
1639
1640struct sym_args {
1641 const char *name;
1642 u64 start;
1643 u64 size;
1644 int idx;
1645 int cnt;
1646 bool started;
1647 bool global;
1648 bool selected;
1649 bool duplicate;
1650 bool near;
1651};
1652
1653static bool kern_sym_match(struct sym_args *args, const char *name, char type)
1654{
1655 /* A function with the same name, and global or the n'th found or any */
1656 return symbol_type__is_a(type, MAP__FUNCTION) &&
1657 !strcmp(name, args->name) &&
1658 ((args->global && isupper(type)) ||
1659 (args->selected && ++(args->cnt) == args->idx) ||
1660 (!args->global && !args->selected));
1661}
1662
1663static int find_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1664{
1665 struct sym_args *args = arg;
1666
1667 if (args->started) {
1668 if (!args->size)
1669 args->size = start - args->start;
1670 if (args->selected) {
1671 if (args->size)
1672 return 1;
1673 } else if (kern_sym_match(args, name, type)) {
1674 args->duplicate = true;
1675 return 1;
1676 }
1677 } else if (kern_sym_match(args, name, type)) {
1678 args->started = true;
1679 args->start = start;
1680 }
1681
1682 return 0;
1683}
1684
1685static int print_kern_sym_cb(void *arg, const char *name, char type, u64 start)
1686{
1687 struct sym_args *args = arg;
1688
1689 if (kern_sym_match(args, name, type)) {
1690 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1691 ++args->cnt, start, type, name);
1692 args->near = true;
1693 } else if (args->near) {
1694 args->near = false;
1695 pr_err("\t\twhich is near\t\t%s\n", name);
1696 }
1697
1698 return 0;
1699}
1700
1701static int sym_not_found_error(const char *sym_name, int idx)
1702{
1703 if (idx > 0) {
1704 pr_err("N'th occurrence (N=%d) of symbol '%s' not found.\n",
1705 idx, sym_name);
1706 } else if (!idx) {
1707 pr_err("Global symbol '%s' not found.\n", sym_name);
1708 } else {
1709 pr_err("Symbol '%s' not found.\n", sym_name);
1710 }
1711 pr_err("Note that symbols must be functions.\n");
1712
1713 return -EINVAL;
1714}
1715
1716static int find_kern_sym(const char *sym_name, u64 *start, u64 *size, int idx)
1717{
1718 struct sym_args args = {
1719 .name = sym_name,
1720 .idx = idx,
1721 .global = !idx,
1722 .selected = idx > 0,
1723 };
1724 int err;
1725
1726 *start = 0;
1727 *size = 0;
1728
1729 err = kallsyms__parse("/proc/kallsyms", &args, find_kern_sym_cb);
1730 if (err < 0) {
1731 pr_err("Failed to parse /proc/kallsyms\n");
1732 return err;
1733 }
1734
1735 if (args.duplicate) {
1736 pr_err("Multiple kernel symbols with name '%s'\n", sym_name);
1737 args.cnt = 0;
1738 kallsyms__parse("/proc/kallsyms", &args, print_kern_sym_cb);
1739 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1740 sym_name);
1741 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1742 return -EINVAL;
1743 }
1744
1745 if (!args.started) {
1746 pr_err("Kernel symbol lookup: ");
1747 return sym_not_found_error(sym_name, idx);
1748 }
1749
1750 *start = args.start;
1751 *size = args.size;
1752
1753 return 0;
1754}
1755
1756static int find_entire_kern_cb(void *arg, const char *name __maybe_unused,
1757 char type, u64 start)
1758{
1759 struct sym_args *args = arg;
1760
1761 if (!symbol_type__is_a(type, MAP__FUNCTION))
1762 return 0;
1763
1764 if (!args->started) {
1765 args->started = true;
1766 args->start = start;
1767 }
1768 /* Don't know exactly where the kernel ends, so we add a page */
1769 args->size = round_up(start, page_size) + page_size - args->start;
1770
1771 return 0;
1772}
1773
1774static int addr_filter__entire_kernel(struct addr_filter *filt)
1775{
1776 struct sym_args args = { .started = false };
1777 int err;
1778
1779 err = kallsyms__parse("/proc/kallsyms", &args, find_entire_kern_cb);
1780 if (err < 0 || !args.started) {
1781 pr_err("Failed to parse /proc/kallsyms\n");
1782 return err;
1783 }
1784
1785 filt->addr = args.start;
1786 filt->size = args.size;
1787
1788 return 0;
1789}
1790
1791static int check_end_after_start(struct addr_filter *filt, u64 start, u64 size)
1792{
1793 if (start + size >= filt->addr)
1794 return 0;
1795
1796 if (filt->sym_from) {
1797 pr_err("Symbol '%s' (0x%"PRIx64") comes before '%s' (0x%"PRIx64")\n",
1798 filt->sym_to, start, filt->sym_from, filt->addr);
1799 } else {
1800 pr_err("Symbol '%s' (0x%"PRIx64") comes before address 0x%"PRIx64")\n",
1801 filt->sym_to, start, filt->addr);
1802 }
1803
1804 return -EINVAL;
1805}
1806
1807static int addr_filter__resolve_kernel_syms(struct addr_filter *filt)
1808{
1809 bool no_size = false;
1810 u64 start, size;
1811 int err;
1812
1813 if (symbol_conf.kptr_restrict) {
1814 pr_err("Kernel addresses are restricted. Unable to resolve kernel symbols.\n");
1815 return -EINVAL;
1816 }
1817
1818 if (filt->sym_from && !strcmp(filt->sym_from, "*"))
1819 return addr_filter__entire_kernel(filt);
1820
1821 if (filt->sym_from) {
1822 err = find_kern_sym(filt->sym_from, &start, &size,
1823 filt->sym_from_idx);
1824 if (err)
1825 return err;
1826 filt->addr = start;
1827 if (filt->range && !filt->size && !filt->sym_to) {
1828 filt->size = size;
1829 no_size = !!size;
1830 }
1831 }
1832
1833 if (filt->sym_to) {
1834 err = find_kern_sym(filt->sym_to, &start, &size,
1835 filt->sym_to_idx);
1836 if (err)
1837 return err;
1838
1839 err = check_end_after_start(filt, start, size);
1840 if (err)
1841 return err;
1842 filt->size = start + size - filt->addr;
1843 no_size = !!size;
1844 }
1845
1846 /* The very last symbol in kallsyms does not imply a particular size */
1847 if (no_size) {
1848 pr_err("Cannot determine size of symbol '%s'\n",
1849 filt->sym_to ? filt->sym_to : filt->sym_from);
1850 return -EINVAL;
1851 }
1852
1853 return 0;
1854}
1855
1856static struct dso *load_dso(const char *name)
1857{
1858 struct map *map;
1859 struct dso *dso;
1860
1861 map = dso__new_map(name);
1862 if (!map)
1863 return NULL;
1864
1865 map__load(map);
1866
1867 dso = dso__get(map->dso);
1868
1869 map__put(map);
1870
1871 return dso;
1872}
1873
1874static bool dso_sym_match(struct symbol *sym, const char *name, int *cnt,
1875 int idx)
1876{
1877 /* Same name, and global or the n'th found or any */
1878 return !arch__compare_symbol_names(name, sym->name) &&
1879 ((!idx && sym->binding == STB_GLOBAL) ||
1880 (idx > 0 && ++*cnt == idx) ||
1881 idx < 0);
1882}
1883
1884static void print_duplicate_syms(struct dso *dso, const char *sym_name)
1885{
1886 struct symbol *sym;
1887 bool near = false;
1888 int cnt = 0;
1889
1890 pr_err("Multiple symbols with name '%s'\n", sym_name);
1891
1892 sym = dso__first_symbol(dso, MAP__FUNCTION);
1893 while (sym) {
1894 if (dso_sym_match(sym, sym_name, &cnt, -1)) {
1895 pr_err("#%d\t0x%"PRIx64"\t%c\t%s\n",
1896 ++cnt, sym->start,
1897 sym->binding == STB_GLOBAL ? 'g' :
1898 sym->binding == STB_LOCAL ? 'l' : 'w',
1899 sym->name);
1900 near = true;
1901 } else if (near) {
1902 near = false;
1903 pr_err("\t\twhich is near\t\t%s\n", sym->name);
1904 }
1905 sym = dso__next_symbol(sym);
1906 }
1907
1908 pr_err("Disambiguate symbol name by inserting #n after the name e.g. %s #2\n",
1909 sym_name);
1910 pr_err("Or select a global symbol by inserting #0 or #g or #G\n");
1911}
1912
1913static int find_dso_sym(struct dso *dso, const char *sym_name, u64 *start,
1914 u64 *size, int idx)
1915{
1916 struct symbol *sym;
1917 int cnt = 0;
1918
1919 *start = 0;
1920 *size = 0;
1921
1922 sym = dso__first_symbol(dso, MAP__FUNCTION);
1923 while (sym) {
1924 if (*start) {
1925 if (!*size)
1926 *size = sym->start - *start;
1927 if (idx > 0) {
1928 if (*size)
1929 return 1;
1930 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1931 print_duplicate_syms(dso, sym_name);
1932 return -EINVAL;
1933 }
1934 } else if (dso_sym_match(sym, sym_name, &cnt, idx)) {
1935 *start = sym->start;
1936 *size = sym->end - sym->start;
1937 }
1938 sym = dso__next_symbol(sym);
1939 }
1940
1941 if (!*start)
1942 return sym_not_found_error(sym_name, idx);
1943
1944 return 0;
1945}
1946
1947static int addr_filter__entire_dso(struct addr_filter *filt, struct dso *dso)
1948{
1949 struct symbol *first_sym = dso__first_symbol(dso, MAP__FUNCTION);
1950 struct symbol *last_sym = dso__last_symbol(dso, MAP__FUNCTION);
1951
1952 if (!first_sym || !last_sym) {
1953 pr_err("Failed to determine filter for %s\nNo symbols found.\n",
1954 filt->filename);
1955 return -EINVAL;
1956 }
1957
1958 filt->addr = first_sym->start;
1959 filt->size = last_sym->end - first_sym->start;
1960
1961 return 0;
1962}
1963
1964static int addr_filter__resolve_syms(struct addr_filter *filt)
1965{
1966 u64 start, size;
1967 struct dso *dso;
1968 int err = 0;
1969
1970 if (!filt->sym_from && !filt->sym_to)
1971 return 0;
1972
1973 if (!filt->filename)
1974 return addr_filter__resolve_kernel_syms(filt);
1975
1976 dso = load_dso(filt->filename);
1977 if (!dso) {
1978 pr_err("Failed to load symbols from: %s\n", filt->filename);
1979 return -EINVAL;
1980 }
1981
1982 if (filt->sym_from && !strcmp(filt->sym_from, "*")) {
1983 err = addr_filter__entire_dso(filt, dso);
1984 goto put_dso;
1985 }
1986
1987 if (filt->sym_from) {
1988 err = find_dso_sym(dso, filt->sym_from, &start, &size,
1989 filt->sym_from_idx);
1990 if (err)
1991 goto put_dso;
1992 filt->addr = start;
1993 if (filt->range && !filt->size && !filt->sym_to)
1994 filt->size = size;
1995 }
1996
1997 if (filt->sym_to) {
1998 err = find_dso_sym(dso, filt->sym_to, &start, &size,
1999 filt->sym_to_idx);
2000 if (err)
2001 goto put_dso;
2002
2003 err = check_end_after_start(filt, start, size);
2004 if (err)
2005 return err;
2006
2007 filt->size = start + size - filt->addr;
2008 }
2009
2010put_dso:
2011 dso__put(dso);
2012
2013 return err;
2014}
2015
2016static char *addr_filter__to_str(struct addr_filter *filt)
2017{
2018 char filename_buf[PATH_MAX];
2019 const char *at = "";
2020 const char *fn = "";
2021 char *filter;
2022 int err;
2023
2024 if (filt->filename) {
2025 at = "@";
2026 fn = realpath(filt->filename, filename_buf);
2027 if (!fn)
2028 return NULL;
2029 }
2030
2031 if (filt->range) {
2032 err = asprintf(&filter, "%s 0x%"PRIx64"/0x%"PRIx64"%s%s",
2033 filt->action, filt->addr, filt->size, at, fn);
2034 } else {
2035 err = asprintf(&filter, "%s 0x%"PRIx64"%s%s",
2036 filt->action, filt->addr, at, fn);
2037 }
2038
2039 return err < 0 ? NULL : filter;
2040}
2041
2042static int parse_addr_filter(struct perf_evsel *evsel, const char *filter,
2043 int max_nr)
2044{
2045 struct addr_filters filts;
2046 struct addr_filter *filt;
2047 int err;
2048
2049 addr_filters__init(&filts);
2050
2051 err = addr_filters__parse_bare_filter(&filts, filter);
2052 if (err)
2053 goto out_exit;
2054
2055 if (filts.cnt > max_nr) {
2056 pr_err("Error: number of address filters (%d) exceeds maximum (%d)\n",
2057 filts.cnt, max_nr);
2058 err = -EINVAL;
2059 goto out_exit;
2060 }
2061
2062 list_for_each_entry(filt, &filts.head, list) {
2063 char *new_filter;
2064
2065 err = addr_filter__resolve_syms(filt);
2066 if (err)
2067 goto out_exit;
2068
2069 new_filter = addr_filter__to_str(filt);
2070 if (!new_filter) {
2071 err = -ENOMEM;
2072 goto out_exit;
2073 }
2074
2075 if (perf_evsel__append_addr_filter(evsel, new_filter)) {
2076 err = -ENOMEM;
2077 goto out_exit;
2078 }
2079 }
2080
2081out_exit:
2082 addr_filters__exit(&filts);
2083
2084 if (err) {
2085 pr_err("Failed to parse address filter: '%s'\n", filter);
2086 pr_err("Filter format is: filter|start|stop|tracestop <start symbol or address> [/ <end symbol or size>] [@<file name>]\n");
2087 pr_err("Where multiple filters are separated by space or comma.\n");
2088 }
2089
2090 return err;
2091}
2092
2093static struct perf_pmu *perf_evsel__find_pmu(struct perf_evsel *evsel)
2094{
2095 struct perf_pmu *pmu = NULL;
2096
2097 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
2098 if (pmu->type == evsel->attr.type)
2099 break;
2100 }
2101
2102 return pmu;
2103}
2104
2105static int perf_evsel__nr_addr_filter(struct perf_evsel *evsel)
2106{
2107 struct perf_pmu *pmu = perf_evsel__find_pmu(evsel);
2108 int nr_addr_filters = 0;
2109
2110 if (!pmu)
2111 return 0;
2112
2113 perf_pmu__scan_file(pmu, "nr_addr_filters", "%d", &nr_addr_filters);
2114
2115 return nr_addr_filters;
2116}
2117
2118int auxtrace_parse_filters(struct perf_evlist *evlist)
2119{
2120 struct perf_evsel *evsel;
2121 char *filter;
2122 int err, max_nr;
2123
2124 evlist__for_each_entry(evlist, evsel) {
2125 filter = evsel->filter;
2126 max_nr = perf_evsel__nr_addr_filter(evsel);
2127 if (!filter || !max_nr)
2128 continue;
2129 evsel->filter = NULL;
2130 err = parse_addr_filter(evsel, filter, max_nr);
2131 free(filter);
2132 if (err)
2133 return err;
2134 pr_debug("Address filter: %s\n", evsel->filter);
2135 }
2136
2137 return 0;
2138}
diff --git a/tools/perf/util/auxtrace.h b/tools/perf/util/auxtrace.h
index 767989e0e312..26fb1ee5746a 100644
--- a/tools/perf/util/auxtrace.h
+++ b/tools/perf/util/auxtrace.h
@@ -41,6 +41,7 @@ enum auxtrace_type {
41 PERF_AUXTRACE_UNKNOWN, 41 PERF_AUXTRACE_UNKNOWN,
42 PERF_AUXTRACE_INTEL_PT, 42 PERF_AUXTRACE_INTEL_PT,
43 PERF_AUXTRACE_INTEL_BTS, 43 PERF_AUXTRACE_INTEL_BTS,
44 PERF_AUXTRACE_CS_ETM,
44}; 45};
45 46
46enum itrace_period_type { 47enum itrace_period_type {
@@ -63,6 +64,7 @@ enum itrace_period_type {
63 * @calls: limit branch samples to calls (can be combined with @returns) 64 * @calls: limit branch samples to calls (can be combined with @returns)
64 * @returns: limit branch samples to returns (can be combined with @calls) 65 * @returns: limit branch samples to returns (can be combined with @calls)
65 * @callchain: add callchain to 'instructions' events 66 * @callchain: add callchain to 'instructions' events
67 * @thread_stack: feed branches to the thread_stack
66 * @last_branch: add branch context to 'instruction' events 68 * @last_branch: add branch context to 'instruction' events
67 * @callchain_sz: maximum callchain size 69 * @callchain_sz: maximum callchain size
68 * @last_branch_sz: branch context size 70 * @last_branch_sz: branch context size
@@ -82,6 +84,7 @@ struct itrace_synth_opts {
82 bool calls; 84 bool calls;
83 bool returns; 85 bool returns;
84 bool callchain; 86 bool callchain;
87 bool thread_stack;
85 bool last_branch; 88 bool last_branch;
86 unsigned int callchain_sz; 89 unsigned int callchain_sz;
87 unsigned int last_branch_sz; 90 unsigned int last_branch_sz;
@@ -315,6 +318,48 @@ struct auxtrace_record {
315 unsigned int alignment; 318 unsigned int alignment;
316}; 319};
317 320
321/**
322 * struct addr_filter - address filter.
323 * @list: list node
324 * @range: true if it is a range filter
325 * @start: true if action is 'filter' or 'start'
326 * @action: 'filter', 'start' or 'stop' ('tracestop' is accepted but converted
327 * to 'stop')
328 * @sym_from: symbol name for the filter address
329 * @sym_to: symbol name that determines the filter size
330 * @sym_from_idx: selects n'th from symbols with the same name (0 means global
331 * and less than 0 means symbol must be unique)
332 * @sym_to_idx: same as @sym_from_idx but for @sym_to
333 * @addr: filter address
334 * @size: filter region size (for range filters)
335 * @filename: DSO file name or NULL for the kernel
336 * @str: allocated string that contains the other string members
337 */
338struct addr_filter {
339 struct list_head list;
340 bool range;
341 bool start;
342 const char *action;
343 const char *sym_from;
344 const char *sym_to;
345 int sym_from_idx;
346 int sym_to_idx;
347 u64 addr;
348 u64 size;
349 const char *filename;
350 char *str;
351};
352
353/**
354 * struct addr_filters - list of address filters.
355 * @head: list of address filters
356 * @cnt: number of address filters
357 */
358struct addr_filters {
359 struct list_head head;
360 int cnt;
361};
362
318#ifdef HAVE_AUXTRACE_SUPPORT 363#ifdef HAVE_AUXTRACE_SUPPORT
319 364
320/* 365/*
@@ -479,6 +524,12 @@ void perf_session__auxtrace_error_inc(struct perf_session *session,
479 union perf_event *event); 524 union perf_event *event);
480void events_stats__auxtrace_error_warn(const struct events_stats *stats); 525void events_stats__auxtrace_error_warn(const struct events_stats *stats);
481 526
527void addr_filters__init(struct addr_filters *filts);
528void addr_filters__exit(struct addr_filters *filts);
529int addr_filters__parse_bare_filter(struct addr_filters *filts,
530 const char *filter);
531int auxtrace_parse_filters(struct perf_evlist *evlist);
532
482static inline int auxtrace__process_event(struct perf_session *session, 533static inline int auxtrace__process_event(struct perf_session *session,
483 union perf_event *event, 534 union perf_event *event,
484 struct perf_sample *sample, 535 struct perf_sample *sample,
@@ -637,6 +688,12 @@ void auxtrace_index__free(struct list_head *head __maybe_unused)
637{ 688{
638} 689}
639 690
691static inline
692int auxtrace_parse_filters(struct perf_evlist *evlist __maybe_unused)
693{
694 return 0;
695}
696
640int auxtrace_mmap__mmap(struct auxtrace_mmap *mm, 697int auxtrace_mmap__mmap(struct auxtrace_mmap *mm,
641 struct auxtrace_mmap_params *mp, 698 struct auxtrace_mmap_params *mp,
642 void *userpg, int fd); 699 void *userpg, int fd);
diff --git a/tools/perf/util/block-range.c b/tools/perf/util/block-range.c
new file mode 100644
index 000000000000..7b3e1d75d803
--- /dev/null
+++ b/tools/perf/util/block-range.c
@@ -0,0 +1,328 @@
1#include "block-range.h"
2#include "annotate.h"
3
4struct {
5 struct rb_root root;
6 u64 blocks;
7} block_ranges;
8
9static void block_range__debug(void)
10{
11 /*
12 * XXX still paranoid for now; see if we can make this depend on
13 * DEBUG=1 builds.
14 */
15#if 1
16 struct rb_node *rb;
17 u64 old = 0; /* NULL isn't executable */
18
19 for (rb = rb_first(&block_ranges.root); rb; rb = rb_next(rb)) {
20 struct block_range *entry = rb_entry(rb, struct block_range, node);
21
22 assert(old < entry->start);
23 assert(entry->start <= entry->end); /* single instruction block; jump to a jump */
24
25 old = entry->end;
26 }
27#endif
28}
29
30struct block_range *block_range__find(u64 addr)
31{
32 struct rb_node **p = &block_ranges.root.rb_node;
33 struct rb_node *parent = NULL;
34 struct block_range *entry;
35
36 while (*p != NULL) {
37 parent = *p;
38 entry = rb_entry(parent, struct block_range, node);
39
40 if (addr < entry->start)
41 p = &parent->rb_left;
42 else if (addr > entry->end)
43 p = &parent->rb_right;
44 else
45 return entry;
46 }
47
48 return NULL;
49}
50
51static inline void rb_link_left_of_node(struct rb_node *left, struct rb_node *node)
52{
53 struct rb_node **p = &node->rb_left;
54 while (*p) {
55 node = *p;
56 p = &node->rb_right;
57 }
58 rb_link_node(left, node, p);
59}
60
61static inline void rb_link_right_of_node(struct rb_node *right, struct rb_node *node)
62{
63 struct rb_node **p = &node->rb_right;
64 while (*p) {
65 node = *p;
66 p = &node->rb_left;
67 }
68 rb_link_node(right, node, p);
69}
70
71/**
72 * block_range__create
73 * @start: branch target starting this basic block
74 * @end: branch ending this basic block
75 *
76 * Create all the required block ranges to precisely span the given range.
77 */
78struct block_range_iter block_range__create(u64 start, u64 end)
79{
80 struct rb_node **p = &block_ranges.root.rb_node;
81 struct rb_node *n, *parent = NULL;
82 struct block_range *next, *entry = NULL;
83 struct block_range_iter iter = { NULL, NULL };
84
85 while (*p != NULL) {
86 parent = *p;
87 entry = rb_entry(parent, struct block_range, node);
88
89 if (start < entry->start)
90 p = &parent->rb_left;
91 else if (start > entry->end)
92 p = &parent->rb_right;
93 else
94 break;
95 }
96
97 /*
98 * Didn't find anything.. there's a hole at @start, however @end might
99 * be inside/behind the next range.
100 */
101 if (!*p) {
102 if (!entry) /* tree empty */
103 goto do_whole;
104
105 /*
106 * If the last node is before, advance one to find the next.
107 */
108 n = parent;
109 if (entry->end < start) {
110 n = rb_next(n);
111 if (!n)
112 goto do_whole;
113 }
114 next = rb_entry(n, struct block_range, node);
115
116 if (next->start <= end) { /* add head: [start...][n->start...] */
117 struct block_range *head = malloc(sizeof(struct block_range));
118 if (!head)
119 return iter;
120
121 *head = (struct block_range){
122 .start = start,
123 .end = next->start - 1,
124 .is_target = 1,
125 .is_branch = 0,
126 };
127
128 rb_link_left_of_node(&head->node, &next->node);
129 rb_insert_color(&head->node, &block_ranges.root);
130 block_range__debug();
131
132 iter.start = head;
133 goto do_tail;
134 }
135
136do_whole:
137 /*
138 * The whole [start..end] range is non-overlapping.
139 */
140 entry = malloc(sizeof(struct block_range));
141 if (!entry)
142 return iter;
143
144 *entry = (struct block_range){
145 .start = start,
146 .end = end,
147 .is_target = 1,
148 .is_branch = 1,
149 };
150
151 rb_link_node(&entry->node, parent, p);
152 rb_insert_color(&entry->node, &block_ranges.root);
153 block_range__debug();
154
155 iter.start = entry;
156 iter.end = entry;
157 goto done;
158 }
159
160 /*
161 * We found a range that overlapped with ours, split if needed.
162 */
163 if (entry->start < start) { /* split: [e->start...][start...] */
164 struct block_range *head = malloc(sizeof(struct block_range));
165 if (!head)
166 return iter;
167
168 *head = (struct block_range){
169 .start = entry->start,
170 .end = start - 1,
171 .is_target = entry->is_target,
172 .is_branch = 0,
173
174 .coverage = entry->coverage,
175 .entry = entry->entry,
176 };
177
178 entry->start = start;
179 entry->is_target = 1;
180 entry->entry = 0;
181
182 rb_link_left_of_node(&head->node, &entry->node);
183 rb_insert_color(&head->node, &block_ranges.root);
184 block_range__debug();
185
186 } else if (entry->start == start)
187 entry->is_target = 1;
188
189 iter.start = entry;
190
191do_tail:
192 /*
193 * At this point we've got: @iter.start = [@start...] but @end can still be
194 * inside or beyond it.
195 */
196 entry = iter.start;
197 for (;;) {
198 /*
199 * If @end is inside @entry, split.
200 */
201 if (end < entry->end) { /* split: [...end][...e->end] */
202 struct block_range *tail = malloc(sizeof(struct block_range));
203 if (!tail)
204 return iter;
205
206 *tail = (struct block_range){
207 .start = end + 1,
208 .end = entry->end,
209 .is_target = 0,
210 .is_branch = entry->is_branch,
211
212 .coverage = entry->coverage,
213 .taken = entry->taken,
214 .pred = entry->pred,
215 };
216
217 entry->end = end;
218 entry->is_branch = 1;
219 entry->taken = 0;
220 entry->pred = 0;
221
222 rb_link_right_of_node(&tail->node, &entry->node);
223 rb_insert_color(&tail->node, &block_ranges.root);
224 block_range__debug();
225
226 iter.end = entry;
227 goto done;
228 }
229
230 /*
231 * If @end matches @entry, done
232 */
233 if (end == entry->end) {
234 entry->is_branch = 1;
235 iter.end = entry;
236 goto done;
237 }
238
239 next = block_range__next(entry);
240 if (!next)
241 goto add_tail;
242
243 /*
244 * If @end is in beyond @entry but not inside @next, add tail.
245 */
246 if (end < next->start) { /* add tail: [...e->end][...end] */
247 struct block_range *tail;
248add_tail:
249 tail = malloc(sizeof(struct block_range));
250 if (!tail)
251 return iter;
252
253 *tail = (struct block_range){
254 .start = entry->end + 1,
255 .end = end,
256 .is_target = 0,
257 .is_branch = 1,
258 };
259
260 rb_link_right_of_node(&tail->node, &entry->node);
261 rb_insert_color(&tail->node, &block_ranges.root);
262 block_range__debug();
263
264 iter.end = tail;
265 goto done;
266 }
267
268 /*
269 * If there is a hole between @entry and @next, fill it.
270 */
271 if (entry->end + 1 != next->start) {
272 struct block_range *hole = malloc(sizeof(struct block_range));
273 if (!hole)
274 return iter;
275
276 *hole = (struct block_range){
277 .start = entry->end + 1,
278 .end = next->start - 1,
279 .is_target = 0,
280 .is_branch = 0,
281 };
282
283 rb_link_left_of_node(&hole->node, &next->node);
284 rb_insert_color(&hole->node, &block_ranges.root);
285 block_range__debug();
286 }
287
288 entry = next;
289 }
290
291done:
292 assert(iter.start->start == start && iter.start->is_target);
293 assert(iter.end->end == end && iter.end->is_branch);
294
295 block_ranges.blocks++;
296
297 return iter;
298}
299
300
301/*
302 * Compute coverage as:
303 *
304 * br->coverage / br->sym->max_coverage
305 *
306 * This ensures each symbol has a 100% spot, to reflect that each symbol has a
307 * most covered section.
308 *
309 * Returns [0-1] for coverage and -1 if we had no data what so ever or the
310 * symbol does not exist.
311 */
312double block_range__coverage(struct block_range *br)
313{
314 struct symbol *sym;
315
316 if (!br) {
317 if (block_ranges.blocks)
318 return 0;
319
320 return -1;
321 }
322
323 sym = br->sym;
324 if (!sym)
325 return -1;
326
327 return (double)br->coverage / symbol__annotation(sym)->max_coverage;
328}
diff --git a/tools/perf/util/block-range.h b/tools/perf/util/block-range.h
new file mode 100644
index 000000000000..a8c841381131
--- /dev/null
+++ b/tools/perf/util/block-range.h
@@ -0,0 +1,71 @@
1#ifndef __PERF_BLOCK_RANGE_H
2#define __PERF_BLOCK_RANGE_H
3
4#include "symbol.h"
5
6/*
7 * struct block_range - non-overlapping parts of basic blocks
8 * @node: treenode
9 * @start: inclusive start of range
10 * @end: inclusive end of range
11 * @is_target: @start is a jump target
12 * @is_branch: @end is a branch instruction
13 * @coverage: number of blocks that cover this range
14 * @taken: number of times the branch is taken (requires @is_branch)
15 * @pred: number of times the taken branch was predicted
16 */
17struct block_range {
18 struct rb_node node;
19
20 struct symbol *sym;
21
22 u64 start;
23 u64 end;
24
25 int is_target, is_branch;
26
27 u64 coverage;
28 u64 entry;
29 u64 taken;
30 u64 pred;
31};
32
33static inline struct block_range *block_range__next(struct block_range *br)
34{
35 struct rb_node *n = rb_next(&br->node);
36 if (!n)
37 return NULL;
38 return rb_entry(n, struct block_range, node);
39}
40
41struct block_range_iter {
42 struct block_range *start;
43 struct block_range *end;
44};
45
46static inline struct block_range *block_range_iter(struct block_range_iter *iter)
47{
48 return iter->start;
49}
50
51static inline bool block_range_iter__next(struct block_range_iter *iter)
52{
53 if (iter->start == iter->end)
54 return false;
55
56 iter->start = block_range__next(iter->start);
57 return true;
58}
59
60static inline bool block_range_iter__valid(struct block_range_iter *iter)
61{
62 if (!iter->start || !iter->end)
63 return false;
64 return true;
65}
66
67extern struct block_range *block_range__find(u64 addr);
68extern struct block_range_iter block_range__create(u64 start, u64 end);
69extern double block_range__coverage(struct block_range *br);
70
71#endif /* __PERF_BLOCK_RANGE_H */
diff --git a/tools/perf/util/bpf-loader.c b/tools/perf/util/bpf-loader.c
index 493307d1414c..2b2c9b82f5ab 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;
@@ -499,7 +531,7 @@ static int map_prologue(struct perf_probe_event *pev, int *mapping,
499 531
500 ptevs = malloc(array_sz); 532 ptevs = malloc(array_sz);
501 if (!ptevs) { 533 if (!ptevs) {
502 pr_debug("No ehough memory: alloc ptevs failed\n"); 534 pr_debug("No enough memory: alloc ptevs failed\n");
503 return -ENOMEM; 535 return -ENOMEM;
504 } 536 }
505 537
@@ -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;
@@ -897,15 +949,12 @@ bpf_map_priv__clone(struct bpf_map_priv *priv)
897static int 949static int
898bpf_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)
899{ 951{
900 struct bpf_map_priv *priv; 952 const char *map_name = bpf_map__name(map);
901 const char *map_name; 953 struct bpf_map_priv *priv = bpf_map__priv(map);
902 int err;
903 954
904 map_name = bpf_map__get_name(map); 955 if (IS_ERR(priv)) {
905 err = bpf_map__get_private(map, (void **)&priv);
906 if (err) {
907 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);
908 return err; 957 return PTR_ERR(priv);
909 } 958 }
910 959
911 if (!priv) { 960 if (!priv) {
@@ -916,7 +965,7 @@ bpf_map__add_op(struct bpf_map *map, struct bpf_map_op *op)
916 } 965 }
917 INIT_LIST_HEAD(&priv->ops_list); 966 INIT_LIST_HEAD(&priv->ops_list);
918 967
919 if (bpf_map__set_private(map, priv, bpf_map_priv__clear)) { 968 if (bpf_map__set_priv(map, priv, bpf_map_priv__clear)) {
920 free(priv); 969 free(priv);
921 return -BPF_LOADER_ERRNO__INTERNAL; 970 return -BPF_LOADER_ERRNO__INTERNAL;
922 } 971 }
@@ -948,30 +997,26 @@ static int
948__bpf_map__config_value(struct bpf_map *map, 997__bpf_map__config_value(struct bpf_map *map,
949 struct parse_events_term *term) 998 struct parse_events_term *term)
950{ 999{
951 struct bpf_map_def def;
952 struct bpf_map_op *op; 1000 struct bpf_map_op *op;
953 const char *map_name; 1001 const char *map_name = bpf_map__name(map);
954 int err; 1002 const struct bpf_map_def *def = bpf_map__def(map);
955 1003
956 map_name = bpf_map__get_name(map); 1004 if (IS_ERR(def)) {
957
958 err = bpf_map__get_def(map, &def);
959 if (err) {
960 pr_debug("Unable to get map definition from '%s'\n", 1005 pr_debug("Unable to get map definition from '%s'\n",
961 map_name); 1006 map_name);
962 return -BPF_LOADER_ERRNO__INTERNAL; 1007 return -BPF_LOADER_ERRNO__INTERNAL;
963 } 1008 }
964 1009
965 if (def.type != BPF_MAP_TYPE_ARRAY) { 1010 if (def->type != BPF_MAP_TYPE_ARRAY) {
966 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",
967 map_name); 1012 map_name);
968 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; 1013 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
969 } 1014 }
970 if (def.key_size < sizeof(unsigned int)) { 1015 if (def->key_size < sizeof(unsigned int)) {
971 pr_debug("Map %s has incorrect key size\n", map_name); 1016 pr_debug("Map %s has incorrect key size\n", map_name);
972 return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE; 1017 return -BPF_LOADER_ERRNO__OBJCONF_MAP_KEYSIZE;
973 } 1018 }
974 switch (def.value_size) { 1019 switch (def->value_size) {
975 case 1: 1020 case 1:
976 case 2: 1021 case 2:
977 case 4: 1022 case 4:
@@ -1014,12 +1059,10 @@ __bpf_map__config_event(struct bpf_map *map,
1014 struct perf_evlist *evlist) 1059 struct perf_evlist *evlist)
1015{ 1060{
1016 struct perf_evsel *evsel; 1061 struct perf_evsel *evsel;
1017 struct bpf_map_def def; 1062 const struct bpf_map_def *def;
1018 struct bpf_map_op *op; 1063 struct bpf_map_op *op;
1019 const char *map_name; 1064 const char *map_name = bpf_map__name(map);
1020 int err;
1021 1065
1022 map_name = bpf_map__get_name(map);
1023 evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str); 1066 evsel = perf_evlist__find_evsel_by_str(evlist, term->val.str);
1024 if (!evsel) { 1067 if (!evsel) {
1025 pr_debug("Event (for '%s') '%s' doesn't exist\n", 1068 pr_debug("Event (for '%s') '%s' doesn't exist\n",
@@ -1027,18 +1070,18 @@ __bpf_map__config_event(struct bpf_map *map,
1027 return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT; 1070 return -BPF_LOADER_ERRNO__OBJCONF_MAP_NOEVT;
1028 } 1071 }
1029 1072
1030 err = bpf_map__get_def(map, &def); 1073 def = bpf_map__def(map);
1031 if (err) { 1074 if (IS_ERR(def)) {
1032 pr_debug("Unable to get map definition from '%s'\n", 1075 pr_debug("Unable to get map definition from '%s'\n",
1033 map_name); 1076 map_name);
1034 return err; 1077 return PTR_ERR(def);
1035 } 1078 }
1036 1079
1037 /* 1080 /*
1038 * No need to check key_size and value_size: 1081 * No need to check key_size and value_size:
1039 * kernel has already checked them. 1082 * kernel has already checked them.
1040 */ 1083 */
1041 if (def.type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) { 1084 if (def->type != BPF_MAP_TYPE_PERF_EVENT_ARRAY) {
1042 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",
1043 map_name); 1086 map_name);
1044 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE; 1087 return -BPF_LOADER_ERRNO__OBJCONF_MAP_TYPE;
@@ -1087,9 +1130,8 @@ config_map_indices_range_check(struct parse_events_term *term,
1087 const char *map_name) 1130 const char *map_name)
1088{ 1131{
1089 struct parse_events_array *array = &term->array; 1132 struct parse_events_array *array = &term->array;
1090 struct bpf_map_def def; 1133 const struct bpf_map_def *def;
1091 unsigned int i; 1134 unsigned int i;
1092 int err;
1093 1135
1094 if (!array->nr_ranges) 1136 if (!array->nr_ranges)
1095 return 0; 1137 return 0;
@@ -1099,8 +1141,8 @@ config_map_indices_range_check(struct parse_events_term *term,
1099 return -BPF_LOADER_ERRNO__INTERNAL; 1141 return -BPF_LOADER_ERRNO__INTERNAL;
1100 } 1142 }
1101 1143
1102 err = bpf_map__get_def(map, &def); 1144 def = bpf_map__def(map);
1103 if (err) { 1145 if (IS_ERR(def)) {
1104 pr_debug("ERROR: Unable to get map definition from '%s'\n", 1146 pr_debug("ERROR: Unable to get map definition from '%s'\n",
1105 map_name); 1147 map_name);
1106 return -BPF_LOADER_ERRNO__INTERNAL; 1148 return -BPF_LOADER_ERRNO__INTERNAL;
@@ -1111,7 +1153,7 @@ config_map_indices_range_check(struct parse_events_term *term,
1111 size_t length = array->ranges[i].length; 1153 size_t length = array->ranges[i].length;
1112 unsigned int idx = start + length - 1; 1154 unsigned int idx = start + length - 1;
1113 1155
1114 if (idx >= def.max_entries) { 1156 if (idx >= def->max_entries) {
1115 pr_debug("ERROR: index %d too large\n", idx); 1157 pr_debug("ERROR: index %d too large\n", idx);
1116 return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG; 1158 return -BPF_LOADER_ERRNO__OBJCONF_MAP_IDX2BIG;
1117 } 1159 }
@@ -1147,7 +1189,7 @@ bpf__obj_config_map(struct bpf_object *obj,
1147 goto out; 1189 goto out;
1148 } 1190 }
1149 1191
1150 map = bpf_object__get_map_by_name(obj, map_name); 1192 map = bpf_object__find_map_by_name(obj, map_name);
1151 if (!map) { 1193 if (!map) {
1152 pr_debug("ERROR: Map %s doesn't exist\n", map_name); 1194 pr_debug("ERROR: Map %s doesn't exist\n", map_name);
1153 err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST; 1195 err = -BPF_LOADER_ERRNO__OBJCONF_MAP_NOTEXIST;
@@ -1204,14 +1246,14 @@ out:
1204} 1246}
1205 1247
1206typedef int (*map_config_func_t)(const char *name, int map_fd, 1248typedef int (*map_config_func_t)(const char *name, int map_fd,
1207 struct bpf_map_def *pdef, 1249 const struct bpf_map_def *pdef,
1208 struct bpf_map_op *op, 1250 struct bpf_map_op *op,
1209 void *pkey, void *arg); 1251 void *pkey, void *arg);
1210 1252
1211static int 1253static int
1212foreach_key_array_all(map_config_func_t func, 1254foreach_key_array_all(map_config_func_t func,
1213 void *arg, const char *name, 1255 void *arg, const char *name,
1214 int map_fd, struct bpf_map_def *pdef, 1256 int map_fd, const struct bpf_map_def *pdef,
1215 struct bpf_map_op *op) 1257 struct bpf_map_op *op)
1216{ 1258{
1217 unsigned int i; 1259 unsigned int i;
@@ -1231,7 +1273,7 @@ foreach_key_array_all(map_config_func_t func,
1231static int 1273static int
1232foreach_key_array_ranges(map_config_func_t func, void *arg, 1274foreach_key_array_ranges(map_config_func_t func, void *arg,
1233 const char *name, int map_fd, 1275 const char *name, int map_fd,
1234 struct bpf_map_def *pdef, 1276 const struct bpf_map_def *pdef,
1235 struct bpf_map_op *op) 1277 struct bpf_map_op *op)
1236{ 1278{
1237 unsigned int i, j; 1279 unsigned int i, j;
@@ -1261,15 +1303,12 @@ bpf_map_config_foreach_key(struct bpf_map *map,
1261 void *arg) 1303 void *arg)
1262{ 1304{
1263 int err, map_fd; 1305 int err, map_fd;
1264 const char *name;
1265 struct bpf_map_op *op; 1306 struct bpf_map_op *op;
1266 struct bpf_map_def def; 1307 const struct bpf_map_def *def;
1267 struct bpf_map_priv *priv; 1308 const char *name = bpf_map__name(map);
1309 struct bpf_map_priv *priv = bpf_map__priv(map);
1268 1310
1269 name = bpf_map__get_name(map); 1311 if (IS_ERR(priv)) {
1270
1271 err = bpf_map__get_private(map, (void **)&priv);
1272 if (err) {
1273 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);
1274 return -BPF_LOADER_ERRNO__INTERNAL; 1313 return -BPF_LOADER_ERRNO__INTERNAL;
1275 } 1314 }
@@ -1278,29 +1317,29 @@ bpf_map_config_foreach_key(struct bpf_map *map,
1278 return 0; 1317 return 0;
1279 } 1318 }
1280 1319
1281 err = bpf_map__get_def(map, &def); 1320 def = bpf_map__def(map);
1282 if (err) { 1321 if (IS_ERR(def)) {
1283 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);
1284 return -BPF_LOADER_ERRNO__INTERNAL; 1323 return -BPF_LOADER_ERRNO__INTERNAL;
1285 } 1324 }
1286 map_fd = bpf_map__get_fd(map); 1325 map_fd = bpf_map__fd(map);
1287 if (map_fd < 0) { 1326 if (map_fd < 0) {
1288 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);
1289 return map_fd; 1328 return map_fd;
1290 } 1329 }
1291 1330
1292 list_for_each_entry(op, &priv->ops_list, list) { 1331 list_for_each_entry(op, &priv->ops_list, list) {
1293 switch (def.type) { 1332 switch (def->type) {
1294 case BPF_MAP_TYPE_ARRAY: 1333 case BPF_MAP_TYPE_ARRAY:
1295 case BPF_MAP_TYPE_PERF_EVENT_ARRAY: 1334 case BPF_MAP_TYPE_PERF_EVENT_ARRAY:
1296 switch (op->key_type) { 1335 switch (op->key_type) {
1297 case BPF_MAP_KEY_ALL: 1336 case BPF_MAP_KEY_ALL:
1298 err = foreach_key_array_all(func, arg, name, 1337 err = foreach_key_array_all(func, arg, name,
1299 map_fd, &def, op); 1338 map_fd, def, op);
1300 break; 1339 break;
1301 case BPF_MAP_KEY_RANGES: 1340 case BPF_MAP_KEY_RANGES:
1302 err = foreach_key_array_ranges(func, arg, name, 1341 err = foreach_key_array_ranges(func, arg, name,
1303 map_fd, &def, 1342 map_fd, def,
1304 op); 1343 op);
1305 break; 1344 break;
1306 default: 1345 default:
@@ -1410,7 +1449,7 @@ apply_config_evsel_for_key(const char *name, int map_fd, void *pkey,
1410 1449
1411static int 1450static int
1412apply_obj_config_map_for_key(const char *name, int map_fd, 1451apply_obj_config_map_for_key(const char *name, int map_fd,
1413 struct bpf_map_def *pdef __maybe_unused, 1452 const struct bpf_map_def *pdef,
1414 struct bpf_map_op *op, 1453 struct bpf_map_op *op,
1415 void *pkey, void *arg __maybe_unused) 1454 void *pkey, void *arg __maybe_unused)
1416{ 1455{
@@ -1475,9 +1514,9 @@ int bpf__apply_obj_config(void)
1475 1514
1476#define bpf__for_each_stdout_map(pos, obj, objtmp) \ 1515#define bpf__for_each_stdout_map(pos, obj, objtmp) \
1477 bpf__for_each_map(pos, obj, objtmp) \ 1516 bpf__for_each_map(pos, obj, objtmp) \
1478 if (bpf_map__get_name(pos) && \ 1517 if (bpf_map__name(pos) && \
1479 (strcmp("__bpf_stdout__", \ 1518 (strcmp("__bpf_stdout__", \
1480 bpf_map__get_name(pos)) == 0)) 1519 bpf_map__name(pos)) == 0))
1481 1520
1482int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused) 1521int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
1483{ 1522{
@@ -1489,10 +1528,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
1489 bool need_init = false; 1528 bool need_init = false;
1490 1529
1491 bpf__for_each_stdout_map(map, obj, tmp) { 1530 bpf__for_each_stdout_map(map, obj, tmp) {
1492 struct bpf_map_priv *priv; 1531 struct bpf_map_priv *priv = bpf_map__priv(map);
1493 1532
1494 err = bpf_map__get_private(map, (void **)&priv); 1533 if (IS_ERR(priv))
1495 if (err)
1496 return -BPF_LOADER_ERRNO__INTERNAL; 1534 return -BPF_LOADER_ERRNO__INTERNAL;
1497 1535
1498 /* 1536 /*
@@ -1520,10 +1558,9 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
1520 } 1558 }
1521 1559
1522 bpf__for_each_stdout_map(map, obj, tmp) { 1560 bpf__for_each_stdout_map(map, obj, tmp) {
1523 struct bpf_map_priv *priv; 1561 struct bpf_map_priv *priv = bpf_map__priv(map);
1524 1562
1525 err = bpf_map__get_private(map, (void **)&priv); 1563 if (IS_ERR(priv))
1526 if (err)
1527 return -BPF_LOADER_ERRNO__INTERNAL; 1564 return -BPF_LOADER_ERRNO__INTERNAL;
1528 if (priv) 1565 if (priv)
1529 continue; 1566 continue;
@@ -1533,7 +1570,7 @@ int bpf__setup_stdout(struct perf_evlist *evlist __maybe_unused)
1533 if (!priv) 1570 if (!priv)
1534 return -ENOMEM; 1571 return -ENOMEM;
1535 1572
1536 err = bpf_map__set_private(map, priv, bpf_map_priv__clear); 1573 err = bpf_map__set_priv(map, priv, bpf_map_priv__clear);
1537 if (err) { 1574 if (err) {
1538 bpf_map_priv__clear(map, priv); 1575 bpf_map_priv__clear(map, priv);
1539 return err; 1576 return err;
@@ -1607,7 +1644,7 @@ bpf_loader_strerror(int err, char *buf, size_t size)
1607 snprintf(buf, size, "Unknown bpf loader error %d", err); 1644 snprintf(buf, size, "Unknown bpf loader error %d", err);
1608 else 1645 else
1609 snprintf(buf, size, "%s", 1646 snprintf(buf, size, "%s",
1610 strerror_r(err, sbuf, sizeof(sbuf))); 1647 str_error_r(err, sbuf, sizeof(sbuf)));
1611 1648
1612 buf[size - 1] = '\0'; 1649 buf[size - 1] = '\0';
1613 return -1; 1650 return -1;
@@ -1677,7 +1714,7 @@ int bpf__strerror_load(struct bpf_object *obj,
1677{ 1714{
1678 bpf__strerror_head(err, buf, size); 1715 bpf__strerror_head(err, buf, size);
1679 case LIBBPF_ERRNO__KVER: { 1716 case LIBBPF_ERRNO__KVER: {
1680 unsigned int obj_kver = bpf_object__get_kversion(obj); 1717 unsigned int obj_kver = bpf_object__kversion(obj);
1681 unsigned int real_kver; 1718 unsigned int real_kver;
1682 1719
1683 if (fetch_kernel_version(&real_kver, NULL, 0)) { 1720 if (fetch_kernel_version(&real_kver, NULL, 0)) {
diff --git a/tools/perf/util/bpf-loader.h b/tools/perf/util/bpf-loader.h
index 941e17275aa7..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);
@@ -107,9 +107,9 @@ static inline int bpf__unprobe(struct bpf_object *obj __maybe_unused) { return 0
107static 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; }
108 108
109static inline int 109static inline int
110bpf__foreach_tev(struct bpf_object *obj __maybe_unused, 110bpf__foreach_event(struct bpf_object *obj __maybe_unused,
111 bpf_prog_iter_callback_t func __maybe_unused, 111 bpf_prog_iter_callback_t func __maybe_unused,
112 void *arg __maybe_unused) 112 void *arg __maybe_unused)
113{ 113{
114 return 0; 114 return 0;
115} 115}
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 67e5966503b2..e528c40739cc 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];
172 274
173 id_name = dso__build_id_filename(dso, bf, size); 275 if (!dso->has_build_id)
276 goto err;
277
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
@@ -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)
@@ -368,7 +595,7 @@ int build_id_cache__list_build_ids(const char *pathname,
368 char *dir_name; 595 char *dir_name;
369 int ret = 0; 596 int ret = 0;
370 597
371 dir_name = build_id_cache__dirname_from_path(pathname, false, false); 598 dir_name = build_id_cache__cachedir(NULL, pathname, false, false);
372 if (!dir_name) 599 if (!dir_name)
373 return -ENOMEM; 600 return -ENOMEM;
374 601
@@ -380,12 +607,36 @@ int build_id_cache__list_build_ids(const char *pathname,
380 return ret; 607 return ret;
381} 608}
382 609
610#if defined(HAVE_LIBELF_SUPPORT) && defined(HAVE_GELF_GETNOTE_SUPPORT)
611static int build_id_cache__add_sdt_cache(const char *sbuild_id,
612 const char *realname)
613{
614 struct probe_cache *cache;
615 int ret;
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_debug4("Found %d SDTs in %s\n", ret, realname);
624 if (probe_cache__commit(cache) < 0)
625 ret = -1;
626 }
627 probe_cache__delete(cache);
628 return ret;
629}
630#else
631#define build_id_cache__add_sdt_cache(sbuild_id, realname) (0)
632#endif
633
383int 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,
384 bool is_kallsyms, bool is_vdso) 635 bool is_kallsyms, bool is_vdso)
385{ 636{
386 const size_t size = PATH_MAX; 637 const size_t size = PATH_MAX;
387 char *realname = NULL, *filename = NULL, *dir_name = NULL, 638 char *realname = NULL, *filename = NULL, *dir_name = NULL,
388 *linkname = zalloc(size), *targetname, *tmp; 639 *linkname = zalloc(size), *tmp;
389 int err = -1; 640 int err = -1;
390 641
391 if (!is_kallsyms) { 642 if (!is_kallsyms) {
@@ -394,14 +645,22 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
394 goto out_free; 645 goto out_free;
395 } 646 }
396 647
397 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);
398 if (!dir_name) 650 if (!dir_name)
399 goto out_free; 651 goto out_free;
400 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
401 if (mkdir_p(dir_name, 0755)) 658 if (mkdir_p(dir_name, 0755))
402 goto out_free; 659 goto out_free;
403 660
404 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) {
405 filename = NULL; 664 filename = NULL;
406 goto out_free; 665 goto out_free;
407 } 666 }
@@ -415,7 +674,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
415 goto out_free; 674 goto out_free;
416 } 675 }
417 676
418 if (!build_id__filename(sbuild_id, linkname, size)) 677 if (!build_id_cache__linkname(sbuild_id, linkname, size))
419 goto out_free; 678 goto out_free;
420 tmp = strrchr(linkname, '/'); 679 tmp = strrchr(linkname, '/');
421 *tmp = '\0'; 680 *tmp = '\0';
@@ -424,11 +683,16 @@ int build_id_cache__add_s(const char *sbuild_id, const char *name,
424 goto out_free; 683 goto out_free;
425 684
426 *tmp = '/'; 685 *tmp = '/';
427 targetname = filename + strlen(buildid_dir) - 5; 686 tmp = dir_name + strlen(buildid_dir) - 5;
428 memcpy(targetname, "../..", 5); 687 memcpy(tmp, "../..", 5);
429 688
430 if (symlink(targetname, linkname) == 0) 689 if (symlink(tmp, linkname) == 0)
431 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_debug4("Failed to update/scan SDT cache for %s\n", realname);
695
432out_free: 696out_free:
433 if (!is_kallsyms) 697 if (!is_kallsyms)
434 free(realname); 698 free(realname);
@@ -452,7 +716,7 @@ static int build_id_cache__add_b(const u8 *build_id, size_t build_id_size,
452bool build_id_cache__cached(const char *sbuild_id) 716bool build_id_cache__cached(const char *sbuild_id)
453{ 717{
454 bool ret = false; 718 bool ret = false;
455 char *filename = build_id__filename(sbuild_id, NULL, 0); 719 char *filename = build_id_cache__linkname(sbuild_id, NULL, 0);
456 720
457 if (filename && !access(filename, F_OK)) 721 if (filename && !access(filename, F_OK))
458 ret = true; 722 ret = true;
@@ -471,7 +735,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
471 if (filename == NULL || linkname == NULL) 735 if (filename == NULL || linkname == NULL)
472 goto out_free; 736 goto out_free;
473 737
474 if (!build_id__filename(sbuild_id, linkname, size)) 738 if (!build_id_cache__linkname(sbuild_id, linkname, size))
475 goto out_free; 739 goto out_free;
476 740
477 if (access(linkname, F_OK)) 741 if (access(linkname, F_OK))
@@ -489,7 +753,7 @@ int build_id_cache__remove_s(const char *sbuild_id)
489 tmp = strrchr(linkname, '/') + 1; 753 tmp = strrchr(linkname, '/') + 1;
490 snprintf(tmp, size - (tmp - linkname), "%s", filename); 754 snprintf(tmp, size - (tmp - linkname), "%s", filename);
491 755
492 if (unlink(linkname)) 756 if (rm_rf(linkname))
493 goto out_free; 757 goto out_free;
494 758
495 err = 0; 759 err = 0;
@@ -501,7 +765,7 @@ out_free:
501 765
502static int dso__cache_build_id(struct dso *dso, struct machine *machine) 766static int dso__cache_build_id(struct dso *dso, struct machine *machine)
503{ 767{
504 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 768 bool is_kallsyms = dso__is_kallsyms(dso);
505 bool is_vdso = dso__is_vdso(dso); 769 bool is_vdso = dso__is_vdso(dso);
506 const char *name = dso->long_name; 770 const char *name = dso->long_name;
507 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 0d814bb74661..512c0c83fbc6 100644
--- a/tools/perf/util/cache.h
+++ b/tools/perf/util/cache.h
@@ -1,40 +1,20 @@
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
@@ -45,9 +25,6 @@ static inline int is_absolute_path(const char *path)
45 return path[0] == '/'; 25 return path[0] == '/';
46} 26}
47 27
48char *strip_path_suffix(const char *path, const char *suffix);
49
50char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); 28char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
51char *perf_path(const char *fmt, ...) __attribute__((format (printf, 1, 2)));
52 29
53#endif /* __PERF_CACHE_H */ 30#endif /* __PERF_CACHE_H */
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h
index 65e2a4f7cb4e..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;
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 dad7d8272168..18dae745034f 100644
--- a/tools/perf/util/config.c
+++ b/tools/perf/util/config.c
@@ -26,6 +26,7 @@ static FILE *config_file;
26static const char *config_file_name; 26static const char *config_file_name;
27static int config_linenr; 27static int config_linenr;
28static int config_file_eof; 28static int config_file_eof;
29static struct perf_config_set *config_set;
29 30
30const char *config_exclusive_filename; 31const char *config_exclusive_filename;
31 32
@@ -275,7 +276,8 @@ static int perf_parse_file(config_fn_t fn, void *data)
275 break; 276 break;
276 } 277 }
277 } 278 }
278 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;
279} 281}
280 282
281static int parse_unit_factor(const char *end, unsigned long *val) 283static int parse_unit_factor(const char *end, unsigned long *val)
@@ -371,7 +373,7 @@ int perf_config_bool(const char *name, const char *value)
371 return !!perf_config_bool_or_int(name, value, &discard); 373 return !!perf_config_bool_or_int(name, value, &discard);
372} 374}
373 375
374const char *perf_config_dirname(const char *name, const char *value) 376static const char *perf_config_dirname(const char *name, const char *value)
375{ 377{
376 if (!name) 378 if (!name)
377 return NULL; 379 return NULL;
@@ -477,54 +479,6 @@ static int perf_config_global(void)
477 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0); 479 return !perf_env_bool("PERF_CONFIG_NOGLOBAL", 0);
478} 480}
479 481
480int perf_config(config_fn_t fn, void *data)
481{
482 int ret = 0, found = 0;
483 const char *home = NULL;
484
485 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
486 if (config_exclusive_filename)
487 return perf_config_from_file(fn, config_exclusive_filename, data);
488 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) {
489 ret += perf_config_from_file(fn, perf_etc_perfconfig(),
490 data);
491 found += 1;
492 }
493
494 home = getenv("HOME");
495 if (perf_config_global() && home) {
496 char *user_config = strdup(mkpath("%s/.perfconfig", home));
497 struct stat st;
498
499 if (user_config == NULL) {
500 warning("Not enough memory to process %s/.perfconfig, "
501 "ignoring it.", home);
502 goto out;
503 }
504
505 if (stat(user_config, &st) < 0)
506 goto out_free;
507
508 if (st.st_uid && (st.st_uid != geteuid())) {
509 warning("File %s not owned by current user or root, "
510 "ignoring it.", user_config);
511 goto out_free;
512 }
513
514 if (!st.st_size)
515 goto out_free;
516
517 ret += perf_config_from_file(fn, user_config, data);
518 found += 1;
519out_free:
520 free(user_config);
521 }
522out:
523 if (found == 0)
524 return -1;
525 return ret;
526}
527
528static struct perf_config_section *find_section(struct list_head *sections, 482static struct perf_config_section *find_section(struct list_head *sections,
529 const char *section_name) 483 const char *section_name)
530{ 484{
@@ -609,8 +563,12 @@ static int collect_config(const char *var, const char *value,
609 struct perf_config_section *section = NULL; 563 struct perf_config_section *section = NULL;
610 struct perf_config_item *item = NULL; 564 struct perf_config_item *item = NULL;
611 struct perf_config_set *set = perf_config_set; 565 struct perf_config_set *set = perf_config_set;
612 struct list_head *sections = &set->sections; 566 struct list_head *sections;
567
568 if (set == NULL)
569 return -1;
613 570
571 sections = &set->sections;
614 key = ptr = strdup(var); 572 key = ptr = strdup(var);
615 if (!key) { 573 if (!key) {
616 pr_debug("%s: strdup failed\n", __func__); 574 pr_debug("%s: strdup failed\n", __func__);
@@ -641,22 +599,115 @@ static int collect_config(const char *var, const char *value,
641 599
642out_free: 600out_free:
643 free(key); 601 free(key);
644 perf_config_set__delete(set);
645 return -1; 602 return -1;
646} 603}
647 604
605static int perf_config_set__init(struct perf_config_set *set)
606{
607 int ret = -1;
608 const char *home = NULL;
609
610 /* Setting $PERF_CONFIG makes perf read _only_ the given config file. */
611 if (config_exclusive_filename)
612 return perf_config_from_file(collect_config, config_exclusive_filename, set);
613 if (perf_config_system() && !access(perf_etc_perfconfig(), R_OK)) {
614 if (perf_config_from_file(collect_config, perf_etc_perfconfig(), set) < 0)
615 goto out;
616 }
617
618 home = getenv("HOME");
619 if (perf_config_global() && home) {
620 char *user_config = strdup(mkpath("%s/.perfconfig", home));
621 struct stat st;
622
623 if (user_config == NULL) {
624 warning("Not enough memory to process %s/.perfconfig, "
625 "ignoring it.", home);
626 goto out;
627 }
628
629 if (stat(user_config, &st) < 0)
630 goto out_free;
631
632 if (st.st_uid && (st.st_uid != geteuid())) {
633 warning("File %s not owned by current user or root, "
634 "ignoring it.", user_config);
635 goto out_free;
636 }
637
638 if (!st.st_size)
639 goto out_free;
640
641 ret = perf_config_from_file(collect_config, user_config, set);
642
643out_free:
644 free(user_config);
645 }
646out:
647 return ret;
648}
649
648struct perf_config_set *perf_config_set__new(void) 650struct perf_config_set *perf_config_set__new(void)
649{ 651{
650 struct perf_config_set *set = zalloc(sizeof(*set)); 652 struct perf_config_set *set = zalloc(sizeof(*set));
651 653
652 if (set) { 654 if (set) {
653 INIT_LIST_HEAD(&set->sections); 655 INIT_LIST_HEAD(&set->sections);
654 perf_config(collect_config, set); 656 if (perf_config_set__init(set) < 0) {
657 perf_config_set__delete(set);
658 set = NULL;
659 }
655 } 660 }
656 661
657 return set; 662 return set;
658} 663}
659 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)
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
690 return ret;
691}
692
693void perf_config__init(void)
694{
695 if (config_set == NULL)
696 config_set = perf_config_set__new();
697}
698
699void perf_config__exit(void)
700{
701 perf_config_set__delete(config_set);
702 config_set = NULL;
703}
704
705void perf_config__refresh(void)
706{
707 perf_config__exit();
708 perf_config__init();
709}
710
660static void perf_config_item__delete(struct perf_config_item *item) 711static void perf_config_item__delete(struct perf_config_item *item)
661{ 712{
662 zfree(&item->name); 713 zfree(&item->name);
@@ -693,6 +744,9 @@ static void perf_config_set__purge(struct perf_config_set *set)
693 744
694void perf_config_set__delete(struct perf_config_set *set) 745void perf_config_set__delete(struct perf_config_set *set)
695{ 746{
747 if (set == NULL)
748 return;
749
696 perf_config_set__purge(set); 750 perf_config_set__purge(set);
697 free(set); 751 free(set);
698} 752}
diff --git a/tools/perf/util/config.h b/tools/perf/util/config.h
index 22ec626ac718..6f813d46045e 100644
--- a/tools/perf/util/config.h
+++ b/tools/perf/util/config.h
@@ -20,7 +20,47 @@ struct perf_config_set {
20 struct list_head sections; 20 struct list_head sections;
21}; 21};
22 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
23struct perf_config_set *perf_config_set__new(void); 34struct perf_config_set *perf_config_set__new(void);
24void perf_config_set__delete(struct perf_config_set *set); 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)
25 65
26#endif /* __PERF_CONFIG_H */ 66#endif /* __PERF_CONFIG_H */
diff --git a/tools/perf/util/cpumap.c b/tools/perf/util/cpumap.c
index 02d801670f30..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)
@@ -590,12 +589,65 @@ int cpu__setup_cpunode_map(void)
590 589
591bool cpu_map__has(struct cpu_map *cpus, int cpu) 590bool cpu_map__has(struct cpu_map *cpus, int cpu)
592{ 591{
592 return cpu_map__idx(cpus, cpu) != -1;
593}
594
595int cpu_map__idx(struct cpu_map *cpus, int cpu)
596{
593 int i; 597 int i;
594 598
595 for (i = 0; i < cpus->nr; ++i) { 599 for (i = 0; i < cpus->nr; ++i) {
596 if (cpus->map[i] == cpu) 600 if (cpus->map[i] == cpu)
597 return true; 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 }
598 } 647 }
599 648
600 return false; 649#undef COMMA
650
651 pr_debug("cpumask list: %s\n", buf);
652 return ret;
601} 653}
diff --git a/tools/perf/util/cpumap.h b/tools/perf/util/cpumap.h
index 1a0a35073ce1..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);
@@ -67,5 +68,7 @@ int 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);
69 70
71int cpu_map__cpu(struct cpu_map *cpus, int idx);
70bool cpu_map__has(struct cpu_map *cpus, int cpu); 72bool cpu_map__has(struct cpu_map *cpus, int cpu);
73int cpu_map__idx(struct cpu_map *cpus, int cpu);
71#endif /* __PERF_CPUMAP_H */ 74#endif /* __PERF_CPUMAP_H */
diff --git a/tools/perf/util/cs-etm.h b/tools/perf/util/cs-etm.h
new file mode 100644
index 000000000000..3cc6bc3263fe
--- /dev/null
+++ b/tools/perf/util/cs-etm.h
@@ -0,0 +1,74 @@
1/*
2 * Copyright(C) 2015 Linaro Limited. All rights reserved.
3 * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 as published by
7 * the Free Software Foundation.
8 *
9 * This program is distributed in the hope that 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 * You should have received a copy of the GNU General Public License along with
15 * this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifndef INCLUDE__UTIL_PERF_CS_ETM_H__
19#define INCLUDE__UTIL_PERF_CS_ETM_H__
20
21/* Versionning header in case things need tro change in the future. That way
22 * decoding of old snapshot is still possible.
23 */
24enum {
25 /* Starting with 0x0 */
26 CS_HEADER_VERSION_0,
27 /* PMU->type (32 bit), total # of CPUs (32 bit) */
28 CS_PMU_TYPE_CPUS,
29 CS_ETM_SNAPSHOT,
30 CS_HEADER_VERSION_0_MAX,
31};
32
33/* Beginning of header common to both ETMv3 and V4 */
34enum {
35 CS_ETM_MAGIC,
36 CS_ETM_CPU,
37};
38
39/* ETMv3/PTM metadata */
40enum {
41 /* Dynamic, configurable parameters */
42 CS_ETM_ETMCR = CS_ETM_CPU + 1,
43 CS_ETM_ETMTRACEIDR,
44 /* RO, taken from sysFS */
45 CS_ETM_ETMCCER,
46 CS_ETM_ETMIDR,
47 CS_ETM_PRIV_MAX,
48};
49
50/* ETMv4 metadata */
51enum {
52 /* Dynamic, configurable parameters */
53 CS_ETMV4_TRCCONFIGR = CS_ETM_CPU + 1,
54 CS_ETMV4_TRCTRACEIDR,
55 /* RO, taken from sysFS */
56 CS_ETMV4_TRCIDR0,
57 CS_ETMV4_TRCIDR1,
58 CS_ETMV4_TRCIDR2,
59 CS_ETMV4_TRCIDR8,
60 CS_ETMV4_TRCAUTHSTATUS,
61 CS_ETMV4_PRIV_MAX,
62};
63
64#define KiB(x) ((x) * 1024)
65#define MiB(x) ((x) * 1024 * 1024)
66
67#define CS_ETM_HEADER_SIZE (CS_HEADER_VERSION_0_MAX * sizeof(u64))
68
69static const u64 __perf_cs_etmv3_magic = 0x3030303030303030ULL;
70static const u64 __perf_cs_etmv4_magic = 0x4040404040404040ULL;
71#define CS_ETMV3_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64))
72#define CS_ETMV4_PRIV_SIZE (CS_ETMV4_PRIV_MAX * sizeof(u64))
73
74#endif
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index bbf69d248ec5..7123f4de32cc 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
@@ -365,7 +437,7 @@ add_bpf_output_values(struct bt_ctf_event_class *event_class,
365 int ret; 437 int ret;
366 438
367 if (nr_elements * sizeof(u32) != raw_size) 439 if (nr_elements * sizeof(u32) != raw_size)
368 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %lu bytes\n", 440 pr_warning("Incorrect raw_size (%u) in bpf output event, skip %zu bytes\n",
369 raw_size, nr_elements * sizeof(u32) - raw_size); 441 raw_size, nr_elements * sizeof(u32) - raw_size);
370 442
371 len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len"); 443 len_type = bt_ctf_event_class_get_field_by_name(event_class, "raw_len");
@@ -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 be83516155ee..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}
diff --git a/tools/perf/util/db-export.c b/tools/perf/util/db-export.c
index c9a6dc173e74..b0c2b5c5d337 100644
--- a/tools/perf/util/db-export.c
+++ b/tools/perf/util/db-export.c
@@ -233,17 +233,6 @@ int db_export__symbol(struct db_export *dbe, struct symbol *sym,
233 return 0; 233 return 0;
234} 234}
235 235
236static struct thread *get_main_thread(struct machine *machine, struct thread *thread)
237{
238 if (thread->pid_ == thread->tid)
239 return thread__get(thread);
240
241 if (thread->pid_ == -1)
242 return NULL;
243
244 return machine__find_thread(machine, thread->pid_, thread->pid_);
245}
246
247static 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,
248 u64 *dso_db_id, u64 *sym_db_id, u64 *offset) 237 u64 *dso_db_id, u64 *sym_db_id, u64 *offset)
249{ 238{
@@ -382,7 +371,7 @@ int db_export__sample(struct db_export *dbe, union perf_event *event,
382 if (err) 371 if (err)
383 return err; 372 return err;
384 373
385 main_thread = get_main_thread(al->machine, thread); 374 main_thread = thread__main_thread(al->machine, thread);
386 if (main_thread) 375 if (main_thread)
387 comm = machine__thread_exec_comm(al->machine, main_thread); 376 comm = machine__thread_exec_comm(al->machine, main_thread);
388 377
diff --git a/tools/perf/util/debug.c b/tools/perf/util/debug.c
index 8c4212abd19b..c1838b643108 100644
--- a/tools/perf/util/debug.c
+++ b/tools/perf/util/debug.c
@@ -6,6 +6,7 @@
6#include <stdarg.h> 6#include <stdarg.h>
7#include <stdio.h> 7#include <stdio.h>
8#include <api/debug.h> 8#include <api/debug.h>
9#include <linux/time64.h>
9 10
10#include "cache.h" 11#include "cache.h"
11#include "color.h" 12#include "color.h"
@@ -14,9 +15,6 @@
14#include "util.h" 15#include "util.h"
15#include "target.h" 16#include "target.h"
16 17
17#define NSECS_PER_SEC 1000000000ULL
18#define NSECS_PER_USEC 1000ULL
19
20int verbose; 18int verbose;
21bool dump_trace = false, quiet = false; 19bool dump_trace = false, quiet = false;
22int debug_ordered_events; 20int debug_ordered_events;
@@ -54,9 +52,9 @@ static int veprintf_time(u64 t, const char *fmt, va_list args)
54 int ret = 0; 52 int ret = 0;
55 u64 secs, usecs, nsecs = t; 53 u64 secs, usecs, nsecs = t;
56 54
57 secs = nsecs / NSECS_PER_SEC; 55 secs = nsecs / NSEC_PER_SEC;
58 nsecs -= secs * NSECS_PER_SEC; 56 nsecs -= secs * NSEC_PER_SEC;
59 usecs = nsecs / NSECS_PER_USEC; 57 usecs = nsecs / NSEC_PER_USEC;
60 58
61 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ", 59 ret = fprintf(stderr, "[%13" PRIu64 ".%06" PRIu64 "] ",
62 secs, usecs); 60 secs, usecs);
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/drv_configs.c b/tools/perf/util/drv_configs.c
new file mode 100644
index 000000000000..1647f285c629
--- /dev/null
+++ b/tools/perf/util/drv_configs.c
@@ -0,0 +1,77 @@
1/*
2 * drv_configs.h: Interface to apply PMU specific configuration
3 * Copyright (c) 2016-2018, Linaro Ltd.
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 "drv_configs.h"
17#include "evlist.h"
18#include "evsel.h"
19#include "pmu.h"
20
21static int
22perf_evsel__apply_drv_configs(struct perf_evsel *evsel,
23 struct perf_evsel_config_term **err_term)
24{
25 bool found = false;
26 int err = 0;
27 struct perf_evsel_config_term *term;
28 struct perf_pmu *pmu = NULL;
29
30 while ((pmu = perf_pmu__scan(pmu)) != NULL)
31 if (pmu->type == evsel->attr.type) {
32 found = true;
33 break;
34 }
35
36 list_for_each_entry(term, &evsel->config_terms, list) {
37 if (term->type != PERF_EVSEL__CONFIG_TERM_DRV_CFG)
38 continue;
39
40 /*
41 * We have a configuration term, report an error if we
42 * can't find the PMU or if the PMU driver doesn't support
43 * cmd line driver configuration.
44 */
45 if (!found || !pmu->set_drv_config) {
46 err = -EINVAL;
47 *err_term = term;
48 break;
49 }
50
51 err = pmu->set_drv_config(term);
52 if (err) {
53 *err_term = term;
54 break;
55 }
56 }
57
58 return err;
59}
60
61int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
62 struct perf_evsel **err_evsel,
63 struct perf_evsel_config_term **err_term)
64{
65 struct perf_evsel *evsel;
66 int err = 0;
67
68 evlist__for_each_entry(evlist, evsel) {
69 err = perf_evsel__apply_drv_configs(evsel, err_term);
70 if (err) {
71 *err_evsel = evsel;
72 break;
73 }
74 }
75
76 return err;
77}
diff --git a/tools/perf/util/drv_configs.h b/tools/perf/util/drv_configs.h
new file mode 100644
index 000000000000..32bc9babc2e0
--- /dev/null
+++ b/tools/perf/util/drv_configs.h
@@ -0,0 +1,26 @@
1/*
2 * drv_configs.h: Interface to apply PMU specific configuration
3 * Copyright (c) 2016-2018, Linaro Ltd.
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_DRV_CONFIGS_H
17#define __PERF_DRV_CONFIGS_H
18
19#include "drv_configs.h"
20#include "evlist.h"
21#include "evsel.h"
22
23int perf_evlist__apply_drv_configs(struct perf_evlist *evlist,
24 struct perf_evsel **err_evsel,
25 struct perf_evsel_config_term **term);
26#endif
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index 5d286f5d7906..d2c6cdd9d42b 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -335,7 +335,7 @@ static int do_open(char *name)
335 return fd; 335 return fd;
336 336
337 pr_debug("dso open failed: %s\n", 337 pr_debug("dso open failed: %s\n",
338 strerror_r(errno, sbuf, sizeof(sbuf))); 338 str_error_r(errno, sbuf, sizeof(sbuf)));
339 if (!dso__data_open_cnt || errno != EMFILE) 339 if (!dso__data_open_cnt || errno != EMFILE)
340 break; 340 break;
341 341
@@ -363,6 +363,9 @@ static int __open_dso(struct dso *dso, struct machine *machine)
363 return -EINVAL; 363 return -EINVAL;
364 } 364 }
365 365
366 if (!is_regular_file(name))
367 return -EINVAL;
368
366 fd = do_open(name); 369 fd = do_open(name);
367 free(name); 370 free(name);
368 return fd; 371 return fd;
@@ -442,17 +445,27 @@ static rlim_t get_fd_limit(void)
442 return limit; 445 return limit;
443} 446}
444 447
445static bool may_cache_fd(void) 448static rlim_t fd_limit;
449
450/*
451 * Used only by tests/dso-data.c to reset the environment
452 * for tests. I dont expect we should change this during
453 * standard runtime.
454 */
455void reset_fd_limit(void)
446{ 456{
447 static rlim_t limit; 457 fd_limit = 0;
458}
448 459
449 if (!limit) 460static bool may_cache_fd(void)
450 limit = get_fd_limit(); 461{
462 if (!fd_limit)
463 fd_limit = get_fd_limit();
451 464
452 if (limit == RLIM_INFINITY) 465 if (fd_limit == RLIM_INFINITY)
453 return true; 466 return true;
454 467
455 return limit > (rlim_t) dso__data_open_cnt; 468 return fd_limit > (rlim_t) dso__data_open_cnt;
456} 469}
457 470
458/* 471/*
@@ -776,7 +789,7 @@ static int data_file_size(struct dso *dso, struct machine *machine)
776 if (fstat(dso->data.fd, &st) < 0) { 789 if (fstat(dso->data.fd, &st) < 0) {
777 ret = -errno; 790 ret = -errno;
778 pr_err("dso cache fstat failed: %s\n", 791 pr_err("dso cache fstat failed: %s\n",
779 strerror_r(errno, sbuf, sizeof(sbuf))); 792 str_error_r(errno, sbuf, sizeof(sbuf)));
780 dso->data.status = DSO_DATA_STATUS_ERROR; 793 dso->data.status = DSO_DATA_STATUS_ERROR;
781 goto out; 794 goto out;
782 } 795 }
@@ -1356,7 +1369,7 @@ int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
1356 BUG_ON(buflen == 0); 1369 BUG_ON(buflen == 0);
1357 1370
1358 if (errnum >= 0) { 1371 if (errnum >= 0) {
1359 const char *err = strerror_r(errnum, buf, buflen); 1372 const char *err = str_error_r(errnum, buf, buflen);
1360 1373
1361 if (err != buf) 1374 if (err != buf)
1362 scnprintf(buf, buflen, "%s", err); 1375 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 a347b19c961a..41e068e94349 100644
--- a/tools/perf/util/dwarf-aux.c
+++ b/tools/perf/util/dwarf-aux.c
@@ -130,6 +130,22 @@ int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
130} 130}
131 131
132/** 132/**
133 * die_get_linkage_name - Get the linkage name of the object
134 * @dw_die: A DIE of the object
135 *
136 * Get the linkage name attiribute of given @dw_die.
137 * For C++ binary, the linkage name will be the mangled symbol.
138 */
139const char *die_get_linkage_name(Dwarf_Die *dw_die)
140{
141 Dwarf_Attribute attr;
142
143 if (dwarf_attr_integrate(dw_die, DW_AT_linkage_name, &attr) == NULL)
144 return NULL;
145 return dwarf_formstring(&attr);
146}
147
148/**
133 * die_compare_name - Compare diename and tname 149 * die_compare_name - Compare diename and tname
134 * @dw_die: a DIE 150 * @dw_die: a DIE
135 * @tname: a string of target name 151 * @tname: a string of target name
@@ -145,18 +161,26 @@ bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
145} 161}
146 162
147/** 163/**
148 * die_match_name - Match diename and glob 164 * die_match_name - Match diename/linkage name and glob
149 * @dw_die: a DIE 165 * @dw_die: a DIE
150 * @glob: a string of target glob pattern 166 * @glob: a string of target glob pattern
151 * 167 *
152 * Glob matching the name of @dw_die and @glob. Return false if matching fail. 168 * Glob matching the name of @dw_die and @glob. Return false if matching fail.
169 * This also match linkage name.
153 */ 170 */
154bool die_match_name(Dwarf_Die *dw_die, const char *glob) 171bool die_match_name(Dwarf_Die *dw_die, const char *glob)
155{ 172{
156 const char *name; 173 const char *name;
157 174
158 name = dwarf_diename(dw_die); 175 name = dwarf_diename(dw_die);
159 return name ? strglobmatch(name, glob) : false; 176 if (name && strglobmatch(name, glob))
177 return true;
178 /* fall back to check linkage name */
179 name = die_get_linkage_name(dw_die);
180 if (name && strglobmatch(name, glob))
181 return true;
182
183 return false;
160} 184}
161 185
162/** 186/**
@@ -1085,3 +1109,182 @@ int die_get_var_range(Dwarf_Die *sp_die __maybe_unused,
1085 return -ENOTSUP; 1109 return -ENOTSUP;
1086} 1110}
1087#endif 1111#endif
1112
1113/*
1114 * die_has_loclist - Check if DW_AT_location of @vr_die is a location list
1115 * @vr_die: a variable DIE
1116 */
1117static bool die_has_loclist(Dwarf_Die *vr_die)
1118{
1119 Dwarf_Attribute loc;
1120 int tag = dwarf_tag(vr_die);
1121
1122 if (tag != DW_TAG_formal_parameter &&
1123 tag != DW_TAG_variable)
1124 return false;
1125
1126 return (dwarf_attr_integrate(vr_die, DW_AT_location, &loc) &&
1127 dwarf_whatform(&loc) == DW_FORM_sec_offset);
1128}
1129
1130/*
1131 * die_is_optimized_target - Check if target program is compiled with
1132 * optimization
1133 * @cu_die: a CU DIE
1134 *
1135 * For any object in given CU whose DW_AT_location is a location list,
1136 * target program is compiled with optimization. This is applicable to
1137 * clang as well.
1138 */
1139bool die_is_optimized_target(Dwarf_Die *cu_die)
1140{
1141 Dwarf_Die tmp_die;
1142
1143 if (die_has_loclist(cu_die))
1144 return true;
1145
1146 if (!dwarf_child(cu_die, &tmp_die) &&
1147 die_is_optimized_target(&tmp_die))
1148 return true;
1149
1150 if (!dwarf_siblingof(cu_die, &tmp_die) &&
1151 die_is_optimized_target(&tmp_die))
1152 return true;
1153
1154 return false;
1155}
1156
1157/*
1158 * die_search_idx - Search index of given line address
1159 * @lines: Line records of single CU
1160 * @nr_lines: Number of @lines
1161 * @addr: address we are looking for
1162 * @idx: index to be set by this function (return value)
1163 *
1164 * Search for @addr by looping over every lines of CU. If address
1165 * matches, set index of that line in @idx. Note that single source
1166 * line can have multiple line records. i.e. single source line can
1167 * have multiple index.
1168 */
1169static bool die_search_idx(Dwarf_Lines *lines, unsigned long nr_lines,
1170 Dwarf_Addr addr, unsigned long *idx)
1171{
1172 unsigned long i;
1173 Dwarf_Addr tmp;
1174
1175 for (i = 0; i < nr_lines; i++) {
1176 if (dwarf_lineaddr(dwarf_onesrcline(lines, i), &tmp))
1177 return false;
1178
1179 if (tmp == addr) {
1180 *idx = i;
1181 return true;
1182 }
1183 }
1184 return false;
1185}
1186
1187/*
1188 * die_get_postprologue_addr - Search next address after function prologue
1189 * @entrypc_idx: entrypc index
1190 * @lines: Line records of single CU
1191 * @nr_lines: Number of @lines
1192 * @hignpc: high PC address of function
1193 * @postprologue_addr: Next address after function prologue (return value)
1194 *
1195 * Look for prologue-end marker. If there is no explicit marker, return
1196 * address of next line record or next source line.
1197 */
1198static bool die_get_postprologue_addr(unsigned long entrypc_idx,
1199 Dwarf_Lines *lines,
1200 unsigned long nr_lines,
1201 Dwarf_Addr highpc,
1202 Dwarf_Addr *postprologue_addr)
1203{
1204 unsigned long i;
1205 int entrypc_lno, lno;
1206 Dwarf_Line *line;
1207 Dwarf_Addr addr;
1208 bool p_end;
1209
1210 /* entrypc_lno is actual source line number */
1211 line = dwarf_onesrcline(lines, entrypc_idx);
1212 if (dwarf_lineno(line, &entrypc_lno))
1213 return false;
1214
1215 for (i = entrypc_idx; i < nr_lines; i++) {
1216 line = dwarf_onesrcline(lines, i);
1217
1218 if (dwarf_lineaddr(line, &addr) ||
1219 dwarf_lineno(line, &lno) ||
1220 dwarf_lineprologueend(line, &p_end))
1221 return false;
1222
1223 /* highpc is exclusive. [entrypc,highpc) */
1224 if (addr >= highpc)
1225 break;
1226
1227 /* clang supports prologue-end marker */
1228 if (p_end)
1229 break;
1230
1231 /* Actual next line in source */
1232 if (lno != entrypc_lno)
1233 break;
1234
1235 /*
1236 * Single source line can have multiple line records.
1237 * For Example,
1238 * void foo() { printf("hello\n"); }
1239 * contains two line records. One points to declaration and
1240 * other points to printf() line. Variable 'lno' won't get
1241 * incremented in this case but 'i' will.
1242 */
1243 if (i != entrypc_idx)
1244 break;
1245 }
1246
1247 dwarf_lineaddr(line, postprologue_addr);
1248 if (*postprologue_addr >= highpc)
1249 dwarf_lineaddr(dwarf_onesrcline(lines, i - 1),
1250 postprologue_addr);
1251
1252 return true;
1253}
1254
1255/*
1256 * die_skip_prologue - Use next address after prologue as probe location
1257 * @sp_die: a subprogram DIE
1258 * @cu_die: a CU DIE
1259 * @entrypc: entrypc of the function
1260 *
1261 * Function prologue prepares stack and registers before executing function
1262 * logic. When target program is compiled without optimization, function
1263 * parameter information is only valid after prologue. When we probe entrypc
1264 * of the function, and try to record function parameter, it contains
1265 * garbage value.
1266 */
1267void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
1268 Dwarf_Addr *entrypc)
1269{
1270 size_t nr_lines = 0;
1271 unsigned long entrypc_idx = 0;
1272 Dwarf_Lines *lines = NULL;
1273 Dwarf_Addr postprologue_addr;
1274 Dwarf_Addr highpc;
1275
1276 if (dwarf_highpc(sp_die, &highpc))
1277 return;
1278
1279 if (dwarf_getsrclines(cu_die, &lines, &nr_lines))
1280 return;
1281
1282 if (!die_search_idx(lines, nr_lines, *entrypc, &entrypc_idx))
1283 return;
1284
1285 if (!die_get_postprologue_addr(entrypc_idx, lines, nr_lines,
1286 highpc, &postprologue_addr))
1287 return;
1288
1289 *entrypc = postprologue_addr;
1290}
diff --git a/tools/perf/util/dwarf-aux.h b/tools/perf/util/dwarf-aux.h
index dc0ce1adb075..8ac53bf1ec4e 100644
--- a/tools/perf/util/dwarf-aux.h
+++ b/tools/perf/util/dwarf-aux.h
@@ -38,6 +38,9 @@ int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
38int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr, 38int cu_walk_functions_at(Dwarf_Die *cu_die, Dwarf_Addr addr,
39 int (*callback)(Dwarf_Die *, void *), void *data); 39 int (*callback)(Dwarf_Die *, void *), void *data);
40 40
41/* Get DW_AT_linkage_name (should be NULL for C binary) */
42const char *die_get_linkage_name(Dwarf_Die *dw_die);
43
41/* Ensure that this DIE is a subprogram and definition (not declaration) */ 44/* Ensure that this DIE is a subprogram and definition (not declaration) */
42bool die_is_func_def(Dwarf_Die *dw_die); 45bool die_is_func_def(Dwarf_Die *dw_die);
43 46
@@ -125,4 +128,12 @@ int die_get_typename(Dwarf_Die *vr_die, struct strbuf *buf);
125/* Get the name and type of given variable DIE, stored as "type\tname" */ 128/* Get the name and type of given variable DIE, stored as "type\tname" */
126int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf); 129int die_get_varname(Dwarf_Die *vr_die, struct strbuf *buf);
127int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf); 130int die_get_var_range(Dwarf_Die *sp_die, Dwarf_Die *vr_die, struct strbuf *buf);
131
132/* Check if target program is compiled with optimization */
133bool die_is_optimized_target(Dwarf_Die *cu_die);
134
135/* Use next address after prologue as probe location */
136void die_skip_prologue(Dwarf_Die *sp_die, Dwarf_Die *cu_die,
137 Dwarf_Addr *entrypc);
138
128#endif 139#endif
diff --git a/tools/perf/util/dwarf-regs.c b/tools/perf/util/dwarf-regs.c
new file mode 100644
index 000000000000..62bc4a86a970
--- /dev/null
+++ b/tools/perf/util/dwarf-regs.c
@@ -0,0 +1,59 @@
1/*
2 * dwarf-regs.c : Mapping of DWARF debug register numbers into register names.
3 *
4 * Written by: Masami Hiramatsu <mhiramat@kernel.org>
5 */
6
7#include <util.h>
8#include <debug.h>
9#include <dwarf-regs.h>
10#include <elf.h>
11
12#ifndef EM_AARCH64
13#define EM_AARCH64 183 /* ARM 64 bit */
14#endif
15
16/* Define const char * {arch}_register_tbl[] */
17#define DEFINE_DWARF_REGSTR_TABLE
18#include "../arch/x86/include/dwarf-regs-table.h"
19#include "../arch/arm/include/dwarf-regs-table.h"
20#include "../arch/arm64/include/dwarf-regs-table.h"
21#include "../arch/sh/include/dwarf-regs-table.h"
22#include "../arch/powerpc/include/dwarf-regs-table.h"
23#include "../arch/s390/include/dwarf-regs-table.h"
24#include "../arch/sparc/include/dwarf-regs-table.h"
25#include "../arch/xtensa/include/dwarf-regs-table.h"
26
27#define __get_dwarf_regstr(tbl, n) (((n) < ARRAY_SIZE(tbl)) ? (tbl)[(n)] : NULL)
28
29/* Return architecture dependent register string (for kprobe-tracer) */
30const char *get_dwarf_regstr(unsigned int n, unsigned int machine)
31{
32 switch (machine) {
33 case EM_NONE: /* Generic arch - use host arch */
34 return get_arch_regstr(n);
35 case EM_386:
36 return __get_dwarf_regstr(x86_32_regstr_tbl, n);
37 case EM_X86_64:
38 return __get_dwarf_regstr(x86_64_regstr_tbl, n);
39 case EM_ARM:
40 return __get_dwarf_regstr(arm_regstr_tbl, n);
41 case EM_AARCH64:
42 return __get_dwarf_regstr(aarch64_regstr_tbl, n);
43 case EM_SH:
44 return __get_dwarf_regstr(sh_regstr_tbl, n);
45 case EM_S390:
46 return __get_dwarf_regstr(s390_regstr_tbl, n);
47 case EM_PPC:
48 case EM_PPC64:
49 return __get_dwarf_regstr(powerpc_regstr_tbl, n);
50 case EM_SPARC:
51 case EM_SPARCV9:
52 return __get_dwarf_regstr(sparc_regstr_tbl, n);
53 case EM_XTENSA:
54 return __get_dwarf_regstr(xtensa_regstr_tbl, n);
55 default:
56 pr_err("ELF MACHINE %x is not supported.\n", machine);
57 }
58 return NULL;
59}
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 f6fcc6832949..8ab0d7da956b 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -1,5 +1,6 @@
1#include <linux/types.h> 1#include <linux/types.h>
2#include <sys/mman.h> 2#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
3#include <api/fs/fs.h>
3#include "event.h" 4#include "event.h"
4#include "debug.h" 5#include "debug.h"
5#include "hist.h" 6#include "hist.h"
@@ -248,6 +249,8 @@ int perf_event__synthesize_mmap_events(struct perf_tool *tool,
248 bool truncation = false; 249 bool truncation = false;
249 unsigned long long timeout = proc_map_timeout * 1000000ULL; 250 unsigned long long timeout = proc_map_timeout * 1000000ULL;
250 int rc = 0; 251 int rc = 0;
252 const char *hugetlbfs_mnt = hugetlbfs__mountpoint();
253 int hugetlbfs_mnt_len = hugetlbfs_mnt ? strlen(hugetlbfs_mnt) : 0;
251 254
252 if (machine__is_default_guest(machine)) 255 if (machine__is_default_guest(machine))
253 return 0; 256 return 0;
@@ -343,6 +346,12 @@ out:
343 if (!strcmp(execname, "")) 346 if (!strcmp(execname, ""))
344 strcpy(execname, anonstr); 347 strcpy(execname, anonstr);
345 348
349 if (hugetlbfs_mnt_len &&
350 !strncmp(execname, hugetlbfs_mnt, hugetlbfs_mnt_len)) {
351 strcpy(execname, anonstr);
352 event->mmap2.flags |= MAP_HUGETLB;
353 }
354
346 size = strlen(execname) + 1; 355 size = strlen(execname) + 1;
347 memcpy(event->mmap2.filename, execname, size); 356 memcpy(event->mmap2.filename, execname, size);
348 size = PERF_ALIGN(size, sizeof(u64)); 357 size = PERF_ALIGN(size, sizeof(u64));
@@ -673,6 +682,8 @@ int perf_event__synthesize_kernel_mmap(struct perf_tool *tool,
673 int err; 682 int err;
674 union perf_event *event; 683 union perf_event *event;
675 684
685 if (symbol_conf.kptr_restrict)
686 return -1;
676 if (map == NULL) 687 if (map == NULL)
677 return -1; 688 return -1;
678 689
@@ -1090,7 +1101,7 @@ size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
1090 struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data); 1101 struct cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
1091 size_t ret; 1102 size_t ret;
1092 1103
1093 ret = fprintf(fp, " nr: "); 1104 ret = fprintf(fp, ": ");
1094 1105
1095 if (cpus) 1106 if (cpus)
1096 ret += cpu_map__fprintf(cpus, fp); 1107 ret += cpu_map__fprintf(cpus, fp);
@@ -1284,7 +1295,7 @@ try_again:
1284 * must be done prior to using kernel maps. 1295 * must be done prior to using kernel maps.
1285 */ 1296 */
1286 if (load_map) 1297 if (load_map)
1287 map__load(al->map, machine->symbol_filter); 1298 map__load(al->map);
1288 al->addr = al->map->map_ip(al->map, al->addr); 1299 al->addr = al->map->map_ip(al->map, al->addr);
1289 } 1300 }
1290} 1301}
@@ -1295,8 +1306,7 @@ void thread__find_addr_location(struct thread *thread,
1295{ 1306{
1296 thread__find_addr_map(thread, cpumode, type, addr, al); 1307 thread__find_addr_map(thread, cpumode, type, addr, al);
1297 if (al->map != NULL) 1308 if (al->map != NULL)
1298 al->sym = map__find_symbol(al->map, al->addr, 1309 al->sym = map__find_symbol(al->map, al->addr);
1299 thread->mg->machine->symbol_filter);
1300 else 1310 else
1301 al->sym = NULL; 1311 al->sym = NULL;
1302} 1312}
@@ -1357,8 +1367,7 @@ int machine__resolve(struct machine *machine, struct addr_location *al,
1357 al->filtered |= (1 << HIST_FILTER__DSO); 1367 al->filtered |= (1 << HIST_FILTER__DSO);
1358 } 1368 }
1359 1369
1360 al->sym = map__find_symbol(al->map, al->addr, 1370 al->sym = map__find_symbol(al->map, al->addr);
1361 machine->symbol_filter);
1362 } 1371 }
1363 1372
1364 if (symbol_conf.sym_list && 1373 if (symbol_conf.sym_list &&
@@ -1414,5 +1423,5 @@ void thread__resolve(struct thread *thread, struct addr_location *al,
1414 al->sym = NULL; 1423 al->sym = NULL;
1415 1424
1416 if (al->map) 1425 if (al->map)
1417 al->sym = map__find_symbol(al->map, al->addr, NULL); 1426 al->sym = map__find_symbol(al->map, al->addr);
1418} 1427}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index e82ba90cc969..d92e02006fb8 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,7 +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;
47 evlist->backward = false; 48 evlist->bkw_mmap_state = BKW_MMAP_NOTREADY;
48} 49}
49 50
50struct perf_evlist *perf_evlist__new(void) 51struct perf_evlist *perf_evlist__new(void)
@@ -100,7 +101,7 @@ static void perf_evlist__update_id_pos(struct perf_evlist *evlist)
100{ 101{
101 struct perf_evsel *evsel; 102 struct perf_evsel *evsel;
102 103
103 evlist__for_each(evlist, evsel) 104 evlist__for_each_entry(evlist, evsel)
104 perf_evsel__calc_id_pos(evsel); 105 perf_evsel__calc_id_pos(evsel);
105 106
106 perf_evlist__set_id_pos(evlist); 107 perf_evlist__set_id_pos(evlist);
@@ -110,7 +111,7 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
110{ 111{
111 struct perf_evsel *pos, *n; 112 struct perf_evsel *pos, *n;
112 113
113 evlist__for_each_safe(evlist, n, pos) { 114 evlist__for_each_entry_safe(evlist, n, pos) {
114 list_del_init(&pos->node); 115 list_del_init(&pos->node);
115 pos->evlist = NULL; 116 pos->evlist = NULL;
116 perf_evsel__delete(pos); 117 perf_evsel__delete(pos);
@@ -122,11 +123,15 @@ static void perf_evlist__purge(struct perf_evlist *evlist)
122void perf_evlist__exit(struct perf_evlist *evlist) 123void perf_evlist__exit(struct perf_evlist *evlist)
123{ 124{
124 zfree(&evlist->mmap); 125 zfree(&evlist->mmap);
126 zfree(&evlist->backward_mmap);
125 fdarray__exit(&evlist->pollfd); 127 fdarray__exit(&evlist->pollfd);
126} 128}
127 129
128void perf_evlist__delete(struct perf_evlist *evlist) 130void perf_evlist__delete(struct perf_evlist *evlist)
129{ 131{
132 if (evlist == NULL)
133 return;
134
130 perf_evlist__munmap(evlist); 135 perf_evlist__munmap(evlist);
131 perf_evlist__close(evlist); 136 perf_evlist__close(evlist);
132 cpu_map__put(evlist->cpus); 137 cpu_map__put(evlist->cpus);
@@ -161,7 +166,7 @@ static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
161{ 166{
162 struct perf_evsel *evsel; 167 struct perf_evsel *evsel;
163 168
164 evlist__for_each(evlist, evsel) 169 evlist__for_each_entry(evlist, evsel)
165 __perf_evlist__propagate_maps(evlist, evsel); 170 __perf_evlist__propagate_maps(evlist, evsel);
166} 171}
167 172
@@ -190,7 +195,7 @@ void perf_evlist__splice_list_tail(struct perf_evlist *evlist,
190{ 195{
191 struct perf_evsel *evsel, *temp; 196 struct perf_evsel *evsel, *temp;
192 197
193 __evlist__for_each_safe(list, temp, evsel) { 198 __evlist__for_each_entry_safe(list, temp, evsel) {
194 list_del_init(&evsel->node); 199 list_del_init(&evsel->node);
195 perf_evlist__add(evlist, evsel); 200 perf_evlist__add(evlist, evsel);
196 } 201 }
@@ -205,7 +210,7 @@ void __perf_evlist__set_leader(struct list_head *list)
205 210
206 leader->nr_members = evsel->idx - leader->idx + 1; 211 leader->nr_members = evsel->idx - leader->idx + 1;
207 212
208 __evlist__for_each(list, evsel) { 213 __evlist__for_each_entry(list, evsel) {
209 evsel->leader = leader; 214 evsel->leader = leader;
210 } 215 }
211} 216}
@@ -234,31 +239,13 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr)
234 239
235int perf_evlist__add_default(struct perf_evlist *evlist) 240int perf_evlist__add_default(struct perf_evlist *evlist)
236{ 241{
237 struct perf_event_attr attr = { 242 struct perf_evsel *evsel = perf_evsel__new_cycles();
238 .type = PERF_TYPE_HARDWARE,
239 .config = PERF_COUNT_HW_CPU_CYCLES,
240 };
241 struct perf_evsel *evsel;
242
243 event_attr_init(&attr);
244 243
245 perf_event_attr__set_max_precise_ip(&attr);
246
247 evsel = perf_evsel__new(&attr);
248 if (evsel == NULL) 244 if (evsel == NULL)
249 goto error; 245 return -ENOMEM;
250
251 /* use asprintf() because free(evsel) assumes name is allocated */
252 if (asprintf(&evsel->name, "cycles%.*s",
253 attr.precise_ip ? attr.precise_ip + 1 : 0, ":ppp") < 0)
254 goto error_free;
255 246
256 perf_evlist__add(evlist, evsel); 247 perf_evlist__add(evlist, evsel);
257 return 0; 248 return 0;
258error_free:
259 perf_evsel__delete(evsel);
260error:
261 return -ENOMEM;
262} 249}
263 250
264int perf_evlist__add_dummy(struct perf_evlist *evlist) 251int perf_evlist__add_dummy(struct perf_evlist *evlist)
@@ -296,7 +283,7 @@ static int perf_evlist__add_attrs(struct perf_evlist *evlist,
296 return 0; 283 return 0;
297 284
298out_delete_partial_list: 285out_delete_partial_list:
299 __evlist__for_each_safe(&head, n, evsel) 286 __evlist__for_each_entry_safe(&head, n, evsel)
300 perf_evsel__delete(evsel); 287 perf_evsel__delete(evsel);
301 return -1; 288 return -1;
302} 289}
@@ -317,7 +304,7 @@ perf_evlist__find_tracepoint_by_id(struct perf_evlist *evlist, int id)
317{ 304{
318 struct perf_evsel *evsel; 305 struct perf_evsel *evsel;
319 306
320 evlist__for_each(evlist, evsel) { 307 evlist__for_each_entry(evlist, evsel) {
321 if (evsel->attr.type == PERF_TYPE_TRACEPOINT && 308 if (evsel->attr.type == PERF_TYPE_TRACEPOINT &&
322 (int)evsel->attr.config == id) 309 (int)evsel->attr.config == id)
323 return evsel; 310 return evsel;
@@ -332,7 +319,7 @@ perf_evlist__find_tracepoint_by_name(struct perf_evlist *evlist,
332{ 319{
333 struct perf_evsel *evsel; 320 struct perf_evsel *evsel;
334 321
335 evlist__for_each(evlist, evsel) { 322 evlist__for_each_entry(evlist, evsel) {
336 if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) && 323 if ((evsel->attr.type == PERF_TYPE_TRACEPOINT) &&
337 (strcmp(evsel->name, name) == 0)) 324 (strcmp(evsel->name, name) == 0))
338 return evsel; 325 return evsel;
@@ -367,7 +354,7 @@ void perf_evlist__disable(struct perf_evlist *evlist)
367{ 354{
368 struct perf_evsel *pos; 355 struct perf_evsel *pos;
369 356
370 evlist__for_each(evlist, pos) { 357 evlist__for_each_entry(evlist, pos) {
371 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 358 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
372 continue; 359 continue;
373 perf_evsel__disable(pos); 360 perf_evsel__disable(pos);
@@ -380,7 +367,7 @@ void perf_evlist__enable(struct perf_evlist *evlist)
380{ 367{
381 struct perf_evsel *pos; 368 struct perf_evsel *pos;
382 369
383 evlist__for_each(evlist, pos) { 370 evlist__for_each_entry(evlist, pos) {
384 if (!perf_evsel__is_group_leader(pos) || !pos->fd) 371 if (!perf_evsel__is_group_leader(pos) || !pos->fd)
385 continue; 372 continue;
386 perf_evsel__enable(pos); 373 perf_evsel__enable(pos);
@@ -397,15 +384,14 @@ void perf_evlist__toggle_enable(struct perf_evlist *evlist)
397static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist, 384static int perf_evlist__enable_event_cpu(struct perf_evlist *evlist,
398 struct perf_evsel *evsel, int cpu) 385 struct perf_evsel *evsel, int cpu)
399{ 386{
400 int thread, err; 387 int thread;
401 int nr_threads = perf_evlist__nr_threads(evlist, evsel); 388 int nr_threads = perf_evlist__nr_threads(evlist, evsel);
402 389
403 if (!evsel->fd) 390 if (!evsel->fd)
404 return -EINVAL; 391 return -EINVAL;
405 392
406 for (thread = 0; thread < nr_threads; thread++) { 393 for (thread = 0; thread < nr_threads; thread++) {
407 err = ioctl(FD(evsel, cpu, thread), 394 int err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
408 PERF_EVENT_IOC_ENABLE, 0);
409 if (err) 395 if (err)
410 return err; 396 return err;
411 } 397 }
@@ -416,14 +402,14 @@ static int perf_evlist__enable_event_thread(struct perf_evlist *evlist,
416 struct perf_evsel *evsel, 402 struct perf_evsel *evsel,
417 int thread) 403 int thread)
418{ 404{
419 int cpu, err; 405 int cpu;
420 int nr_cpus = cpu_map__nr(evlist->cpus); 406 int nr_cpus = cpu_map__nr(evlist->cpus);
421 407
422 if (!evsel->fd) 408 if (!evsel->fd)
423 return -EINVAL; 409 return -EINVAL;
424 410
425 for (cpu = 0; cpu < nr_cpus; cpu++) { 411 for (cpu = 0; cpu < nr_cpus; cpu++) {
426 err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0); 412 int err = ioctl(FD(evsel, cpu, thread), PERF_EVENT_IOC_ENABLE, 0);
427 if (err) 413 if (err)
428 return err; 414 return err;
429 } 415 }
@@ -448,7 +434,7 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
448 int nfds = 0; 434 int nfds = 0;
449 struct perf_evsel *evsel; 435 struct perf_evsel *evsel;
450 436
451 evlist__for_each(evlist, evsel) { 437 evlist__for_each_entry(evlist, evsel) {
452 if (evsel->system_wide) 438 if (evsel->system_wide)
453 nfds += nr_cpus; 439 nfds += nr_cpus;
454 else 440 else
@@ -462,15 +448,16 @@ int perf_evlist__alloc_pollfd(struct perf_evlist *evlist)
462 return 0; 448 return 0;
463} 449}
464 450
465static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx) 451static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd,
452 struct perf_mmap *map, short revent)
466{ 453{
467 int pos = fdarray__add(&evlist->pollfd, fd, POLLIN | POLLERR | POLLHUP); 454 int pos = fdarray__add(&evlist->pollfd, fd, revent | POLLERR | POLLHUP);
468 /* 455 /*
469 * Save the idx so that when we filter out fds POLLHUP'ed we can 456 * Save the idx so that when we filter out fds POLLHUP'ed we can
470 * close the associated evlist->mmap[] entry. 457 * close the associated evlist->mmap[] entry.
471 */ 458 */
472 if (pos >= 0) { 459 if (pos >= 0) {
473 evlist->pollfd.priv[pos].idx = idx; 460 evlist->pollfd.priv[pos].ptr = map;
474 461
475 fcntl(fd, F_SETFL, O_NONBLOCK); 462 fcntl(fd, F_SETFL, O_NONBLOCK);
476 } 463 }
@@ -480,20 +467,22 @@ static int __perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd, int idx
480 467
481int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd) 468int perf_evlist__add_pollfd(struct perf_evlist *evlist, int fd)
482{ 469{
483 return __perf_evlist__add_pollfd(evlist, fd, -1); 470 return __perf_evlist__add_pollfd(evlist, fd, NULL, POLLIN);
484} 471}
485 472
486static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd) 473static void perf_evlist__munmap_filtered(struct fdarray *fda, int fd,
474 void *arg __maybe_unused)
487{ 475{
488 struct perf_evlist *evlist = container_of(fda, struct perf_evlist, pollfd); 476 struct perf_mmap *map = fda->priv[fd].ptr;
489 477
490 perf_evlist__mmap_put(evlist, fda->priv[fd].idx); 478 if (map)
479 perf_mmap__put(map);
491} 480}
492 481
493int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask) 482int perf_evlist__filter_pollfd(struct perf_evlist *evlist, short revents_and_mask)
494{ 483{
495 return fdarray__filter(&evlist->pollfd, revents_and_mask, 484 return fdarray__filter(&evlist->pollfd, revents_and_mask,
496 perf_evlist__munmap_filtered); 485 perf_evlist__munmap_filtered, NULL);
497} 486}
498 487
499int perf_evlist__poll(struct perf_evlist *evlist, int timeout) 488int perf_evlist__poll(struct perf_evlist *evlist, int timeout)
@@ -647,8 +636,8 @@ static int perf_evlist__event2id(struct perf_evlist *evlist,
647 return 0; 636 return 0;
648} 637}
649 638
650static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist, 639struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
651 union perf_event *event) 640 union perf_event *event)
652{ 641{
653 struct perf_evsel *first = perf_evlist__first(evlist); 642 struct perf_evsel *first = perf_evlist__first(evlist);
654 struct hlist_head *head; 643 struct hlist_head *head;
@@ -684,8 +673,11 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
684{ 673{
685 int i; 674 int i;
686 675
676 if (!evlist->backward_mmap)
677 return 0;
678
687 for (i = 0; i < evlist->nr_mmaps; i++) { 679 for (i = 0; i < evlist->nr_mmaps; i++) {
688 int fd = evlist->mmap[i].fd; 680 int fd = evlist->backward_mmap[i].fd;
689 int err; 681 int err;
690 682
691 if (fd < 0) 683 if (fd < 0)
@@ -697,12 +689,12 @@ static int perf_evlist__set_paused(struct perf_evlist *evlist, bool value)
697 return 0; 689 return 0;
698} 690}
699 691
700int perf_evlist__pause(struct perf_evlist *evlist) 692static int perf_evlist__pause(struct perf_evlist *evlist)
701{ 693{
702 return perf_evlist__set_paused(evlist, true); 694 return perf_evlist__set_paused(evlist, true);
703} 695}
704 696
705int perf_evlist__resume(struct perf_evlist *evlist) 697static int perf_evlist__resume(struct perf_evlist *evlist)
706{ 698{
707 return perf_evlist__set_paused(evlist, false); 699 return perf_evlist__set_paused(evlist, false);
708} 700}
@@ -777,9 +769,8 @@ broken_event:
777 return event; 769 return event;
778} 770}
779 771
780union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 772union perf_event *perf_mmap__read_forward(struct perf_mmap *md, bool check_messup)
781{ 773{
782 struct perf_mmap *md = &evlist->mmap[idx];
783 u64 head; 774 u64 head;
784 u64 old = md->prev; 775 u64 old = md->prev;
785 776
@@ -791,13 +782,12 @@ union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
791 782
792 head = perf_mmap__read_head(md); 783 head = perf_mmap__read_head(md);
793 784
794 return perf_mmap__read(md, evlist->overwrite, old, head, &md->prev); 785 return perf_mmap__read(md, check_messup, old, head, &md->prev);
795} 786}
796 787
797union perf_event * 788union perf_event *
798perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx) 789perf_mmap__read_backward(struct perf_mmap *md)
799{ 790{
800 struct perf_mmap *md = &evlist->mmap[idx];
801 u64 head, end; 791 u64 head, end;
802 u64 start = md->prev; 792 u64 start = md->prev;
803 793
@@ -832,9 +822,38 @@ perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
832 return perf_mmap__read(md, false, start, end, &md->prev); 822 return perf_mmap__read(md, false, start, end, &md->prev);
833} 823}
834 824
835void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx) 825union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist, int idx)
836{ 826{
837 struct perf_mmap *md = &evlist->mmap[idx]; 827 struct perf_mmap *md = &evlist->mmap[idx];
828
829 /*
830 * Check messup is required for forward overwritable ring buffer:
831 * memory pointed by md->prev can be overwritten in this case.
832 * No need for read-write ring buffer: kernel stop outputting when
833 * it hit md->prev (perf_mmap__consume()).
834 */
835 return perf_mmap__read_forward(md, evlist->overwrite);
836}
837
838union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, int idx)
839{
840 struct perf_mmap *md = &evlist->mmap[idx];
841
842 /*
843 * No need to check messup for backward ring buffer:
844 * We can always read arbitrary long data from a backward
845 * ring buffer unless we forget to pause it before reading.
846 */
847 return perf_mmap__read_backward(md);
848}
849
850union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
851{
852 return perf_evlist__mmap_read_forward(evlist, idx);
853}
854
855void perf_mmap__read_catchup(struct perf_mmap *md)
856{
838 u64 head; 857 u64 head;
839 858
840 if (!atomic_read(&md->refcnt)) 859 if (!atomic_read(&md->refcnt))
@@ -844,36 +863,44 @@ void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
844 md->prev = head; 863 md->prev = head;
845} 864}
846 865
866void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx)
867{
868 perf_mmap__read_catchup(&evlist->mmap[idx]);
869}
870
847static bool perf_mmap__empty(struct perf_mmap *md) 871static bool perf_mmap__empty(struct perf_mmap *md)
848{ 872{
849 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base; 873 return perf_mmap__read_head(md) == md->prev && !md->auxtrace_mmap.base;
850} 874}
851 875
852static void perf_evlist__mmap_get(struct perf_evlist *evlist, int idx) 876static void perf_mmap__get(struct perf_mmap *map)
853{ 877{
854 atomic_inc(&evlist->mmap[idx].refcnt); 878 atomic_inc(&map->refcnt);
855} 879}
856 880
857static void perf_evlist__mmap_put(struct perf_evlist *evlist, int idx) 881static void perf_mmap__put(struct perf_mmap *md)
858{ 882{
859 BUG_ON(atomic_read(&evlist->mmap[idx].refcnt) == 0); 883 BUG_ON(md->base && atomic_read(&md->refcnt) == 0);
860 884
861 if (atomic_dec_and_test(&evlist->mmap[idx].refcnt)) 885 if (atomic_dec_and_test(&md->refcnt))
862 __perf_evlist__munmap(evlist, idx); 886 perf_mmap__munmap(md);
863} 887}
864 888
865void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx) 889void perf_mmap__consume(struct perf_mmap *md, bool overwrite)
866{ 890{
867 struct perf_mmap *md = &evlist->mmap[idx]; 891 if (!overwrite) {
868
869 if (!evlist->overwrite) {
870 u64 old = md->prev; 892 u64 old = md->prev;
871 893
872 perf_mmap__write_tail(md, old); 894 perf_mmap__write_tail(md, old);
873 } 895 }
874 896
875 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md)) 897 if (atomic_read(&md->refcnt) == 1 && perf_mmap__empty(md))
876 perf_evlist__mmap_put(evlist, idx); 898 perf_mmap__put(md);
899}
900
901void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
902{
903 perf_mmap__consume(&evlist->mmap[idx], evlist->overwrite);
877} 904}
878 905
879int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused, 906int __weak auxtrace_mmap__mmap(struct auxtrace_mmap *mm __maybe_unused,
@@ -904,41 +931,52 @@ void __weak auxtrace_mmap_params__set_idx(
904{ 931{
905} 932}
906 933
907static void __perf_evlist__munmap(struct perf_evlist *evlist, int idx) 934static void perf_mmap__munmap(struct perf_mmap *map)
908{ 935{
909 if (evlist->mmap[idx].base != NULL) { 936 if (map->base != NULL) {
910 munmap(evlist->mmap[idx].base, evlist->mmap_len); 937 munmap(map->base, perf_mmap__mmap_len(map));
911 evlist->mmap[idx].base = NULL; 938 map->base = NULL;
912 evlist->mmap[idx].fd = -1; 939 map->fd = -1;
913 atomic_set(&evlist->mmap[idx].refcnt, 0); 940 atomic_set(&map->refcnt, 0);
914 } 941 }
915 auxtrace_mmap__munmap(&evlist->mmap[idx].auxtrace_mmap); 942 auxtrace_mmap__munmap(&map->auxtrace_mmap);
916} 943}
917 944
918void perf_evlist__munmap(struct perf_evlist *evlist) 945static void perf_evlist__munmap_nofree(struct perf_evlist *evlist)
919{ 946{
920 int i; 947 int i;
921 948
922 if (evlist->mmap == NULL) 949 if (evlist->mmap)
923 return; 950 for (i = 0; i < evlist->nr_mmaps; i++)
951 perf_mmap__munmap(&evlist->mmap[i]);
924 952
925 for (i = 0; i < evlist->nr_mmaps; i++) 953 if (evlist->backward_mmap)
926 __perf_evlist__munmap(evlist, i); 954 for (i = 0; i < evlist->nr_mmaps; i++)
955 perf_mmap__munmap(&evlist->backward_mmap[i]);
956}
927 957
958void perf_evlist__munmap(struct perf_evlist *evlist)
959{
960 perf_evlist__munmap_nofree(evlist);
928 zfree(&evlist->mmap); 961 zfree(&evlist->mmap);
962 zfree(&evlist->backward_mmap);
929} 963}
930 964
931static int perf_evlist__alloc_mmap(struct perf_evlist *evlist) 965static struct perf_mmap *perf_evlist__alloc_mmap(struct perf_evlist *evlist)
932{ 966{
933 int i; 967 int i;
968 struct perf_mmap *map;
934 969
935 evlist->nr_mmaps = cpu_map__nr(evlist->cpus); 970 evlist->nr_mmaps = cpu_map__nr(evlist->cpus);
936 if (cpu_map__empty(evlist->cpus)) 971 if (cpu_map__empty(evlist->cpus))
937 evlist->nr_mmaps = thread_map__nr(evlist->threads); 972 evlist->nr_mmaps = thread_map__nr(evlist->threads);
938 evlist->mmap = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap)); 973 map = zalloc(evlist->nr_mmaps * sizeof(struct perf_mmap));
974 if (!map)
975 return NULL;
976
939 for (i = 0; i < evlist->nr_mmaps; i++) 977 for (i = 0; i < evlist->nr_mmaps; i++)
940 evlist->mmap[i].fd = -1; 978 map[i].fd = -1;
941 return evlist->mmap != NULL ? 0 : -ENOMEM; 979 return map;
942} 980}
943 981
944struct mmap_params { 982struct mmap_params {
@@ -947,8 +985,8 @@ struct mmap_params {
947 struct auxtrace_mmap_params auxtrace_mp; 985 struct auxtrace_mmap_params auxtrace_mp;
948}; 986};
949 987
950static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx, 988static int perf_mmap__mmap(struct perf_mmap *map,
951 struct mmap_params *mp, int fd) 989 struct mmap_params *mp, int fd)
952{ 990{
953 /* 991 /*
954 * The last one will be done at perf_evlist__mmap_consume(), so that we 992 * The last one will be done at perf_evlist__mmap_consume(), so that we
@@ -963,51 +1001,86 @@ static int __perf_evlist__mmap(struct perf_evlist *evlist, int idx,
963 * evlist layer can't just drop it when filtering events in 1001 * evlist layer can't just drop it when filtering events in
964 * perf_evlist__filter_pollfd(). 1002 * perf_evlist__filter_pollfd().
965 */ 1003 */
966 atomic_set(&evlist->mmap[idx].refcnt, 2); 1004 atomic_set(&map->refcnt, 2);
967 evlist->mmap[idx].prev = 0; 1005 map->prev = 0;
968 evlist->mmap[idx].mask = mp->mask; 1006 map->mask = mp->mask;
969 evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, mp->prot, 1007 map->base = mmap(NULL, perf_mmap__mmap_len(map), mp->prot,
970 MAP_SHARED, fd, 0); 1008 MAP_SHARED, fd, 0);
971 if (evlist->mmap[idx].base == MAP_FAILED) { 1009 if (map->base == MAP_FAILED) {
972 pr_debug2("failed to mmap perf event ring buffer, error %d\n", 1010 pr_debug2("failed to mmap perf event ring buffer, error %d\n",
973 errno); 1011 errno);
974 evlist->mmap[idx].base = NULL; 1012 map->base = NULL;
975 return -1; 1013 return -1;
976 } 1014 }
977 evlist->mmap[idx].fd = fd; 1015 map->fd = fd;
978 1016
979 if (auxtrace_mmap__mmap(&evlist->mmap[idx].auxtrace_mmap, 1017 if (auxtrace_mmap__mmap(&map->auxtrace_mmap,
980 &mp->auxtrace_mp, evlist->mmap[idx].base, fd)) 1018 &mp->auxtrace_mp, map->base, fd))
981 return -1; 1019 return -1;
982 1020
983 return 0; 1021 return 0;
984} 1022}
985 1023
1024static bool
1025perf_evlist__should_poll(struct perf_evlist *evlist __maybe_unused,
1026 struct perf_evsel *evsel)
1027{
1028 if (evsel->attr.write_backward)
1029 return false;
1030 return true;
1031}
1032
986static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx, 1033static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
987 struct mmap_params *mp, int cpu, 1034 struct mmap_params *mp, int cpu_idx,
988 int thread, int *output) 1035 int thread, int *_output, int *_output_backward)
989{ 1036{
990 struct perf_evsel *evsel; 1037 struct perf_evsel *evsel;
1038 int revent;
1039 int evlist_cpu = cpu_map__cpu(evlist->cpus, cpu_idx);
991 1040
992 evlist__for_each(evlist, evsel) { 1041 evlist__for_each_entry(evlist, evsel) {
1042 struct perf_mmap *maps = evlist->mmap;
1043 int *output = _output;
993 int fd; 1044 int fd;
1045 int cpu;
1046
1047 if (evsel->attr.write_backward) {
1048 output = _output_backward;
1049 maps = evlist->backward_mmap;
1050
1051 if (!maps) {
1052 maps = perf_evlist__alloc_mmap(evlist);
1053 if (!maps)
1054 return -1;
1055 evlist->backward_mmap = maps;
1056 if (evlist->bkw_mmap_state == BKW_MMAP_NOTREADY)
1057 perf_evlist__toggle_bkw_mmap(evlist, BKW_MMAP_RUNNING);
1058 }
1059 }
994 1060
995 if (evsel->system_wide && thread) 1061 if (evsel->system_wide && thread)
996 continue; 1062 continue;
997 1063
1064 cpu = cpu_map__idx(evsel->cpus, evlist_cpu);
1065 if (cpu == -1)
1066 continue;
1067
998 fd = FD(evsel, cpu, thread); 1068 fd = FD(evsel, cpu, thread);
999 1069
1000 if (*output == -1) { 1070 if (*output == -1) {
1001 *output = fd; 1071 *output = fd;
1002 if (__perf_evlist__mmap(evlist, idx, mp, *output) < 0) 1072
1073 if (perf_mmap__mmap(&maps[idx], mp, *output) < 0)
1003 return -1; 1074 return -1;
1004 } else { 1075 } else {
1005 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0) 1076 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, *output) != 0)
1006 return -1; 1077 return -1;
1007 1078
1008 perf_evlist__mmap_get(evlist, idx); 1079 perf_mmap__get(&maps[idx]);
1009 } 1080 }
1010 1081
1082 revent = perf_evlist__should_poll(evlist, evsel) ? POLLIN : 0;
1083
1011 /* 1084 /*
1012 * The system_wide flag causes a selected event to be opened 1085 * The system_wide flag causes a selected event to be opened
1013 * always without a pid. Consequently it will never get a 1086 * always without a pid. Consequently it will never get a
@@ -1016,8 +1089,8 @@ static int perf_evlist__mmap_per_evsel(struct perf_evlist *evlist, int idx,
1016 * Therefore don't add it for polling. 1089 * Therefore don't add it for polling.
1017 */ 1090 */
1018 if (!evsel->system_wide && 1091 if (!evsel->system_wide &&
1019 __perf_evlist__add_pollfd(evlist, fd, idx) < 0) { 1092 __perf_evlist__add_pollfd(evlist, fd, &maps[idx], revent) < 0) {
1020 perf_evlist__mmap_put(evlist, idx); 1093 perf_mmap__put(&maps[idx]);
1021 return -1; 1094 return -1;
1022 } 1095 }
1023 1096
@@ -1043,13 +1116,14 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
1043 pr_debug2("perf event ring buffer mmapped per cpu\n"); 1116 pr_debug2("perf event ring buffer mmapped per cpu\n");
1044 for (cpu = 0; cpu < nr_cpus; cpu++) { 1117 for (cpu = 0; cpu < nr_cpus; cpu++) {
1045 int output = -1; 1118 int output = -1;
1119 int output_backward = -1;
1046 1120
1047 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu, 1121 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, cpu,
1048 true); 1122 true);
1049 1123
1050 for (thread = 0; thread < nr_threads; thread++) { 1124 for (thread = 0; thread < nr_threads; thread++) {
1051 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu, 1125 if (perf_evlist__mmap_per_evsel(evlist, cpu, mp, cpu,
1052 thread, &output)) 1126 thread, &output, &output_backward))
1053 goto out_unmap; 1127 goto out_unmap;
1054 } 1128 }
1055 } 1129 }
@@ -1057,8 +1131,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist,
1057 return 0; 1131 return 0;
1058 1132
1059out_unmap: 1133out_unmap:
1060 for (cpu = 0; cpu < nr_cpus; cpu++) 1134 perf_evlist__munmap_nofree(evlist);
1061 __perf_evlist__munmap(evlist, cpu);
1062 return -1; 1135 return -1;
1063} 1136}
1064 1137
@@ -1071,20 +1144,20 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist,
1071 pr_debug2("perf event ring buffer mmapped per thread\n"); 1144 pr_debug2("perf event ring buffer mmapped per thread\n");
1072 for (thread = 0; thread < nr_threads; thread++) { 1145 for (thread = 0; thread < nr_threads; thread++) {
1073 int output = -1; 1146 int output = -1;
1147 int output_backward = -1;
1074 1148
1075 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread, 1149 auxtrace_mmap_params__set_idx(&mp->auxtrace_mp, evlist, thread,
1076 false); 1150 false);
1077 1151
1078 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread, 1152 if (perf_evlist__mmap_per_evsel(evlist, thread, mp, 0, thread,
1079 &output)) 1153 &output, &output_backward))
1080 goto out_unmap; 1154 goto out_unmap;
1081 } 1155 }
1082 1156
1083 return 0; 1157 return 0;
1084 1158
1085out_unmap: 1159out_unmap:
1086 for (thread = 0; thread < nr_threads; thread++) 1160 perf_evlist__munmap_nofree(evlist);
1087 __perf_evlist__munmap(evlist, thread);
1088 return -1; 1161 return -1;
1089} 1162}
1090 1163
@@ -1217,7 +1290,9 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1217 .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE), 1290 .prot = PROT_READ | (overwrite ? 0 : PROT_WRITE),
1218 }; 1291 };
1219 1292
1220 if (evlist->mmap == NULL && perf_evlist__alloc_mmap(evlist) < 0) 1293 if (!evlist->mmap)
1294 evlist->mmap = perf_evlist__alloc_mmap(evlist);
1295 if (!evlist->mmap)
1221 return -ENOMEM; 1296 return -ENOMEM;
1222 1297
1223 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0) 1298 if (evlist->pollfd.entries == NULL && perf_evlist__alloc_pollfd(evlist) < 0)
@@ -1231,7 +1306,7 @@ int perf_evlist__mmap_ex(struct perf_evlist *evlist, unsigned int pages,
1231 auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len, 1306 auxtrace_mmap_params__init(&mp.auxtrace_mp, evlist->mmap_len,
1232 auxtrace_pages, auxtrace_overwrite); 1307 auxtrace_pages, auxtrace_overwrite);
1233 1308
1234 evlist__for_each(evlist, evsel) { 1309 evlist__for_each_entry(evlist, evsel) {
1235 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 1310 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
1236 evsel->sample_id == NULL && 1311 evsel->sample_id == NULL &&
1237 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0) 1312 perf_evsel__alloc_id(evsel, cpu_map__nr(cpus), threads->nr) < 0)
@@ -1307,7 +1382,7 @@ void __perf_evlist__set_sample_bit(struct perf_evlist *evlist,
1307{ 1382{
1308 struct perf_evsel *evsel; 1383 struct perf_evsel *evsel;
1309 1384
1310 evlist__for_each(evlist, evsel) 1385 evlist__for_each_entry(evlist, evsel)
1311 __perf_evsel__set_sample_bit(evsel, bit); 1386 __perf_evsel__set_sample_bit(evsel, bit);
1312} 1387}
1313 1388
@@ -1316,7 +1391,7 @@ void __perf_evlist__reset_sample_bit(struct perf_evlist *evlist,
1316{ 1391{
1317 struct perf_evsel *evsel; 1392 struct perf_evsel *evsel;
1318 1393
1319 evlist__for_each(evlist, evsel) 1394 evlist__for_each_entry(evlist, evsel)
1320 __perf_evsel__reset_sample_bit(evsel, bit); 1395 __perf_evsel__reset_sample_bit(evsel, bit);
1321} 1396}
1322 1397
@@ -1327,7 +1402,7 @@ int perf_evlist__apply_filters(struct perf_evlist *evlist, struct perf_evsel **e
1327 const int ncpus = cpu_map__nr(evlist->cpus), 1402 const int ncpus = cpu_map__nr(evlist->cpus),
1328 nthreads = thread_map__nr(evlist->threads); 1403 nthreads = thread_map__nr(evlist->threads);
1329 1404
1330 evlist__for_each(evlist, evsel) { 1405 evlist__for_each_entry(evlist, evsel) {
1331 if (evsel->filter == NULL) 1406 if (evsel->filter == NULL)
1332 continue; 1407 continue;
1333 1408
@@ -1350,7 +1425,7 @@ int perf_evlist__set_filter(struct perf_evlist *evlist, const char *filter)
1350 struct perf_evsel *evsel; 1425 struct perf_evsel *evsel;
1351 int err = 0; 1426 int err = 0;
1352 1427
1353 evlist__for_each(evlist, evsel) { 1428 evlist__for_each_entry(evlist, evsel) {
1354 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 1429 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
1355 continue; 1430 continue;
1356 1431
@@ -1404,7 +1479,7 @@ bool perf_evlist__valid_sample_type(struct perf_evlist *evlist)
1404 if (evlist->id_pos < 0 || evlist->is_pos < 0) 1479 if (evlist->id_pos < 0 || evlist->is_pos < 0)
1405 return false; 1480 return false;
1406 1481
1407 evlist__for_each(evlist, pos) { 1482 evlist__for_each_entry(evlist, pos) {
1408 if (pos->id_pos != evlist->id_pos || 1483 if (pos->id_pos != evlist->id_pos ||
1409 pos->is_pos != evlist->is_pos) 1484 pos->is_pos != evlist->is_pos)
1410 return false; 1485 return false;
@@ -1420,7 +1495,7 @@ u64 __perf_evlist__combined_sample_type(struct perf_evlist *evlist)
1420 if (evlist->combined_sample_type) 1495 if (evlist->combined_sample_type)
1421 return evlist->combined_sample_type; 1496 return evlist->combined_sample_type;
1422 1497
1423 evlist__for_each(evlist, evsel) 1498 evlist__for_each_entry(evlist, evsel)
1424 evlist->combined_sample_type |= evsel->attr.sample_type; 1499 evlist->combined_sample_type |= evsel->attr.sample_type;
1425 1500
1426 return evlist->combined_sample_type; 1501 return evlist->combined_sample_type;
@@ -1437,7 +1512,7 @@ u64 perf_evlist__combined_branch_type(struct perf_evlist *evlist)
1437 struct perf_evsel *evsel; 1512 struct perf_evsel *evsel;
1438 u64 branch_type = 0; 1513 u64 branch_type = 0;
1439 1514
1440 evlist__for_each(evlist, evsel) 1515 evlist__for_each_entry(evlist, evsel)
1441 branch_type |= evsel->attr.branch_sample_type; 1516 branch_type |= evsel->attr.branch_sample_type;
1442 return branch_type; 1517 return branch_type;
1443} 1518}
@@ -1448,7 +1523,7 @@ bool perf_evlist__valid_read_format(struct perf_evlist *evlist)
1448 u64 read_format = first->attr.read_format; 1523 u64 read_format = first->attr.read_format;
1449 u64 sample_type = first->attr.sample_type; 1524 u64 sample_type = first->attr.sample_type;
1450 1525
1451 evlist__for_each(evlist, pos) { 1526 evlist__for_each_entry(evlist, pos) {
1452 if (read_format != pos->attr.read_format) 1527 if (read_format != pos->attr.read_format)
1453 return false; 1528 return false;
1454 } 1529 }
@@ -1505,7 +1580,7 @@ bool perf_evlist__valid_sample_id_all(struct perf_evlist *evlist)
1505{ 1580{
1506 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first; 1581 struct perf_evsel *first = perf_evlist__first(evlist), *pos = first;
1507 1582
1508 evlist__for_each_continue(evlist, pos) { 1583 evlist__for_each_entry_continue(evlist, pos) {
1509 if (first->attr.sample_id_all != pos->attr.sample_id_all) 1584 if (first->attr.sample_id_all != pos->attr.sample_id_all)
1510 return false; 1585 return false;
1511 } 1586 }
@@ -1530,10 +1605,9 @@ void perf_evlist__close(struct perf_evlist *evlist)
1530 struct perf_evsel *evsel; 1605 struct perf_evsel *evsel;
1531 int ncpus = cpu_map__nr(evlist->cpus); 1606 int ncpus = cpu_map__nr(evlist->cpus);
1532 int nthreads = thread_map__nr(evlist->threads); 1607 int nthreads = thread_map__nr(evlist->threads);
1533 int n;
1534 1608
1535 evlist__for_each_reverse(evlist, evsel) { 1609 evlist__for_each_entry_reverse(evlist, evsel) {
1536 n = evsel->cpus ? evsel->cpus->nr : ncpus; 1610 int n = evsel->cpus ? evsel->cpus->nr : ncpus;
1537 perf_evsel__close(evsel, n, nthreads); 1611 perf_evsel__close(evsel, n, nthreads);
1538 } 1612 }
1539} 1613}
@@ -1586,7 +1660,7 @@ int perf_evlist__open(struct perf_evlist *evlist)
1586 1660
1587 perf_evlist__update_id_pos(evlist); 1661 perf_evlist__update_id_pos(evlist);
1588 1662
1589 evlist__for_each(evlist, evsel) { 1663 evlist__for_each_entry(evlist, evsel) {
1590 err = perf_evsel__open(evsel, evsel->cpus, evsel->threads); 1664 err = perf_evsel__open(evsel, evsel->cpus, evsel->threads);
1591 if (err < 0) 1665 if (err < 0)
1592 goto out_err; 1666 goto out_err;
@@ -1747,7 +1821,7 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp)
1747 struct perf_evsel *evsel; 1821 struct perf_evsel *evsel;
1748 size_t printed = 0; 1822 size_t printed = 0;
1749 1823
1750 evlist__for_each(evlist, evsel) { 1824 evlist__for_each_entry(evlist, evsel) {
1751 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "", 1825 printed += fprintf(fp, "%s%s", evsel->idx ? ", " : "",
1752 perf_evsel__name(evsel)); 1826 perf_evsel__name(evsel));
1753 } 1827 }
@@ -1759,7 +1833,7 @@ int perf_evlist__strerror_open(struct perf_evlist *evlist,
1759 int err, char *buf, size_t size) 1833 int err, char *buf, size_t size)
1760{ 1834{
1761 int printed, value; 1835 int printed, value;
1762 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1836 char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
1763 1837
1764 switch (err) { 1838 switch (err) {
1765 case EACCES: 1839 case EACCES:
@@ -1811,7 +1885,7 @@ out_default:
1811 1885
1812int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size) 1886int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size)
1813{ 1887{
1814 char sbuf[STRERR_BUFSIZE], *emsg = strerror_r(err, sbuf, sizeof(sbuf)); 1888 char sbuf[STRERR_BUFSIZE], *emsg = str_error_r(err, sbuf, sizeof(sbuf));
1815 int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0; 1889 int pages_attempted = evlist->mmap_len / 1024, pages_max_per_user, printed = 0;
1816 1890
1817 switch (err) { 1891 switch (err) {
@@ -1849,7 +1923,7 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
1849 if (move_evsel == perf_evlist__first(evlist)) 1923 if (move_evsel == perf_evlist__first(evlist))
1850 return; 1924 return;
1851 1925
1852 evlist__for_each_safe(evlist, n, evsel) { 1926 evlist__for_each_entry_safe(evlist, n, evsel) {
1853 if (evsel->leader == move_evsel->leader) 1927 if (evsel->leader == move_evsel->leader)
1854 list_move_tail(&evsel->node, &move); 1928 list_move_tail(&evsel->node, &move);
1855 } 1929 }
@@ -1865,7 +1939,7 @@ void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
1865 if (tracking_evsel->tracking) 1939 if (tracking_evsel->tracking)
1866 return; 1940 return;
1867 1941
1868 evlist__for_each(evlist, evsel) { 1942 evlist__for_each_entry(evlist, evsel) {
1869 if (evsel != tracking_evsel) 1943 if (evsel != tracking_evsel)
1870 evsel->tracking = false; 1944 evsel->tracking = false;
1871 } 1945 }
@@ -1879,7 +1953,7 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
1879{ 1953{
1880 struct perf_evsel *evsel; 1954 struct perf_evsel *evsel;
1881 1955
1882 evlist__for_each(evlist, evsel) { 1956 evlist__for_each_entry(evlist, evsel) {
1883 if (!evsel->name) 1957 if (!evsel->name)
1884 continue; 1958 continue;
1885 if (strcmp(str, evsel->name) == 0) 1959 if (strcmp(str, evsel->name) == 0)
@@ -1888,3 +1962,61 @@ perf_evlist__find_evsel_by_str(struct perf_evlist *evlist,
1888 1962
1889 return NULL; 1963 return NULL;
1890} 1964}
1965
1966void perf_evlist__toggle_bkw_mmap(struct perf_evlist *evlist,
1967 enum bkw_mmap_state state)
1968{
1969 enum bkw_mmap_state old_state = evlist->bkw_mmap_state;
1970 enum action {
1971 NONE,
1972 PAUSE,
1973 RESUME,
1974 } action = NONE;
1975
1976 if (!evlist->backward_mmap)
1977 return;
1978
1979 switch (old_state) {
1980 case BKW_MMAP_NOTREADY: {
1981 if (state != BKW_MMAP_RUNNING)
1982 goto state_err;;
1983 break;
1984 }
1985 case BKW_MMAP_RUNNING: {
1986 if (state != BKW_MMAP_DATA_PENDING)
1987 goto state_err;
1988 action = PAUSE;
1989 break;
1990 }
1991 case BKW_MMAP_DATA_PENDING: {
1992 if (state != BKW_MMAP_EMPTY)
1993 goto state_err;
1994 break;
1995 }
1996 case BKW_MMAP_EMPTY: {
1997 if (state != BKW_MMAP_RUNNING)
1998 goto state_err;
1999 action = RESUME;
2000 break;
2001 }
2002 default:
2003 WARN_ONCE(1, "Shouldn't get there\n");
2004 }
2005
2006 evlist->bkw_mmap_state = state;
2007
2008 switch (action) {
2009 case PAUSE:
2010 perf_evlist__pause(evlist);
2011 break;
2012 case RESUME:
2013 perf_evlist__resume(evlist);
2014 break;
2015 case NONE:
2016 default:
2017 break;
2018 }
2019
2020state_err:
2021 return;
2022}
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index d740fb877ab6..4fd034f22d2f 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -35,6 +35,40 @@ struct perf_mmap {
35 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 35 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
36}; 36};
37 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
38struct perf_evlist { 72struct perf_evlist {
39 struct list_head entries; 73 struct list_head entries;
40 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE]; 74 struct hlist_head heads[PERF_EVLIST__HLIST_SIZE];
@@ -44,17 +78,18 @@ struct perf_evlist {
44 bool overwrite; 78 bool overwrite;
45 bool enabled; 79 bool enabled;
46 bool has_user_cpus; 80 bool has_user_cpus;
47 bool backward;
48 size_t mmap_len; 81 size_t mmap_len;
49 int id_pos; 82 int id_pos;
50 int is_pos; 83 int is_pos;
51 u64 combined_sample_type; 84 u64 combined_sample_type;
85 enum bkw_mmap_state bkw_mmap_state;
52 struct { 86 struct {
53 int cork_fd; 87 int cork_fd;
54 pid_t pid; 88 pid_t pid;
55 } workload; 89 } workload;
56 struct fdarray pollfd; 90 struct fdarray pollfd;
57 struct perf_mmap *mmap; 91 struct perf_mmap *mmap;
92 struct perf_mmap *backward_mmap;
58 struct thread_map *threads; 93 struct thread_map *threads;
59 struct cpu_map *cpus; 94 struct cpu_map *cpus;
60 struct perf_evsel *selected; 95 struct perf_evsel *selected;
@@ -129,16 +164,24 @@ struct perf_evsel *perf_evlist__id2evsel_strict(struct perf_evlist *evlist,
129 164
130struct 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);
131 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
132union 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);
133 176
177union perf_event *perf_evlist__mmap_read_forward(struct perf_evlist *evlist,
178 int idx);
134union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist, 179union perf_event *perf_evlist__mmap_read_backward(struct perf_evlist *evlist,
135 int idx); 180 int idx);
136void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx); 181void perf_evlist__mmap_read_catchup(struct perf_evlist *evlist, int idx);
137 182
138void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx); 183void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx);
139 184
140int perf_evlist__pause(struct perf_evlist *evlist);
141int perf_evlist__resume(struct perf_evlist *evlist);
142int perf_evlist__open(struct perf_evlist *evlist); 185int perf_evlist__open(struct perf_evlist *evlist);
143void perf_evlist__close(struct perf_evlist *evlist); 186void perf_evlist__close(struct perf_evlist *evlist);
144 187
@@ -249,70 +292,70 @@ void perf_evlist__to_front(struct perf_evlist *evlist,
249 struct perf_evsel *move_evsel); 292 struct perf_evsel *move_evsel);
250 293
251/** 294/**
252 * __evlist__for_each - iterate thru all the evsels 295 * __evlist__for_each_entry - iterate thru all the evsels
253 * @list: list_head instance to iterate 296 * @list: list_head instance to iterate
254 * @evsel: struct evsel iterator 297 * @evsel: struct evsel iterator
255 */ 298 */
256#define __evlist__for_each(list, evsel) \ 299#define __evlist__for_each_entry(list, evsel) \
257 list_for_each_entry(evsel, list, node) 300 list_for_each_entry(evsel, list, node)
258 301
259/** 302/**
260 * evlist__for_each - iterate thru all the evsels 303 * evlist__for_each_entry - iterate thru all the evsels
261 * @evlist: evlist instance to iterate 304 * @evlist: evlist instance to iterate
262 * @evsel: struct evsel iterator 305 * @evsel: struct evsel iterator
263 */ 306 */
264#define evlist__for_each(evlist, evsel) \ 307#define evlist__for_each_entry(evlist, evsel) \
265 __evlist__for_each(&(evlist)->entries, evsel) 308 __evlist__for_each_entry(&(evlist)->entries, evsel)
266 309
267/** 310/**
268 * __evlist__for_each_continue - continue iteration thru all the evsels 311 * __evlist__for_each_entry_continue - continue iteration thru all the evsels
269 * @list: list_head instance to iterate 312 * @list: list_head instance to iterate
270 * @evsel: struct evsel iterator 313 * @evsel: struct evsel iterator
271 */ 314 */
272#define __evlist__for_each_continue(list, evsel) \ 315#define __evlist__for_each_entry_continue(list, evsel) \
273 list_for_each_entry_continue(evsel, list, node) 316 list_for_each_entry_continue(evsel, list, node)
274 317
275/** 318/**
276 * evlist__for_each_continue - continue iteration thru all the evsels 319 * evlist__for_each_entry_continue - continue iteration thru all the evsels
277 * @evlist: evlist instance to iterate 320 * @evlist: evlist instance to iterate
278 * @evsel: struct evsel iterator 321 * @evsel: struct evsel iterator
279 */ 322 */
280#define evlist__for_each_continue(evlist, evsel) \ 323#define evlist__for_each_entry_continue(evlist, evsel) \
281 __evlist__for_each_continue(&(evlist)->entries, evsel) 324 __evlist__for_each_entry_continue(&(evlist)->entries, evsel)
282 325
283/** 326/**
284 * __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
285 * @list: list_head instance to iterate 328 * @list: list_head instance to iterate
286 * @evsel: struct evsel iterator 329 * @evsel: struct evsel iterator
287 */ 330 */
288#define __evlist__for_each_reverse(list, evsel) \ 331#define __evlist__for_each_entry_reverse(list, evsel) \
289 list_for_each_entry_reverse(evsel, list, node) 332 list_for_each_entry_reverse(evsel, list, node)
290 333
291/** 334/**
292 * 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
293 * @evlist: evlist instance to iterate 336 * @evlist: evlist instance to iterate
294 * @evsel: struct evsel iterator 337 * @evsel: struct evsel iterator
295 */ 338 */
296#define evlist__for_each_reverse(evlist, evsel) \ 339#define evlist__for_each_entry_reverse(evlist, evsel) \
297 __evlist__for_each_reverse(&(evlist)->entries, evsel) 340 __evlist__for_each_entry_reverse(&(evlist)->entries, evsel)
298 341
299/** 342/**
300 * __evlist__for_each_safe - safely iterate thru all the evsels 343 * __evlist__for_each_entry_safe - safely iterate thru all the evsels
301 * @list: list_head instance to iterate 344 * @list: list_head instance to iterate
302 * @tmp: struct evsel temp iterator 345 * @tmp: struct evsel temp iterator
303 * @evsel: struct evsel iterator 346 * @evsel: struct evsel iterator
304 */ 347 */
305#define __evlist__for_each_safe(list, tmp, evsel) \ 348#define __evlist__for_each_entry_safe(list, tmp, evsel) \
306 list_for_each_entry_safe(evsel, tmp, list, node) 349 list_for_each_entry_safe(evsel, tmp, list, node)
307 350
308/** 351/**
309 * evlist__for_each_safe - safely iterate thru all the evsels 352 * evlist__for_each_entry_safe - safely iterate thru all the evsels
310 * @evlist: evlist instance to iterate 353 * @evlist: evlist instance to iterate
311 * @evsel: struct evsel iterator 354 * @evsel: struct evsel iterator
312 * @tmp: struct evsel temp iterator 355 * @tmp: struct evsel temp iterator
313 */ 356 */
314#define evlist__for_each_safe(evlist, tmp, evsel) \ 357#define evlist__for_each_entry_safe(evlist, tmp, evsel) \
315 __evlist__for_each_safe(&(evlist)->entries, tmp, evsel) 358 __evlist__for_each_entry_safe(&(evlist)->entries, tmp, evsel)
316 359
317void perf_evlist__set_tracking_event(struct perf_evlist *evlist, 360void perf_evlist__set_tracking_event(struct perf_evlist *evlist,
318 struct perf_evsel *tracking_evsel); 361 struct perf_evsel *tracking_evsel);
@@ -321,4 +364,7 @@ void perf_event_attr__set_max_precise_ip(struct perf_event_attr *attr);
321 364
322struct perf_evsel * 365struct perf_evsel *
323perf_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);
324#endif /* __PERF_EVLIST_H */ 370#endif /* __PERF_EVLIST_H */
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 5d7037ef7d3b..8bc271141d9d 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -200,6 +200,24 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
200 evsel->attr.read_format |= PERF_FORMAT_ID; 200 evsel->attr.read_format |= PERF_FORMAT_ID;
201} 201}
202 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
203void perf_evsel__init(struct perf_evsel *evsel, 221void perf_evsel__init(struct perf_evsel *evsel,
204 struct perf_event_attr *attr, int idx) 222 struct perf_event_attr *attr, int idx)
205{ 223{
@@ -235,6 +253,34 @@ struct perf_evsel *perf_evsel__new_idx(struct perf_event_attr *attr, int idx)
235 return evsel; 253 return evsel;
236} 254}
237 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
238/* 284/*
239 * Returns pointer with encoded error via <linux/err.h> interface. 285 * Returns pointer with encoded error via <linux/err.h> interface.
240 */ 286 */
@@ -461,17 +507,17 @@ static int __perf_evsel__hw_cache_name(u64 config, char *bf, size_t size)
461 u8 op, result, type = (config >> 0) & 0xff; 507 u8 op, result, type = (config >> 0) & 0xff;
462 const char *err = "unknown-ext-hardware-cache-type"; 508 const char *err = "unknown-ext-hardware-cache-type";
463 509
464 if (type > PERF_COUNT_HW_CACHE_MAX) 510 if (type >= PERF_COUNT_HW_CACHE_MAX)
465 goto out_err; 511 goto out_err;
466 512
467 op = (config >> 8) & 0xff; 513 op = (config >> 8) & 0xff;
468 err = "unknown-ext-hardware-cache-op"; 514 err = "unknown-ext-hardware-cache-op";
469 if (op > PERF_COUNT_HW_CACHE_OP_MAX) 515 if (op >= PERF_COUNT_HW_CACHE_OP_MAX)
470 goto out_err; 516 goto out_err;
471 517
472 result = (config >> 16) & 0xff; 518 result = (config >> 16) & 0xff;
473 err = "unknown-ext-hardware-cache-result"; 519 err = "unknown-ext-hardware-cache-result";
474 if (result > PERF_COUNT_HW_CACHE_RESULT_MAX) 520 if (result >= PERF_COUNT_HW_CACHE_RESULT_MAX)
475 goto out_err; 521 goto out_err;
476 522
477 err = "invalid-cache"; 523 err = "invalid-cache";
@@ -572,6 +618,8 @@ void perf_evsel__config_callchain(struct perf_evsel *evsel,
572 618
573 perf_evsel__set_sample_bit(evsel, CALLCHAIN); 619 perf_evsel__set_sample_bit(evsel, CALLCHAIN);
574 620
621 attr->sample_max_stack = param->max_stack;
622
575 if (param->record_mode == CALLCHAIN_LBR) { 623 if (param->record_mode == CALLCHAIN_LBR) {
576 if (!opts->branch_stack) { 624 if (!opts->branch_stack) {
577 if (attr->exclude_user) { 625 if (attr->exclude_user) {
@@ -635,7 +683,8 @@ static void apply_config_terms(struct perf_evsel *evsel,
635 struct perf_event_attr *attr = &evsel->attr; 683 struct perf_event_attr *attr = &evsel->attr;
636 struct callchain_param param; 684 struct callchain_param param;
637 u32 dump_size = 0; 685 u32 dump_size = 0;
638 char *callgraph_buf = NULL; 686 int max_stack = 0;
687 const char *callgraph_buf = NULL;
639 688
640 /* callgraph default */ 689 /* callgraph default */
641 param.record_mode = callchain_param.record_mode; 690 param.record_mode = callchain_param.record_mode;
@@ -662,6 +711,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
662 case PERF_EVSEL__CONFIG_TERM_STACK_USER: 711 case PERF_EVSEL__CONFIG_TERM_STACK_USER:
663 dump_size = term->val.stack_user; 712 dump_size = term->val.stack_user;
664 break; 713 break;
714 case PERF_EVSEL__CONFIG_TERM_MAX_STACK:
715 max_stack = term->val.max_stack;
716 break;
665 case PERF_EVSEL__CONFIG_TERM_INHERIT: 717 case PERF_EVSEL__CONFIG_TERM_INHERIT:
666 /* 718 /*
667 * attr->inherit should has already been set by 719 * attr->inherit should has already been set by
@@ -671,13 +723,21 @@ static void apply_config_terms(struct perf_evsel *evsel,
671 */ 723 */
672 attr->inherit = term->val.inherit ? 1 : 0; 724 attr->inherit = term->val.inherit ? 1 : 0;
673 break; 725 break;
726 case PERF_EVSEL__CONFIG_TERM_OVERWRITE:
727 attr->write_backward = term->val.overwrite ? 1 : 0;
728 break;
674 default: 729 default:
675 break; 730 break;
676 } 731 }
677 } 732 }
678 733
679 /* 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. */
680 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 }
681 741
682 /* parse callgraph parameters */ 742 /* parse callgraph parameters */
683 if (callgraph_buf != NULL) { 743 if (callgraph_buf != NULL) {
@@ -747,6 +807,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
747 807
748 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;
749 attr->inherit = !opts->no_inherit; 809 attr->inherit = !opts->no_inherit;
810 attr->write_backward = opts->overwrite ? 1 : 0;
750 811
751 perf_evsel__set_sample_bit(evsel, IP); 812 perf_evsel__set_sample_bit(evsel, IP);
752 perf_evsel__set_sample_bit(evsel, TID); 813 perf_evsel__set_sample_bit(evsel, TID);
@@ -821,7 +882,7 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
821 perf_evsel__set_sample_bit(evsel, REGS_INTR); 882 perf_evsel__set_sample_bit(evsel, REGS_INTR);
822 } 883 }
823 884
824 if (target__has_cpu(&opts->target)) 885 if (target__has_cpu(&opts->target) || opts->sample_cpu)
825 perf_evsel__set_sample_bit(evsel, CPU); 886 perf_evsel__set_sample_bit(evsel, CPU);
826 887
827 if (opts->period) 888 if (opts->period)
@@ -924,14 +985,13 @@ void perf_evsel__config(struct perf_evsel *evsel, struct record_opts *opts,
924 985
925static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads) 986static int perf_evsel__alloc_fd(struct perf_evsel *evsel, int ncpus, int nthreads)
926{ 987{
927 int cpu, thread;
928
929 if (evsel->system_wide) 988 if (evsel->system_wide)
930 nthreads = 1; 989 nthreads = 1;
931 990
932 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int)); 991 evsel->fd = xyarray__new(ncpus, nthreads, sizeof(int));
933 992
934 if (evsel->fd) { 993 if (evsel->fd) {
994 int cpu, thread;
935 for (cpu = 0; cpu < ncpus; cpu++) { 995 for (cpu = 0; cpu < ncpus; cpu++) {
936 for (thread = 0; thread < nthreads; thread++) { 996 for (thread = 0; thread < nthreads; thread++) {
937 FD(evsel, cpu, thread) = -1; 997 FD(evsel, cpu, thread) = -1;
@@ -984,15 +1044,15 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
984 return -1; 1044 return -1;
985} 1045}
986 1046
987int perf_evsel__append_filter(struct perf_evsel *evsel, 1047static int perf_evsel__append_filter(struct perf_evsel *evsel,
988 const char *op, const char *filter) 1048 const char *fmt, const char *filter)
989{ 1049{
990 char *new_filter; 1050 char *new_filter;
991 1051
992 if (evsel->filter == NULL) 1052 if (evsel->filter == NULL)
993 return perf_evsel__set_filter(evsel, filter); 1053 return perf_evsel__set_filter(evsel, filter);
994 1054
995 if (asprintf(&new_filter,"(%s) %s (%s)", evsel->filter, op, filter) > 0) { 1055 if (asprintf(&new_filter, fmt, evsel->filter, filter) > 0) {
996 free(evsel->filter); 1056 free(evsel->filter);
997 evsel->filter = new_filter; 1057 evsel->filter = new_filter;
998 return 0; 1058 return 0;
@@ -1001,6 +1061,16 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
1001 return -1; 1061 return -1;
1002} 1062}
1003 1063
1064int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter)
1065{
1066 return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter);
1067}
1068
1069int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
1070{
1071 return perf_evsel__append_filter(evsel, "%s,%s", filter);
1072}
1073
1004int perf_evsel__enable(struct perf_evsel *evsel) 1074int perf_evsel__enable(struct perf_evsel *evsel)
1005{ 1075{
1006 int nthreads = thread_map__nr(evsel->threads); 1076 int nthreads = thread_map__nr(evsel->threads);
@@ -1329,6 +1399,7 @@ int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
1329 PRINT_ATTRf(clockid, p_signed); 1399 PRINT_ATTRf(clockid, p_signed);
1330 PRINT_ATTRf(sample_regs_intr, p_hex); 1400 PRINT_ATTRf(sample_regs_intr, p_hex);
1331 PRINT_ATTRf(aux_watermark, p_unsigned); 1401 PRINT_ATTRf(aux_watermark, p_unsigned);
1402 PRINT_ATTRf(sample_max_stack, p_unsigned);
1332 1403
1333 return ret; 1404 return ret;
1334} 1405}
@@ -1347,6 +1418,9 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
1347 int pid = -1, err; 1418 int pid = -1, err;
1348 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE; 1419 enum { NO_CHANGE, SET_TO_MAX, INCREASED_MAX } set_rlimit = NO_CHANGE;
1349 1420
1421 if (perf_missing_features.write_backward && evsel->attr.write_backward)
1422 return -EINVAL;
1423
1350 if (evsel->system_wide) 1424 if (evsel->system_wide)
1351 nthreads = 1; 1425 nthreads = 1;
1352 else 1426 else
@@ -1377,8 +1451,6 @@ fallback_missing_features:
1377 if (perf_missing_features.lbr_flags) 1451 if (perf_missing_features.lbr_flags)
1378 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS | 1452 evsel->attr.branch_sample_type &= ~(PERF_SAMPLE_BRANCH_NO_FLAGS |
1379 PERF_SAMPLE_BRANCH_NO_CYCLES); 1453 PERF_SAMPLE_BRANCH_NO_CYCLES);
1380 if (perf_missing_features.write_backward)
1381 evsel->attr.write_backward = false;
1382retry_sample_id: 1454retry_sample_id:
1383 if (perf_missing_features.sample_id_all) 1455 if (perf_missing_features.sample_id_all)
1384 evsel->attr.sample_id_all = 0; 1456 evsel->attr.sample_id_all = 0;
@@ -1441,12 +1513,6 @@ retry_open:
1441 err = -EINVAL; 1513 err = -EINVAL;
1442 goto out_close; 1514 goto out_close;
1443 } 1515 }
1444
1445 if (evsel->overwrite &&
1446 perf_missing_features.write_backward) {
1447 err = -EINVAL;
1448 goto out_close;
1449 }
1450 } 1516 }
1451 } 1517 }
1452 1518
@@ -1484,7 +1550,10 @@ try_fallback:
1484 * Must probe features in the order they were added to the 1550 * Must probe features in the order they were added to the
1485 * perf_event_attr interface. 1551 * perf_event_attr interface.
1486 */ 1552 */
1487 if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) { 1553 if (!perf_missing_features.write_backward && evsel->attr.write_backward) {
1554 perf_missing_features.write_backward = true;
1555 goto out_close;
1556 } else if (!perf_missing_features.clockid_wrong && evsel->attr.use_clockid) {
1488 perf_missing_features.clockid_wrong = true; 1557 perf_missing_features.clockid_wrong = true;
1489 goto fallback_missing_features; 1558 goto fallback_missing_features;
1490 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) { 1559 } else if (!perf_missing_features.clockid && evsel->attr.use_clockid) {
@@ -1509,12 +1578,7 @@ try_fallback:
1509 PERF_SAMPLE_BRANCH_NO_FLAGS))) { 1578 PERF_SAMPLE_BRANCH_NO_FLAGS))) {
1510 perf_missing_features.lbr_flags = true; 1579 perf_missing_features.lbr_flags = true;
1511 goto fallback_missing_features; 1580 goto fallback_missing_features;
1512 } else if (!perf_missing_features.write_backward &&
1513 evsel->attr.write_backward) {
1514 perf_missing_features.write_backward = true;
1515 goto fallback_missing_features;
1516 } 1581 }
1517
1518out_close: 1582out_close:
1519 do { 1583 do {
1520 while (--thread >= 0) { 1584 while (--thread >= 0) {
@@ -1673,7 +1737,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1673 data->cpu = data->pid = data->tid = -1; 1737 data->cpu = data->pid = data->tid = -1;
1674 data->stream_id = data->id = data->time = -1ULL; 1738 data->stream_id = data->id = data->time = -1ULL;
1675 data->period = evsel->attr.sample_period; 1739 data->period = evsel->attr.sample_period;
1676 data->weight = 0;
1677 data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 1740 data->cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
1678 1741
1679 if (event->header.type != PERF_RECORD_SAMPLE) { 1742 if (event->header.type != PERF_RECORD_SAMPLE) {
@@ -1880,7 +1943,6 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event,
1880 } 1943 }
1881 } 1944 }
1882 1945
1883 data->weight = 0;
1884 if (type & PERF_SAMPLE_WEIGHT) { 1946 if (type & PERF_SAMPLE_WEIGHT) {
1885 OVERFLOW_CHECK_u64(array); 1947 OVERFLOW_CHECK_u64(array);
1886 data->weight = *array; 1948 data->weight = *array;
@@ -2239,17 +2301,11 @@ void *perf_evsel__rawptr(struct perf_evsel *evsel, struct perf_sample *sample,
2239 return sample->raw_data + offset; 2301 return sample->raw_data + offset;
2240} 2302}
2241 2303
2242u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample, 2304u64 format_field__intval(struct format_field *field, struct perf_sample *sample,
2243 const char *name) 2305 bool needs_swap)
2244{ 2306{
2245 struct format_field *field = perf_evsel__field(evsel, name);
2246 void *ptr;
2247 u64 value; 2307 u64 value;
2248 2308 void *ptr = sample->raw_data + field->offset;
2249 if (!field)
2250 return 0;
2251
2252 ptr = sample->raw_data + field->offset;
2253 2309
2254 switch (field->size) { 2310 switch (field->size) {
2255 case 1: 2311 case 1:
@@ -2267,7 +2323,7 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2267 return 0; 2323 return 0;
2268 } 2324 }
2269 2325
2270 if (!evsel->needs_swap) 2326 if (!needs_swap)
2271 return value; 2327 return value;
2272 2328
2273 switch (field->size) { 2329 switch (field->size) {
@@ -2284,6 +2340,17 @@ u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2284 return 0; 2340 return 0;
2285} 2341}
2286 2342
2343u64 perf_evsel__intval(struct perf_evsel *evsel, struct perf_sample *sample,
2344 const char *name)
2345{
2346 struct format_field *field = perf_evsel__field(evsel, name);
2347
2348 if (!field)
2349 return 0;
2350
2351 return field ? format_field__intval(field, sample, evsel->needs_swap) : 0;
2352}
2353
2287bool perf_evsel__fallback(struct perf_evsel *evsel, int err, 2354bool perf_evsel__fallback(struct perf_evsel *evsel, int err,
2288 char *msg, size_t msgsize) 2355 char *msg, size_t msgsize)
2289{ 2356{
@@ -2372,6 +2439,9 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2372 "No such device - did you specify an out-of-range profile CPU?"); 2439 "No such device - did you specify an out-of-range profile CPU?");
2373 break; 2440 break;
2374 case EOPNOTSUPP: 2441 case EOPNOTSUPP:
2442 if (evsel->attr.sample_period != 0)
2443 return scnprintf(msg, size, "%s",
2444 "PMU Hardware doesn't support sampling/overflow-interrupts.");
2375 if (evsel->attr.precise_ip) 2445 if (evsel->attr.precise_ip)
2376 return scnprintf(msg, size, "%s", 2446 return scnprintf(msg, size, "%s",
2377 "\'precise\' request may not be supported. Try removing 'p' modifier."); 2447 "\'precise\' request may not be supported. Try removing 'p' modifier.");
@@ -2389,6 +2459,8 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2389 "We found oprofile daemon running, please stop it and try again."); 2459 "We found oprofile daemon running, please stop it and try again.");
2390 break; 2460 break;
2391 case EINVAL: 2461 case EINVAL:
2462 if (evsel->attr.write_backward && perf_missing_features.write_backward)
2463 return scnprintf(msg, size, "Reading from overwrite event is not supported by this kernel.");
2392 if (perf_missing_features.clockid) 2464 if (perf_missing_features.clockid)
2393 return scnprintf(msg, size, "clockid feature not supported."); 2465 return scnprintf(msg, size, "clockid feature not supported.");
2394 if (perf_missing_features.clockid_wrong) 2466 if (perf_missing_features.clockid_wrong)
@@ -2402,6 +2474,13 @@ int perf_evsel__open_strerror(struct perf_evsel *evsel, struct target *target,
2402 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n" 2474 "The sys_perf_event_open() syscall returned with %d (%s) for event (%s).\n"
2403 "/bin/dmesg may provide additional information.\n" 2475 "/bin/dmesg may provide additional information.\n"
2404 "No CONFIG_PERF_EVENTS=y kernel support configured?", 2476 "No CONFIG_PERF_EVENTS=y kernel support configured?",
2405 err, strerror_r(err, sbuf, sizeof(sbuf)), 2477 err, str_error_r(err, sbuf, sizeof(sbuf)),
2406 perf_evsel__name(evsel)); 2478 perf_evsel__name(evsel));
2407} 2479}
2480
2481char *perf_evsel__env_arch(struct perf_evsel *evsel)
2482{
2483 if (evsel && evsel->evlist && evsel->evlist->env)
2484 return evsel->evlist->env->arch;
2485 return NULL;
2486}
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index c1f10159804c..b1503b0ecdff 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -44,6 +44,9 @@ 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,
49 PERF_EVSEL__CONFIG_TERM_DRV_CFG,
47 PERF_EVSEL__CONFIG_TERM_MAX, 50 PERF_EVSEL__CONFIG_TERM_MAX,
48}; 51};
49 52
@@ -55,8 +58,11 @@ struct perf_evsel_config_term {
55 u64 freq; 58 u64 freq;
56 bool time; 59 bool time;
57 char *callgraph; 60 char *callgraph;
61 char *drv_cfg;
58 u64 stack_user; 62 u64 stack_user;
63 int max_stack;
59 bool inherit; 64 bool inherit;
65 bool overwrite;
60 } val; 66 } val;
61}; 67};
62 68
@@ -112,7 +118,6 @@ struct perf_evsel {
112 bool tracking; 118 bool tracking;
113 bool per_pkg; 119 bool per_pkg;
114 bool precise_max; 120 bool precise_max;
115 bool overwrite;
116 /* parse modifier helper */ 121 /* parse modifier helper */
117 int exclude_GH; 122 int exclude_GH;
118 int nr_members; 123 int nr_members;
@@ -172,6 +177,8 @@ static inline struct perf_evsel *perf_evsel__newtp(const char *sys, const char *
172 return perf_evsel__newtp_idx(sys, name, 0); 177 return perf_evsel__newtp_idx(sys, name, 0);
173} 178}
174 179
180struct perf_evsel *perf_evsel__new_cycles(void);
181
175struct event_format *event_format__new(const char *sys, const char *name); 182struct event_format *event_format__new(const char *sys, const char *name);
176 183
177void perf_evsel__init(struct perf_evsel *evsel, 184void perf_evsel__init(struct perf_evsel *evsel,
@@ -228,8 +235,9 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
228 bool use_sample_identifier); 235 bool use_sample_identifier);
229 236
230int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter); 237int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
231int perf_evsel__append_filter(struct perf_evsel *evsel, 238int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
232 const char *op, const char *filter); 239int perf_evsel__append_addr_filter(struct perf_evsel *evsel,
240 const char *filter);
233int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads, 241int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
234 const char *filter); 242 const char *filter);
235int perf_evsel__enable(struct perf_evsel *evsel); 243int perf_evsel__enable(struct perf_evsel *evsel);
@@ -259,6 +267,8 @@ static inline char *perf_evsel__strval(struct perf_evsel *evsel,
259 267
260struct format_field; 268struct format_field;
261 269
270u64 format_field__intval(struct format_field *field, struct perf_sample *sample, bool needs_swap);
271
262struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name); 272struct format_field *perf_evsel__field(struct perf_evsel *evsel, const char *name);
263 273
264#define perf_evsel__match(evsel, t, c) \ 274#define perf_evsel__match(evsel, t, c) \
@@ -351,23 +361,7 @@ static inline bool perf_evsel__is_group_event(struct perf_evsel *evsel)
351 return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1; 361 return perf_evsel__is_group_leader(evsel) && evsel->nr_members > 1;
352} 362}
353 363
354/** 364bool perf_evsel__is_function_event(struct perf_evsel *evsel);
355 * perf_evsel__is_function_event - Return whether given evsel is a function
356 * trace event
357 *
358 * @evsel - evsel selector to be tested
359 *
360 * Return %true if event is function trace event
361 */
362static inline bool perf_evsel__is_function_event(struct perf_evsel *evsel)
363{
364#define FUNCTION_EVENT "ftrace:function"
365
366 return evsel->name &&
367 !strncmp(FUNCTION_EVENT, evsel->name, sizeof(FUNCTION_EVENT));
368
369#undef FUNCTION_EVENT
370}
371 365
372static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel) 366static inline bool perf_evsel__is_bpf_output(struct perf_evsel *evsel)
373{ 367{
@@ -431,4 +425,6 @@ typedef int (*attr__fprintf_f)(FILE *, const char *, const char *, void *);
431int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr, 425int perf_event_attr__fprintf(FILE *fp, struct perf_event_attr *attr,
432 attr__fprintf_f attr__fprintf, void *priv); 426 attr__fprintf_f attr__fprintf, void *priv);
433 427
428char *perf_evsel__env_arch(struct perf_evsel *evsel);
429
434#endif /* __PERF_EVSEL_H */ 430#endif /* __PERF_EVSEL_H */
diff --git a/tools/perf/util/evsel_fprintf.c b/tools/perf/util/evsel_fprintf.c
index 3674e77ad640..662a0a6182e7 100644
--- a/tools/perf/util/evsel_fprintf.c
+++ b/tools/perf/util/evsel_fprintf.c
@@ -122,9 +122,6 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
122 if (!node) 122 if (!node)
123 break; 123 break;
124 124
125 if (node->sym && node->sym->ignore)
126 goto next;
127
128 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 125 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
129 126
130 if (print_ip) 127 if (print_ip)
@@ -158,7 +155,7 @@ int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
158 155
159 if (!print_oneline) 156 if (!print_oneline)
160 printed += fprintf(fp, "\n"); 157 printed += fprintf(fp, "\n");
161next: 158
162 callchain_cursor_advance(cursor); 159 callchain_cursor_advance(cursor);
163 } 160 }
164 } 161 }
@@ -181,7 +178,7 @@ int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
181 if (cursor != NULL) { 178 if (cursor != NULL) {
182 printed += sample__fprintf_callchain(sample, left_alignment, 179 printed += sample__fprintf_callchain(sample, left_alignment,
183 print_opts, cursor, fp); 180 print_opts, cursor, fp);
184 } else if (!(al->sym && al->sym->ignore)) { 181 } else {
185 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " "); 182 printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
186 183
187 if (print_ip) 184 if (print_ip)
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 08852dde1378..85dd0db0a127 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}";
@@ -828,8 +828,7 @@ static int write_group_desc(int fd, struct perf_header *h __maybe_unused,
828 * default get_cpuid(): nothing gets recorded 828 * default get_cpuid(): nothing gets recorded
829 * actual implementation must be in arch/$(ARCH)/util/header.c 829 * actual implementation must be in arch/$(ARCH)/util/header.c
830 */ 830 */
831int __attribute__ ((weak)) get_cpuid(char *buffer __maybe_unused, 831int __weak get_cpuid(char *buffer __maybe_unused, size_t sz __maybe_unused)
832 size_t sz __maybe_unused)
833{ 832{
834 return -1; 833 return -1;
835} 834}
@@ -1306,42 +1305,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, 1305static void print_numa_topology(struct perf_header *ph, int fd __maybe_unused,
1307 FILE *fp) 1306 FILE *fp)
1308{ 1307{
1309 u32 nr, c, i; 1308 int i;
1310 char *str, *tmp; 1309 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 1310
1328 str = tmp + 1; 1311 for (i = 0; i < ph->env.nr_numa_nodes; i++) {
1329 mem_free = strtoull(str, &tmp, 0); 1312 n = &ph->env.numa_nodes[i];
1330 if (*tmp != ':')
1331 goto error;
1332 1313
1333 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB," 1314 fprintf(fp, "# node%u meminfo : total = %"PRIu64" kB,"
1334 " free = %"PRIu64" kB\n", 1315 " free = %"PRIu64" kB\n",
1335 c, mem_total, mem_free); 1316 n->node, n->mem_total, n->mem_free);
1336 1317
1337 str = tmp + 1; 1318 fprintf(fp, "# node%u cpu list : ", n->node);
1338 fprintf(fp, "# node%u cpu list : %s\n", c, str); 1319 cpu_map__fprintf(n->map, fp);
1339
1340 str += strlen(str) + 1;
1341 } 1320 }
1342 return;
1343error:
1344 fprintf(fp, "# numa topology : not available\n");
1345} 1321}
1346 1322
1347static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp) 1323static void print_cpuid(struct perf_header *ph, int fd __maybe_unused, FILE *fp)
@@ -1425,7 +1401,7 @@ static void print_group_desc(struct perf_header *ph, int fd __maybe_unused,
1425 1401
1426 session = container_of(ph, struct perf_session, header); 1402 session = container_of(ph, struct perf_session, header);
1427 1403
1428 evlist__for_each(session->evlist, evsel) { 1404 evlist__for_each_entry(session->evlist, evsel) {
1429 if (perf_evsel__is_group_leader(evsel) && 1405 if (perf_evsel__is_group_leader(evsel) &&
1430 evsel->nr_members > 1) { 1406 evsel->nr_members > 1) {
1431 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "", 1407 fprintf(fp, "# group: %s{%s", evsel->group_name ?: "",
@@ -1703,7 +1679,7 @@ perf_evlist__find_by_index(struct perf_evlist *evlist, int idx)
1703{ 1679{
1704 struct perf_evsel *evsel; 1680 struct perf_evsel *evsel;
1705 1681
1706 evlist__for_each(evlist, evsel) { 1682 evlist__for_each_entry(evlist, evsel) {
1707 if (evsel->idx == idx) 1683 if (evsel->idx == idx)
1708 return evsel; 1684 return evsel;
1709 } 1685 }
@@ -1906,11 +1882,10 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1906 struct perf_header *ph, int fd, 1882 struct perf_header *ph, int fd,
1907 void *data __maybe_unused) 1883 void *data __maybe_unused)
1908{ 1884{
1885 struct numa_node *nodes, *n;
1909 ssize_t ret; 1886 ssize_t ret;
1910 u32 nr, node, i; 1887 u32 nr, i;
1911 char *str; 1888 char *str;
1912 uint64_t mem_total, mem_free;
1913 struct strbuf sb;
1914 1889
1915 /* nr nodes */ 1890 /* nr nodes */
1916 ret = readn(fd, &nr, sizeof(nr)); 1891 ret = readn(fd, &nr, sizeof(nr));
@@ -1921,47 +1896,47 @@ static int process_numa_topology(struct perf_file_section *section __maybe_unuse
1921 nr = bswap_32(nr); 1896 nr = bswap_32(nr);
1922 1897
1923 ph->env.nr_numa_nodes = nr; 1898 ph->env.nr_numa_nodes = nr;
1924 if (strbuf_init(&sb, 256) < 0) 1899 nodes = zalloc(sizeof(*nodes) * nr);
1925 return -1; 1900 if (!nodes)
1901 return -ENOMEM;
1926 1902
1927 for (i = 0; i < nr; i++) { 1903 for (i = 0; i < nr; i++) {
1904 n = &nodes[i];
1905
1928 /* node number */ 1906 /* node number */
1929 ret = readn(fd, &node, sizeof(node)); 1907 ret = readn(fd, &n->node, sizeof(u32));
1930 if (ret != sizeof(node)) 1908 if (ret != sizeof(n->node))
1931 goto error; 1909 goto error;
1932 1910
1933 ret = readn(fd, &mem_total, sizeof(u64)); 1911 ret = readn(fd, &n->mem_total, sizeof(u64));
1934 if (ret != sizeof(u64)) 1912 if (ret != sizeof(u64))
1935 goto error; 1913 goto error;
1936 1914
1937 ret = readn(fd, &mem_free, sizeof(u64)); 1915 ret = readn(fd, &n->mem_free, sizeof(u64));
1938 if (ret != sizeof(u64)) 1916 if (ret != sizeof(u64))
1939 goto error; 1917 goto error;
1940 1918
1941 if (ph->needs_swap) { 1919 if (ph->needs_swap) {
1942 node = bswap_32(node); 1920 n->node = bswap_32(n->node);
1943 mem_total = bswap_64(mem_total); 1921 n->mem_total = bswap_64(n->mem_total);
1944 mem_free = bswap_64(mem_free); 1922 n->mem_free = bswap_64(n->mem_free);
1945 } 1923 }
1946 1924
1947 if (strbuf_addf(&sb, "%u:%"PRIu64":%"PRIu64":",
1948 node, mem_total, mem_free) < 0)
1949 goto error;
1950
1951 str = do_read_string(fd, ph); 1925 str = do_read_string(fd, ph);
1952 if (!str) 1926 if (!str)
1953 goto error; 1927 goto error;
1954 1928
1955 /* include a NULL character at the end */ 1929 n->map = cpu_map__new(str);
1956 if (strbuf_add(&sb, str, strlen(str) + 1) < 0) 1930 if (!n->map)
1957 goto error; 1931 goto error;
1932
1958 free(str); 1933 free(str);
1959 } 1934 }
1960 ph->env.numa_nodes = strbuf_detach(&sb, NULL); 1935 ph->env.numa_nodes = nodes;
1961 return 0; 1936 return 0;
1962 1937
1963error: 1938error:
1964 strbuf_release(&sb); 1939 free(nodes);
1965 return -1; 1940 return -1;
1966} 1941}
1967 1942
@@ -2075,7 +2050,7 @@ static int process_group_desc(struct perf_file_section *section __maybe_unused,
2075 session->evlist->nr_groups = nr_groups; 2050 session->evlist->nr_groups = nr_groups;
2076 2051
2077 i = nr = 0; 2052 i = nr = 0;
2078 evlist__for_each(session->evlist, evsel) { 2053 evlist__for_each_entry(session->evlist, evsel) {
2079 if (evsel->idx == (int) desc[i].leader_idx) { 2054 if (evsel->idx == (int) desc[i].leader_idx) {
2080 evsel->leader = evsel; 2055 evsel->leader = evsel;
2081 /* {anon_group} is a dummy name */ 2056 /* {anon_group} is a dummy name */
@@ -2383,7 +2358,7 @@ int perf_session__write_header(struct perf_session *session,
2383 2358
2384 lseek(fd, sizeof(f_header), SEEK_SET); 2359 lseek(fd, sizeof(f_header), SEEK_SET);
2385 2360
2386 evlist__for_each(session->evlist, evsel) { 2361 evlist__for_each_entry(session->evlist, evsel) {
2387 evsel->id_offset = lseek(fd, 0, SEEK_CUR); 2362 evsel->id_offset = lseek(fd, 0, SEEK_CUR);
2388 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64)); 2363 err = do_write(fd, evsel->id, evsel->ids * sizeof(u64));
2389 if (err < 0) { 2364 if (err < 0) {
@@ -2394,7 +2369,7 @@ int perf_session__write_header(struct perf_session *session,
2394 2369
2395 attr_offset = lseek(fd, 0, SEEK_CUR); 2370 attr_offset = lseek(fd, 0, SEEK_CUR);
2396 2371
2397 evlist__for_each(evlist, evsel) { 2372 evlist__for_each_entry(evlist, evsel) {
2398 f_attr = (struct perf_file_attr){ 2373 f_attr = (struct perf_file_attr){
2399 .attr = evsel->attr, 2374 .attr = evsel->attr,
2400 .ids = { 2375 .ids = {
@@ -2828,7 +2803,7 @@ static int perf_evlist__prepare_tracepoint_events(struct perf_evlist *evlist,
2828{ 2803{
2829 struct perf_evsel *pos; 2804 struct perf_evsel *pos;
2830 2805
2831 evlist__for_each(evlist, pos) { 2806 evlist__for_each_entry(evlist, pos) {
2832 if (pos->attr.type == PERF_TYPE_TRACEPOINT && 2807 if (pos->attr.type == PERF_TYPE_TRACEPOINT &&
2833 perf_evsel__prepare_tracepoint_event(pos, pevent)) 2808 perf_evsel__prepare_tracepoint_event(pos, pevent))
2834 return -1; 2809 return -1;
@@ -3127,7 +3102,7 @@ int perf_event__synthesize_attrs(struct perf_tool *tool,
3127 struct perf_evsel *evsel; 3102 struct perf_evsel *evsel;
3128 int err = 0; 3103 int err = 0;
3129 3104
3130 evlist__for_each(session->evlist, evsel) { 3105 evlist__for_each_entry(session->evlist, evsel) {
3131 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids, 3106 err = perf_event__synthesize_attr(tool, &evsel->attr, evsel->ids,
3132 evsel->id, process); 3107 evsel->id, process);
3133 if (err) { 3108 if (err) {
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d306ca118449..d30109b421ee 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -151,4 +151,5 @@ int write_padded(int fd, const void *bf, size_t count, size_t count_aligned);
151 */ 151 */
152int get_cpuid(char *buffer, size_t sz); 152int get_cpuid(char *buffer, size_t sz);
153 153
154char *get_cpuid_str(void);
154#endif /* __PERF_HEADER_H */ 155#endif /* __PERF_HEADER_H */
diff --git a/tools/perf/util/help-unknown-cmd.c b/tools/perf/util/help-unknown-cmd.c
index d62ccaeeadd6..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"
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index d1f19e0012d4..b02992efb513 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);
@@ -177,8 +177,10 @@ void hists__calc_col_len(struct hists *hists, struct hist_entry *h)
177 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12); 177 hists__new_col_len(hists, HISTC_LOCAL_WEIGHT, 12);
178 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12); 178 hists__new_col_len(hists, HISTC_GLOBAL_WEIGHT, 12);
179 179
180 if (h->srcline) 180 if (h->srcline) {
181 hists__new_col_len(hists, HISTC_SRCLINE, strlen(h->srcline)); 181 len = MAX(strlen(h->srcline), strlen(sort_srcline.se_header));
182 hists__new_col_len(hists, HISTC_SRCLINE, len);
183 }
182 184
183 if (h->srcfile) 185 if (h->srcfile)
184 hists__new_col_len(hists, HISTC_SRCFILE, strlen(h->srcfile)); 186 hists__new_col_len(hists, HISTC_SRCFILE, strlen(h->srcfile));
@@ -352,86 +354,116 @@ void hists__delete_entries(struct hists *hists)
352 * histogram, sorted on item, collects periods 354 * histogram, sorted on item, collects periods
353 */ 355 */
354 356
355static struct hist_entry *hist_entry__new(struct hist_entry *template, 357static int hist_entry__init(struct hist_entry *he,
356 bool sample_self) 358 struct hist_entry *template,
359 bool sample_self)
357{ 360{
358 size_t callchain_size = 0; 361 *he = *template;
359 struct hist_entry *he;
360 362
361 if (symbol_conf.use_callchain) 363 if (symbol_conf.cumulate_callchain) {
362 callchain_size = sizeof(struct callchain_root); 364 he->stat_acc = malloc(sizeof(he->stat));
365 if (he->stat_acc == NULL)
366 return -ENOMEM;
367 memcpy(he->stat_acc, &he->stat, sizeof(he->stat));
368 if (!sample_self)
369 memset(&he->stat, 0, sizeof(he->stat));
370 }
371
372 map__get(he->ms.map);
373
374 if (he->branch_info) {
375 /*
376 * This branch info is (a part of) allocated from
377 * sample__resolve_bstack() and will be freed after
378 * adding new entries. So we need to save a copy.
379 */
380 he->branch_info = malloc(sizeof(*he->branch_info));
381 if (he->branch_info == NULL) {
382 map__zput(he->ms.map);
383 free(he->stat_acc);
384 return -ENOMEM;
385 }
386
387 memcpy(he->branch_info, template->branch_info,
388 sizeof(*he->branch_info));
389
390 map__get(he->branch_info->from.map);
391 map__get(he->branch_info->to.map);
392 }
393
394 if (he->mem_info) {
395 map__get(he->mem_info->iaddr.map);
396 map__get(he->mem_info->daddr.map);
397 }
363 398
364 he = zalloc(sizeof(*he) + callchain_size); 399 if (symbol_conf.use_callchain)
400 callchain_init(he->callchain);
365 401
366 if (he != NULL) { 402 if (he->raw_data) {
367 *he = *template; 403 he->raw_data = memdup(he->raw_data, he->raw_size);
368 404
369 if (symbol_conf.cumulate_callchain) { 405 if (he->raw_data == NULL) {
370 he->stat_acc = malloc(sizeof(he->stat)); 406 map__put(he->ms.map);
371 if (he->stat_acc == NULL) { 407 if (he->branch_info) {
372 free(he); 408 map__put(he->branch_info->from.map);
373 return NULL; 409 map__put(he->branch_info->to.map);
410 free(he->branch_info);
411 }
412 if (he->mem_info) {
413 map__put(he->mem_info->iaddr.map);
414 map__put(he->mem_info->daddr.map);
374 } 415 }
375 memcpy(he->stat_acc, &he->stat, sizeof(he->stat)); 416 free(he->stat_acc);
376 if (!sample_self) 417 return -ENOMEM;
377 memset(&he->stat, 0, sizeof(he->stat));
378 } 418 }
419 }
420 INIT_LIST_HEAD(&he->pairs.node);
421 thread__get(he->thread);
422 he->hroot_in = RB_ROOT;
423 he->hroot_out = RB_ROOT;
379 424
380 map__get(he->ms.map); 425 if (!symbol_conf.report_hierarchy)
426 he->leaf = true;
381 427
382 if (he->branch_info) { 428 return 0;
383 /* 429}
384 * This branch info is (a part of) allocated from
385 * sample__resolve_bstack() and will be freed after
386 * adding new entries. So we need to save a copy.
387 */
388 he->branch_info = malloc(sizeof(*he->branch_info));
389 if (he->branch_info == NULL) {
390 map__zput(he->ms.map);
391 free(he->stat_acc);
392 free(he);
393 return NULL;
394 }
395 430
396 memcpy(he->branch_info, template->branch_info, 431static void *hist_entry__zalloc(size_t size)
397 sizeof(*he->branch_info)); 432{
433 return zalloc(size + sizeof(struct hist_entry));
434}
398 435
399 map__get(he->branch_info->from.map); 436static void hist_entry__free(void *ptr)
400 map__get(he->branch_info->to.map); 437{
401 } 438 free(ptr);
439}
402 440
403 if (he->mem_info) { 441static struct hist_entry_ops default_ops = {
404 map__get(he->mem_info->iaddr.map); 442 .new = hist_entry__zalloc,
405 map__get(he->mem_info->daddr.map); 443 .free = hist_entry__free,
406 } 444};
407 445
408 if (symbol_conf.use_callchain) 446static struct hist_entry *hist_entry__new(struct hist_entry *template,
409 callchain_init(he->callchain); 447 bool sample_self)
448{
449 struct hist_entry_ops *ops = template->ops;
450 size_t callchain_size = 0;
451 struct hist_entry *he;
452 int err = 0;
410 453
411 if (he->raw_data) { 454 if (!ops)
412 he->raw_data = memdup(he->raw_data, he->raw_size); 455 ops = template->ops = &default_ops;
413 456
414 if (he->raw_data == NULL) { 457 if (symbol_conf.use_callchain)
415 map__put(he->ms.map); 458 callchain_size = sizeof(struct callchain_root);
416 if (he->branch_info) {
417 map__put(he->branch_info->from.map);
418 map__put(he->branch_info->to.map);
419 free(he->branch_info);
420 }
421 if (he->mem_info) {
422 map__put(he->mem_info->iaddr.map);
423 map__put(he->mem_info->daddr.map);
424 }
425 free(he->stat_acc);
426 free(he);
427 return NULL;
428 }
429 }
430 INIT_LIST_HEAD(&he->pairs.node);
431 thread__get(he->thread);
432 459
433 if (!symbol_conf.report_hierarchy) 460 he = ops->new(callchain_size);
434 he->leaf = true; 461 if (he) {
462 err = hist_entry__init(he, template, sample_self);
463 if (err) {
464 ops->free(he);
465 he = NULL;
466 }
435 } 467 }
436 468
437 return he; 469 return he;
@@ -531,13 +563,15 @@ out:
531 return he; 563 return he;
532} 564}
533 565
534struct hist_entry *__hists__add_entry(struct hists *hists, 566static struct hist_entry*
535 struct addr_location *al, 567__hists__add_entry(struct hists *hists,
536 struct symbol *sym_parent, 568 struct addr_location *al,
537 struct branch_info *bi, 569 struct symbol *sym_parent,
538 struct mem_info *mi, 570 struct branch_info *bi,
539 struct perf_sample *sample, 571 struct mem_info *mi,
540 bool sample_self) 572 struct perf_sample *sample,
573 bool sample_self,
574 struct hist_entry_ops *ops)
541{ 575{
542 struct hist_entry entry = { 576 struct hist_entry entry = {
543 .thread = al->thread, 577 .thread = al->thread,
@@ -564,11 +598,37 @@ struct hist_entry *__hists__add_entry(struct hists *hists,
564 .transaction = sample->transaction, 598 .transaction = sample->transaction,
565 .raw_data = sample->raw_data, 599 .raw_data = sample->raw_data,
566 .raw_size = sample->raw_size, 600 .raw_size = sample->raw_size,
601 .ops = ops,
567 }; 602 };
568 603
569 return hists__findnew_entry(hists, &entry, al, sample_self); 604 return hists__findnew_entry(hists, &entry, al, sample_self);
570} 605}
571 606
607struct hist_entry *hists__add_entry(struct hists *hists,
608 struct addr_location *al,
609 struct symbol *sym_parent,
610 struct branch_info *bi,
611 struct mem_info *mi,
612 struct perf_sample *sample,
613 bool sample_self)
614{
615 return __hists__add_entry(hists, al, sym_parent, bi, mi,
616 sample, sample_self, NULL);
617}
618
619struct hist_entry *hists__add_entry_ops(struct hists *hists,
620 struct hist_entry_ops *ops,
621 struct addr_location *al,
622 struct symbol *sym_parent,
623 struct branch_info *bi,
624 struct mem_info *mi,
625 struct perf_sample *sample,
626 bool sample_self)
627{
628 return __hists__add_entry(hists, al, sym_parent, bi, mi,
629 sample, sample_self, ops);
630}
631
572static int 632static int
573iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused, 633iter_next_nop_entry(struct hist_entry_iter *iter __maybe_unused,
574 struct addr_location *al __maybe_unused) 634 struct addr_location *al __maybe_unused)
@@ -622,8 +682,8 @@ iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al
622 */ 682 */
623 sample->period = cost; 683 sample->period = cost;
624 684
625 he = __hists__add_entry(hists, al, iter->parent, NULL, mi, 685 he = hists__add_entry(hists, al, iter->parent, NULL, mi,
626 sample, true); 686 sample, true);
627 if (!he) 687 if (!he)
628 return -ENOMEM; 688 return -ENOMEM;
629 689
@@ -727,8 +787,8 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
727 sample->period = 1; 787 sample->period = 1;
728 sample->weight = bi->flags.cycles ? bi->flags.cycles : 1; 788 sample->weight = bi->flags.cycles ? bi->flags.cycles : 1;
729 789
730 he = __hists__add_entry(hists, al, iter->parent, &bi[i], NULL, 790 he = hists__add_entry(hists, al, iter->parent, &bi[i], NULL,
731 sample, true); 791 sample, true);
732 if (he == NULL) 792 if (he == NULL)
733 return -ENOMEM; 793 return -ENOMEM;
734 794
@@ -764,8 +824,8 @@ iter_add_single_normal_entry(struct hist_entry_iter *iter, struct addr_location
764 struct perf_sample *sample = iter->sample; 824 struct perf_sample *sample = iter->sample;
765 struct hist_entry *he; 825 struct hist_entry *he;
766 826
767 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 827 he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
768 sample, true); 828 sample, true);
769 if (he == NULL) 829 if (he == NULL)
770 return -ENOMEM; 830 return -ENOMEM;
771 831
@@ -825,8 +885,8 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
825 struct hist_entry *he; 885 struct hist_entry *he;
826 int err = 0; 886 int err = 0;
827 887
828 he = __hists__add_entry(hists, al, iter->parent, NULL, NULL, 888 he = hists__add_entry(hists, al, iter->parent, NULL, NULL,
829 sample, true); 889 sample, true);
830 if (he == NULL) 890 if (he == NULL)
831 return -ENOMEM; 891 return -ENOMEM;
832 892
@@ -900,8 +960,8 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
900 } 960 }
901 } 961 }
902 962
903 he = __hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL, 963 he = hists__add_entry(evsel__hists(evsel), al, iter->parent, NULL, NULL,
904 sample, false); 964 sample, false);
905 if (he == NULL) 965 if (he == NULL)
906 return -ENOMEM; 966 return -ENOMEM;
907 967
@@ -1043,6 +1103,8 @@ hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
1043 1103
1044void hist_entry__delete(struct hist_entry *he) 1104void hist_entry__delete(struct hist_entry *he)
1045{ 1105{
1106 struct hist_entry_ops *ops = he->ops;
1107
1046 thread__zput(he->thread); 1108 thread__zput(he->thread);
1047 map__zput(he->ms.map); 1109 map__zput(he->ms.map);
1048 1110
@@ -1067,7 +1129,7 @@ void hist_entry__delete(struct hist_entry *he)
1067 free_callchain(he->callchain); 1129 free_callchain(he->callchain);
1068 free(he->trace_output); 1130 free(he->trace_output);
1069 free(he->raw_data); 1131 free(he->raw_data);
1070 free(he); 1132 ops->free(he);
1071} 1133}
1072 1134
1073/* 1135/*
@@ -1081,7 +1143,7 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
1081 struct perf_hpp_fmt *fmt, int printed) 1143 struct perf_hpp_fmt *fmt, int printed)
1082{ 1144{
1083 if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) { 1145 if (!list_is_last(&fmt->list, &he->hists->hpp_list->fields)) {
1084 const int width = fmt->width(fmt, hpp, hists_to_evsel(he->hists)); 1146 const int width = fmt->width(fmt, hpp, he->hists);
1085 if (printed < width) { 1147 if (printed < width) {
1086 advance_hpp(hpp, printed); 1148 advance_hpp(hpp, printed);
1087 printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " "); 1149 printed = scnprintf(hpp->buf, hpp->size, "%-*s", width - printed, " ");
@@ -1614,7 +1676,7 @@ static void __hists__insert_output_entry(struct rb_root *entries,
1614} 1676}
1615 1677
1616static void output_resort(struct hists *hists, struct ui_progress *prog, 1678static void output_resort(struct hists *hists, struct ui_progress *prog,
1617 bool use_callchain) 1679 bool use_callchain, hists__resort_cb_t cb)
1618{ 1680{
1619 struct rb_root *root; 1681 struct rb_root *root;
1620 struct rb_node *next; 1682 struct rb_node *next;
@@ -1653,6 +1715,9 @@ static void output_resort(struct hists *hists, struct ui_progress *prog,
1653 n = rb_entry(next, struct hist_entry, rb_node_in); 1715 n = rb_entry(next, struct hist_entry, rb_node_in);
1654 next = rb_next(&n->rb_node_in); 1716 next = rb_next(&n->rb_node_in);
1655 1717
1718 if (cb && cb(n))
1719 continue;
1720
1656 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain); 1721 __hists__insert_output_entry(&hists->entries, n, min_callchain_hits, use_callchain);
1657 hists__inc_stats(hists, n); 1722 hists__inc_stats(hists, n);
1658 1723
@@ -1673,12 +1738,18 @@ void perf_evsel__output_resort(struct perf_evsel *evsel, struct ui_progress *pro
1673 else 1738 else
1674 use_callchain = symbol_conf.use_callchain; 1739 use_callchain = symbol_conf.use_callchain;
1675 1740
1676 output_resort(evsel__hists(evsel), prog, use_callchain); 1741 output_resort(evsel__hists(evsel), prog, use_callchain, NULL);
1677} 1742}
1678 1743
1679void hists__output_resort(struct hists *hists, struct ui_progress *prog) 1744void hists__output_resort(struct hists *hists, struct ui_progress *prog)
1680{ 1745{
1681 output_resort(hists, prog, symbol_conf.use_callchain); 1746 output_resort(hists, prog, symbol_conf.use_callchain, NULL);
1747}
1748
1749void hists__output_resort_cb(struct hists *hists, struct ui_progress *prog,
1750 hists__resort_cb_t cb)
1751{
1752 output_resort(hists, prog, symbol_conf.use_callchain, cb);
1682} 1753}
1683 1754
1684static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd) 1755static bool can_goto_child(struct hist_entry *he, enum hierarchy_move_dir hmd)
@@ -2082,6 +2153,50 @@ out:
2082 return he; 2153 return he;
2083} 2154}
2084 2155
2156static struct hist_entry *add_dummy_hierarchy_entry(struct hists *hists,
2157 struct rb_root *root,
2158 struct hist_entry *pair)
2159{
2160 struct rb_node **p;
2161 struct rb_node *parent = NULL;
2162 struct hist_entry *he;
2163 struct perf_hpp_fmt *fmt;
2164
2165 p = &root->rb_node;
2166 while (*p != NULL) {
2167 int64_t cmp = 0;
2168
2169 parent = *p;
2170 he = rb_entry(parent, struct hist_entry, rb_node_in);
2171
2172 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
2173 cmp = fmt->collapse(fmt, he, pair);
2174 if (cmp)
2175 break;
2176 }
2177 if (!cmp)
2178 goto out;
2179
2180 if (cmp < 0)
2181 p = &parent->rb_left;
2182 else
2183 p = &parent->rb_right;
2184 }
2185
2186 he = hist_entry__new(pair, true);
2187 if (he) {
2188 rb_link_node(&he->rb_node_in, parent, p);
2189 rb_insert_color(&he->rb_node_in, root);
2190
2191 he->dummy = true;
2192 he->hists = hists;
2193 memset(&he->stat, 0, sizeof(he->stat));
2194 hists__inc_stats(hists, he);
2195 }
2196out:
2197 return he;
2198}
2199
2085static struct hist_entry *hists__find_entry(struct hists *hists, 2200static struct hist_entry *hists__find_entry(struct hists *hists,
2086 struct hist_entry *he) 2201 struct hist_entry *he)
2087{ 2202{
@@ -2107,6 +2222,51 @@ static struct hist_entry *hists__find_entry(struct hists *hists,
2107 return NULL; 2222 return NULL;
2108} 2223}
2109 2224
2225static struct hist_entry *hists__find_hierarchy_entry(struct rb_root *root,
2226 struct hist_entry *he)
2227{
2228 struct rb_node *n = root->rb_node;
2229
2230 while (n) {
2231 struct hist_entry *iter;
2232 struct perf_hpp_fmt *fmt;
2233 int64_t cmp = 0;
2234
2235 iter = rb_entry(n, struct hist_entry, rb_node_in);
2236 perf_hpp_list__for_each_sort_list(he->hpp_list, fmt) {
2237 cmp = fmt->collapse(fmt, iter, he);
2238 if (cmp)
2239 break;
2240 }
2241
2242 if (cmp < 0)
2243 n = n->rb_left;
2244 else if (cmp > 0)
2245 n = n->rb_right;
2246 else
2247 return iter;
2248 }
2249
2250 return NULL;
2251}
2252
2253static void hists__match_hierarchy(struct rb_root *leader_root,
2254 struct rb_root *other_root)
2255{
2256 struct rb_node *nd;
2257 struct hist_entry *pos, *pair;
2258
2259 for (nd = rb_first(leader_root); nd; nd = rb_next(nd)) {
2260 pos = rb_entry(nd, struct hist_entry, rb_node_in);
2261 pair = hists__find_hierarchy_entry(other_root, pos);
2262
2263 if (pair) {
2264 hist_entry__add_pair(pair, pos);
2265 hists__match_hierarchy(&pos->hroot_in, &pair->hroot_in);
2266 }
2267 }
2268}
2269
2110/* 2270/*
2111 * Look for pairs to link to the leader buckets (hist_entries): 2271 * Look for pairs to link to the leader buckets (hist_entries):
2112 */ 2272 */
@@ -2116,6 +2276,12 @@ void hists__match(struct hists *leader, struct hists *other)
2116 struct rb_node *nd; 2276 struct rb_node *nd;
2117 struct hist_entry *pos, *pair; 2277 struct hist_entry *pos, *pair;
2118 2278
2279 if (symbol_conf.report_hierarchy) {
2280 /* hierarchy report always collapses entries */
2281 return hists__match_hierarchy(&leader->entries_collapsed,
2282 &other->entries_collapsed);
2283 }
2284
2119 if (hists__has(leader, need_collapse)) 2285 if (hists__has(leader, need_collapse))
2120 root = &leader->entries_collapsed; 2286 root = &leader->entries_collapsed;
2121 else 2287 else
@@ -2130,6 +2296,50 @@ void hists__match(struct hists *leader, struct hists *other)
2130 } 2296 }
2131} 2297}
2132 2298
2299static int hists__link_hierarchy(struct hists *leader_hists,
2300 struct hist_entry *parent,
2301 struct rb_root *leader_root,
2302 struct rb_root *other_root)
2303{
2304 struct rb_node *nd;
2305 struct hist_entry *pos, *leader;
2306
2307 for (nd = rb_first(other_root); nd; nd = rb_next(nd)) {
2308 pos = rb_entry(nd, struct hist_entry, rb_node_in);
2309
2310 if (hist_entry__has_pairs(pos)) {
2311 bool found = false;
2312
2313 list_for_each_entry(leader, &pos->pairs.head, pairs.node) {
2314 if (leader->hists == leader_hists) {
2315 found = true;
2316 break;
2317 }
2318 }
2319 if (!found)
2320 return -1;
2321 } else {
2322 leader = add_dummy_hierarchy_entry(leader_hists,
2323 leader_root, pos);
2324 if (leader == NULL)
2325 return -1;
2326
2327 /* do not point parent in the pos */
2328 leader->parent_he = parent;
2329
2330 hist_entry__add_pair(pos, leader);
2331 }
2332
2333 if (!pos->leaf) {
2334 if (hists__link_hierarchy(leader_hists, leader,
2335 &leader->hroot_in,
2336 &pos->hroot_in) < 0)
2337 return -1;
2338 }
2339 }
2340 return 0;
2341}
2342
2133/* 2343/*
2134 * Look for entries in the other hists that are not present in the leader, if 2344 * Look for entries in the other hists that are not present in the leader, if
2135 * we find them, just add a dummy entry on the leader hists, with period=0, 2345 * we find them, just add a dummy entry on the leader hists, with period=0,
@@ -2141,6 +2351,13 @@ int hists__link(struct hists *leader, struct hists *other)
2141 struct rb_node *nd; 2351 struct rb_node *nd;
2142 struct hist_entry *pos, *pair; 2352 struct hist_entry *pos, *pair;
2143 2353
2354 if (symbol_conf.report_hierarchy) {
2355 /* hierarchy report always collapses entries */
2356 return hists__link_hierarchy(leader, NULL,
2357 &leader->entries_collapsed,
2358 &other->entries_collapsed);
2359 }
2360
2144 if (hists__has(other, need_collapse)) 2361 if (hists__has(other, need_collapse))
2145 root = &other->entries_collapsed; 2362 root = &other->entries_collapsed;
2146 else 2363 else
@@ -2199,7 +2416,7 @@ size_t perf_evlist__fprintf_nr_events(struct perf_evlist *evlist, FILE *fp)
2199 struct perf_evsel *pos; 2416 struct perf_evsel *pos;
2200 size_t ret = 0; 2417 size_t ret = 0;
2201 2418
2202 evlist__for_each(evlist, pos) { 2419 evlist__for_each_entry(evlist, pos) {
2203 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos)); 2420 ret += fprintf(fp, "%s stats:\n", perf_evsel__name(pos));
2204 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); 2421 ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp);
2205 } 2422 }
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index 7b54ccf1b737..9928fed8bc59 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
@@ -120,13 +121,23 @@ extern const struct hist_iter_ops hist_iter_branch;
120extern const struct hist_iter_ops hist_iter_mem; 121extern const struct hist_iter_ops hist_iter_mem;
121extern const struct hist_iter_ops hist_iter_cumulative; 122extern const struct hist_iter_ops hist_iter_cumulative;
122 123
123struct hist_entry *__hists__add_entry(struct hists *hists, 124struct hist_entry *hists__add_entry(struct hists *hists,
124 struct addr_location *al, 125 struct addr_location *al,
125 struct symbol *parent, 126 struct symbol *parent,
126 struct branch_info *bi, 127 struct branch_info *bi,
127 struct mem_info *mi, 128 struct mem_info *mi,
128 struct perf_sample *sample, 129 struct perf_sample *sample,
129 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
130int 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,
131 int max_stack_depth, void *arg); 142 int max_stack_depth, void *arg);
132 143
@@ -142,8 +153,12 @@ int hist_entry__snprintf_alignment(struct hist_entry *he, struct perf_hpp *hpp,
142 struct perf_hpp_fmt *fmt, int printed); 153 struct perf_hpp_fmt *fmt, int printed);
143void hist_entry__delete(struct hist_entry *he); 154void hist_entry__delete(struct hist_entry *he);
144 155
156typedef int (*hists__resort_cb_t)(struct hist_entry *he);
157
145void 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);
146void 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);
147int hists__collapse_resort(struct hists *hists, struct ui_progress *prog); 162int hists__collapse_resort(struct hists *hists, struct ui_progress *prog);
148 163
149void 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);
@@ -159,7 +174,8 @@ void events_stats__inc(struct events_stats *stats, u32 type);
159size_t events_stats__fprintf(struct events_stats *stats, FILE *fp); 174size_t events_stats__fprintf(struct events_stats *stats, FILE *fp);
160 175
161size_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,
162 int max_cols, float min_pcnt, FILE *fp); 177 int max_cols, float min_pcnt, FILE *fp,
178 bool use_callchain);
163size_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);
164 180
165void hists__filter_by_dso(struct hists *hists); 181void hists__filter_by_dso(struct hists *hists);
@@ -214,9 +230,9 @@ struct perf_hpp {
214struct perf_hpp_fmt { 230struct perf_hpp_fmt {
215 const char *name; 231 const char *name;
216 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 232 int (*header)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
217 struct perf_evsel *evsel); 233 struct hists *hists, int line, int *span);
218 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 234 int (*width)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
219 struct perf_evsel *evsel); 235 struct hists *hists);
220 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 236 int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
221 struct hist_entry *he); 237 struct hist_entry *he);
222 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 238 int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
@@ -243,6 +259,7 @@ struct perf_hpp_list {
243 struct list_head fields; 259 struct list_head fields;
244 struct list_head sorts; 260 struct list_head sorts;
245 261
262 int nr_header_lines;
246 int need_collapse; 263 int need_collapse;
247 int parent; 264 int parent;
248 int sym; 265 int sym;
@@ -351,6 +368,7 @@ static inline bool perf_hpp__should_skip(struct perf_hpp_fmt *format,
351void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists); 368void perf_hpp__reset_width(struct perf_hpp_fmt *fmt, struct hists *hists);
352void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists); 369void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists);
353void perf_hpp__set_user_width(const char *width_list_str); 370void perf_hpp__set_user_width(const char *width_list_str);
371void hists__reset_column_width(struct hists *hists);
354 372
355typedef u64 (*hpp_field_fn)(struct hist_entry *he); 373typedef u64 (*hpp_field_fn)(struct hist_entry *he);
356typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front); 374typedef int (*hpp_callback_fn)(struct perf_hpp *hpp, bool front);
@@ -467,5 +485,10 @@ static inline struct rb_node *rb_hierarchy_next(struct rb_node *node)
467#define HIERARCHY_INDENT 3 485#define HIERARCHY_INDENT 3
468 486
469bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit); 487bool hist_entry__has_hierarchy_children(struct hist_entry *he, float limit);
488int hpp_color_scnprintf(struct perf_hpp *hpp, const char *fmt, ...);
489int __hpp__slsmg_color_printf(struct perf_hpp *hpp, const char *fmt, ...);
490int __hist_entry__snprintf(struct hist_entry *he, struct perf_hpp *hpp,
491 struct perf_hpp_list *hpp_list);
492int hists__fprintf_headers(struct hists *hists, FILE *fp);
470 493
471#endif /* __PERF_HIST_H */ 494#endif /* __PERF_HIST_H */
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/dwarf-regs.h b/tools/perf/util/include/dwarf-regs.h
index 07c644ed64c4..43bfd8da7919 100644
--- a/tools/perf/util/include/dwarf-regs.h
+++ b/tools/perf/util/include/dwarf-regs.h
@@ -3,6 +3,12 @@
3 3
4#ifdef HAVE_DWARF_SUPPORT 4#ifdef HAVE_DWARF_SUPPORT
5const char *get_arch_regstr(unsigned int n); 5const char *get_arch_regstr(unsigned int n);
6/*
7 * get_dwarf_regstr - Returns ftrace register string from DWARF regnum
8 * n: DWARF register number
9 * machine: ELF machine signature (EM_*)
10 */
11const char *get_dwarf_regstr(unsigned int n, unsigned int machine);
6#endif 12#endif
7 13
8#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET 14#ifdef HAVE_ARCH_REGS_QUERY_REGISTER_OFFSET
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 9df996085563..f545ec1e758a 100644
--- a/tools/perf/util/intel-bts.c
+++ b/tools/perf/util/intel-bts.c
@@ -346,7 +346,7 @@ static int intel_bts_get_next_insn(struct intel_bts_queue *btsq, u64 ip)
346 goto out_put; 346 goto out_put;
347 347
348 /* Load maps to ensure dso->is_64_bit has been updated */ 348 /* Load maps to ensure dso->is_64_bit has been updated */
349 map__load(al.map, machine->symbol_filter); 349 map__load(al.map);
350 350
351 x86_64 = al.map->dso->is_64_bit; 351 x86_64 = al.map->dso->is_64_bit;
352 352
@@ -422,7 +422,8 @@ static int intel_bts_get_branch_type(struct intel_bts_queue *btsq,
422} 422}
423 423
424static int intel_bts_process_buffer(struct intel_bts_queue *btsq, 424static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
425 struct auxtrace_buffer *buffer) 425 struct auxtrace_buffer *buffer,
426 struct thread *thread)
426{ 427{
427 struct branch *branch; 428 struct branch *branch;
428 size_t sz, bsz = sizeof(struct branch); 429 size_t sz, bsz = sizeof(struct branch);
@@ -444,6 +445,12 @@ static int intel_bts_process_buffer(struct intel_bts_queue *btsq,
444 if (!branch->from && !branch->to) 445 if (!branch->from && !branch->to)
445 continue; 446 continue;
446 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);
447 if (filter && !(filter & btsq->sample_flags)) 454 if (filter && !(filter & btsq->sample_flags))
448 continue; 455 continue;
449 err = intel_bts_synth_branch_sample(btsq, branch); 456 err = intel_bts_synth_branch_sample(btsq, branch);
@@ -507,12 +514,13 @@ static int intel_bts_process_queue(struct intel_bts_queue *btsq, u64 *timestamp)
507 goto out_put; 514 goto out_put;
508 } 515 }
509 516
510 if (!btsq->bts->synth_opts.callchain && thread && 517 if (!btsq->bts->synth_opts.callchain &&
518 !btsq->bts->synth_opts.thread_stack && thread &&
511 (!old_buffer || btsq->bts->sampling_mode || 519 (!old_buffer || btsq->bts->sampling_mode ||
512 (btsq->bts->snapshot_mode && !buffer->consecutive))) 520 (btsq->bts->snapshot_mode && !buffer->consecutive)))
513 thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1); 521 thread_stack__set_trace_nr(thread, buffer->buffer_nr + 1);
514 522
515 err = intel_bts_process_buffer(btsq, buffer); 523 err = intel_bts_process_buffer(btsq, buffer, thread);
516 524
517 auxtrace_buffer__drop_data(buffer); 525 auxtrace_buffer__drop_data(buffer);
518 526
@@ -777,7 +785,7 @@ static int intel_bts_synth_events(struct intel_bts *bts,
777 u64 id; 785 u64 id;
778 int err; 786 int err;
779 787
780 evlist__for_each(evlist, evsel) { 788 evlist__for_each_entry(evlist, evsel) {
781 if (evsel->attr.type == bts->pmu_type && evsel->ids) { 789 if (evsel->attr.type == bts->pmu_type && evsel->ids) {
782 found = true; 790 found = true;
783 break; 791 break;
@@ -905,10 +913,14 @@ int intel_bts_process_auxtrace_info(union perf_event *event,
905 if (dump_trace) 913 if (dump_trace)
906 return 0; 914 return 0;
907 915
908 if (session->itrace_synth_opts && session->itrace_synth_opts->set) 916 if (session->itrace_synth_opts && session->itrace_synth_opts->set) {
909 bts->synth_opts = *session->itrace_synth_opts; 917 bts->synth_opts = *session->itrace_synth_opts;
910 else 918 } else {
911 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 }
912 924
913 if (bts->synth_opts.calls) 925 if (bts->synth_opts.calls)
914 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 9c8f15da86ce..16c06d3ae577 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.c
@@ -80,6 +80,7 @@ struct intel_pt_decoder {
80 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 80 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
81 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 81 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
82 uint64_t max_insn_cnt, void *data); 82 uint64_t max_insn_cnt, void *data);
83 bool (*pgd_ip)(uint64_t ip, void *data);
83 void *data; 84 void *data;
84 struct intel_pt_state state; 85 struct intel_pt_state state;
85 const unsigned char *buf; 86 const unsigned char *buf;
@@ -89,6 +90,7 @@ struct intel_pt_decoder {
89 bool pge; 90 bool pge;
90 bool have_tma; 91 bool have_tma;
91 bool have_cyc; 92 bool have_cyc;
93 bool fixup_last_mtc;
92 uint64_t pos; 94 uint64_t pos;
93 uint64_t last_ip; 95 uint64_t last_ip;
94 uint64_t ip; 96 uint64_t ip;
@@ -123,8 +125,6 @@ struct intel_pt_decoder {
123 bool have_calc_cyc_to_tsc; 125 bool have_calc_cyc_to_tsc;
124 int exec_mode; 126 int exec_mode;
125 unsigned int insn_bytes; 127 unsigned int insn_bytes;
126 uint64_t sign_bit;
127 uint64_t sign_bits;
128 uint64_t period; 128 uint64_t period;
129 enum intel_pt_period_type period_type; 129 enum intel_pt_period_type period_type;
130 uint64_t tot_insn_cnt; 130 uint64_t tot_insn_cnt;
@@ -188,12 +188,10 @@ struct intel_pt_decoder *intel_pt_decoder_new(struct intel_pt_params *params)
188 188
189 decoder->get_trace = params->get_trace; 189 decoder->get_trace = params->get_trace;
190 decoder->walk_insn = params->walk_insn; 190 decoder->walk_insn = params->walk_insn;
191 decoder->pgd_ip = params->pgd_ip;
191 decoder->data = params->data; 192 decoder->data = params->data;
192 decoder->return_compression = params->return_compression; 193 decoder->return_compression = params->return_compression;
193 194
194 decoder->sign_bit = (uint64_t)1 << 47;
195 decoder->sign_bits = ~(((uint64_t)1 << 48) - 1);
196
197 decoder->period = params->period; 195 decoder->period = params->period;
198 decoder->period_type = params->period_type; 196 decoder->period_type = params->period_type;
199 197
@@ -362,21 +360,30 @@ int intel_pt__strerror(int code, char *buf, size_t buflen)
362 return 0; 360 return 0;
363} 361}
364 362
365static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder, 363static uint64_t intel_pt_calc_ip(const struct intel_pt_pkt *packet,
366 const struct intel_pt_pkt *packet,
367 uint64_t last_ip) 364 uint64_t last_ip)
368{ 365{
369 uint64_t ip; 366 uint64_t ip;
370 367
371 switch (packet->count) { 368 switch (packet->count) {
372 case 2: 369 case 1:
373 ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) | 370 ip = (last_ip & (uint64_t)0xffffffffffff0000ULL) |
374 packet->payload; 371 packet->payload;
375 break; 372 break;
376 case 4: 373 case 2:
377 ip = (last_ip & (uint64_t)0xffffffff00000000ULL) | 374 ip = (last_ip & (uint64_t)0xffffffff00000000ULL) |
378 packet->payload; 375 packet->payload;
379 break; 376 break;
377 case 3:
378 ip = packet->payload;
379 /* Sign-extend 6-byte ip */
380 if (ip & (uint64_t)0x800000000000ULL)
381 ip |= (uint64_t)0xffff000000000000ULL;
382 break;
383 case 4:
384 ip = (last_ip & (uint64_t)0xffff000000000000ULL) |
385 packet->payload;
386 break;
380 case 6: 387 case 6:
381 ip = packet->payload; 388 ip = packet->payload;
382 break; 389 break;
@@ -384,16 +391,12 @@ static uint64_t intel_pt_calc_ip(struct intel_pt_decoder *decoder,
384 return 0; 391 return 0;
385 } 392 }
386 393
387 if (ip & decoder->sign_bit)
388 return ip | decoder->sign_bits;
389
390 return ip; 394 return ip;
391} 395}
392 396
393static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder) 397static inline void intel_pt_set_last_ip(struct intel_pt_decoder *decoder)
394{ 398{
395 decoder->last_ip = intel_pt_calc_ip(decoder, &decoder->packet, 399 decoder->last_ip = intel_pt_calc_ip(&decoder->packet, decoder->last_ip);
396 decoder->last_ip);
397} 400}
398 401
399static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder) 402static inline void intel_pt_set_ip(struct intel_pt_decoder *decoder)
@@ -584,10 +587,31 @@ struct intel_pt_calc_cyc_to_tsc_info {
584 uint64_t tsc_timestamp; 587 uint64_t tsc_timestamp;
585 uint64_t timestamp; 588 uint64_t timestamp;
586 bool have_tma; 589 bool have_tma;
590 bool fixup_last_mtc;
587 bool from_mtc; 591 bool from_mtc;
588 double cbr_cyc_to_tsc; 592 double cbr_cyc_to_tsc;
589}; 593};
590 594
595/*
596 * MTC provides a 8-bit slice of CTC but the TMA packet only provides the lower
597 * 16 bits of CTC. If mtc_shift > 8 then some of the MTC bits are not in the CTC
598 * provided by the TMA packet. Fix-up the last_mtc calculated from the TMA
599 * packet by copying the missing bits from the current MTC assuming the least
600 * difference between the two, and that the current MTC comes after last_mtc.
601 */
602static void intel_pt_fixup_last_mtc(uint32_t mtc, int mtc_shift,
603 uint32_t *last_mtc)
604{
605 uint32_t first_missing_bit = 1U << (16 - mtc_shift);
606 uint32_t mask = ~(first_missing_bit - 1);
607
608 *last_mtc |= mtc & mask;
609 if (*last_mtc >= mtc) {
610 *last_mtc -= first_missing_bit;
611 *last_mtc &= 0xff;
612 }
613}
614
591static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info) 615static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
592{ 616{
593 struct intel_pt_decoder *decoder = pkt_info->decoder; 617 struct intel_pt_decoder *decoder = pkt_info->decoder;
@@ -617,6 +641,11 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
617 return 0; 641 return 0;
618 642
619 mtc = pkt_info->packet.payload; 643 mtc = pkt_info->packet.payload;
644 if (decoder->mtc_shift > 8 && data->fixup_last_mtc) {
645 data->fixup_last_mtc = false;
646 intel_pt_fixup_last_mtc(mtc, decoder->mtc_shift,
647 &data->last_mtc);
648 }
620 if (mtc > data->last_mtc) 649 if (mtc > data->last_mtc)
621 mtc_delta = mtc - data->last_mtc; 650 mtc_delta = mtc - data->last_mtc;
622 else 651 else
@@ -685,6 +714,7 @@ static int intel_pt_calc_cyc_cb(struct intel_pt_pkt_info *pkt_info)
685 714
686 data->ctc_delta = 0; 715 data->ctc_delta = 0;
687 data->have_tma = true; 716 data->have_tma = true;
717 data->fixup_last_mtc = true;
688 718
689 return 0; 719 return 0;
690 720
@@ -751,6 +781,7 @@ static void intel_pt_calc_cyc_to_tsc(struct intel_pt_decoder *decoder,
751 .tsc_timestamp = decoder->tsc_timestamp, 781 .tsc_timestamp = decoder->tsc_timestamp,
752 .timestamp = decoder->timestamp, 782 .timestamp = decoder->timestamp,
753 .have_tma = decoder->have_tma, 783 .have_tma = decoder->have_tma,
784 .fixup_last_mtc = decoder->fixup_last_mtc,
754 .from_mtc = from_mtc, 785 .from_mtc = from_mtc,
755 .cbr_cyc_to_tsc = 0, 786 .cbr_cyc_to_tsc = 0,
756 }; 787 };
@@ -1008,6 +1039,19 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1008 int err; 1039 int err;
1009 1040
1010 err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0); 1041 err = intel_pt_walk_insn(decoder, &intel_pt_insn, 0);
1042 if (err == INTEL_PT_RETURN &&
1043 decoder->pgd_ip &&
1044 decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
1045 (decoder->state.type & INTEL_PT_BRANCH) &&
1046 decoder->pgd_ip(decoder->state.to_ip, decoder->data)) {
1047 /* Unconditional branch leaving filter region */
1048 decoder->no_progress = 0;
1049 decoder->pge = false;
1050 decoder->continuous_period = false;
1051 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1052 decoder->state.to_ip = 0;
1053 return 0;
1054 }
1011 if (err == INTEL_PT_RETURN) 1055 if (err == INTEL_PT_RETURN)
1012 return 0; 1056 return 0;
1013 if (err) 1057 if (err)
@@ -1036,6 +1080,21 @@ static int intel_pt_walk_tip(struct intel_pt_decoder *decoder)
1036 } 1080 }
1037 1081
1038 if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) { 1082 if (intel_pt_insn.branch == INTEL_PT_BR_CONDITIONAL) {
1083 uint64_t to_ip = decoder->ip + intel_pt_insn.length +
1084 intel_pt_insn.rel;
1085
1086 if (decoder->pgd_ip &&
1087 decoder->pkt_state == INTEL_PT_STATE_TIP_PGD &&
1088 decoder->pgd_ip(to_ip, decoder->data)) {
1089 /* Conditional branch leaving filter region */
1090 decoder->pge = false;
1091 decoder->continuous_period = false;
1092 decoder->pkt_state = INTEL_PT_STATE_IN_SYNC;
1093 decoder->ip = to_ip;
1094 decoder->state.from_ip = decoder->ip;
1095 decoder->state.to_ip = 0;
1096 return 0;
1097 }
1039 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch", 1098 intel_pt_log_at("ERROR: Conditional branch when expecting indirect branch",
1040 decoder->ip); 1099 decoder->ip);
1041 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC; 1100 decoder->pkt_state = INTEL_PT_STATE_ERR_RESYNC;
@@ -1241,6 +1300,7 @@ static void intel_pt_calc_tma(struct intel_pt_decoder *decoder)
1241 } 1300 }
1242 decoder->ctc_delta = 0; 1301 decoder->ctc_delta = 0;
1243 decoder->have_tma = true; 1302 decoder->have_tma = true;
1303 decoder->fixup_last_mtc = true;
1244 intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x CTC rem %#x\n", 1304 intel_pt_log("CTC timestamp " x64_fmt " last MTC %#x CTC rem %#x\n",
1245 decoder->ctc_timestamp, decoder->last_mtc, ctc_rem); 1305 decoder->ctc_timestamp, decoder->last_mtc, ctc_rem);
1246} 1306}
@@ -1255,6 +1315,12 @@ static void intel_pt_calc_mtc_timestamp(struct intel_pt_decoder *decoder)
1255 1315
1256 mtc = decoder->packet.payload; 1316 mtc = decoder->packet.payload;
1257 1317
1318 if (decoder->mtc_shift > 8 && decoder->fixup_last_mtc) {
1319 decoder->fixup_last_mtc = false;
1320 intel_pt_fixup_last_mtc(mtc, decoder->mtc_shift,
1321 &decoder->last_mtc);
1322 }
1323
1258 if (mtc > decoder->last_mtc) 1324 if (mtc > decoder->last_mtc)
1259 mtc_delta = mtc - decoder->last_mtc; 1325 mtc_delta = mtc - decoder->last_mtc;
1260 else 1326 else
@@ -1323,6 +1389,8 @@ static void intel_pt_calc_cyc_timestamp(struct intel_pt_decoder *decoder)
1323 timestamp, decoder->timestamp); 1389 timestamp, decoder->timestamp);
1324 else 1390 else
1325 decoder->timestamp = timestamp; 1391 decoder->timestamp = timestamp;
1392
1393 decoder->timestamp_insn_cnt = 0;
1326} 1394}
1327 1395
1328/* Walk PSB+ packets when already in sync. */ 1396/* Walk PSB+ packets when already in sync. */
@@ -1657,6 +1725,12 @@ next:
1657 } 1725 }
1658} 1726}
1659 1727
1728static inline bool intel_pt_have_ip(struct intel_pt_decoder *decoder)
1729{
1730 return decoder->last_ip || decoder->packet.count == 0 ||
1731 decoder->packet.count == 3 || decoder->packet.count == 6;
1732}
1733
1660/* Walk PSB+ packets to get in sync. */ 1734/* Walk PSB+ packets to get in sync. */
1661static int intel_pt_walk_psb(struct intel_pt_decoder *decoder) 1735static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1662{ 1736{
@@ -1677,8 +1751,7 @@ static int intel_pt_walk_psb(struct intel_pt_decoder *decoder)
1677 1751
1678 case INTEL_PT_FUP: 1752 case INTEL_PT_FUP:
1679 decoder->pge = true; 1753 decoder->pge = true;
1680 if (decoder->last_ip || decoder->packet.count == 6 || 1754 if (intel_pt_have_ip(decoder)) {
1681 decoder->packet.count == 0) {
1682 uint64_t current_ip = decoder->ip; 1755 uint64_t current_ip = decoder->ip;
1683 1756
1684 intel_pt_set_ip(decoder); 1757 intel_pt_set_ip(decoder);
@@ -1767,8 +1840,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1767 case INTEL_PT_TIP_PGE: 1840 case INTEL_PT_TIP_PGE:
1768 case INTEL_PT_TIP: 1841 case INTEL_PT_TIP:
1769 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD; 1842 decoder->pge = decoder->packet.type != INTEL_PT_TIP_PGD;
1770 if (decoder->last_ip || decoder->packet.count == 6 || 1843 if (intel_pt_have_ip(decoder))
1771 decoder->packet.count == 0)
1772 intel_pt_set_ip(decoder); 1844 intel_pt_set_ip(decoder);
1773 if (decoder->ip) 1845 if (decoder->ip)
1774 return 0; 1846 return 0;
@@ -1776,9 +1848,7 @@ static int intel_pt_walk_to_ip(struct intel_pt_decoder *decoder)
1776 1848
1777 case INTEL_PT_FUP: 1849 case INTEL_PT_FUP:
1778 if (decoder->overflow) { 1850 if (decoder->overflow) {
1779 if (decoder->last_ip || 1851 if (intel_pt_have_ip(decoder))
1780 decoder->packet.count == 6 ||
1781 decoder->packet.count == 0)
1782 intel_pt_set_ip(decoder); 1852 intel_pt_set_ip(decoder);
1783 if (decoder->ip) 1853 if (decoder->ip)
1784 return 0; 1854 return 0;
diff --git a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
index 02c38fec1c37..89399985fa4d 100644
--- a/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
+++ b/tools/perf/util/intel-pt-decoder/intel-pt-decoder.h
@@ -83,6 +83,7 @@ struct intel_pt_params {
83 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn, 83 int (*walk_insn)(struct intel_pt_insn *intel_pt_insn,
84 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip, 84 uint64_t *insn_cnt_ptr, uint64_t *ip, uint64_t to_ip,
85 uint64_t max_insn_cnt, void *data); 85 uint64_t max_insn_cnt, void *data);
86 bool (*pgd_ip)(uint64_t ip, void *data);
86 void *data; 87 void *data;
87 bool return_compression; 88 bool return_compression;
88 uint64_t period; 89 uint64_t period;
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 137196990012..dc041d4368c8 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"
@@ -102,6 +103,9 @@ struct intel_pt {
102 unsigned max_non_turbo_ratio; 103 unsigned max_non_turbo_ratio;
103 104
104 unsigned long num_events; 105 unsigned long num_events;
106
107 char *filter;
108 struct addr_filters filts;
105}; 109};
106 110
107enum switch_state { 111enum switch_state {
@@ -240,7 +244,7 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
240 } 244 }
241 245
242 queue = &ptq->pt->queues.queue_array[ptq->queue_nr]; 246 queue = &ptq->pt->queues.queue_array[ptq->queue_nr];
243 247next:
244 buffer = auxtrace_buffer__next(queue, buffer); 248 buffer = auxtrace_buffer__next(queue, buffer);
245 if (!buffer) { 249 if (!buffer) {
246 if (old_buffer) 250 if (old_buffer)
@@ -263,9 +267,6 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
263 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer)) 267 intel_pt_do_fix_overlap(ptq->pt, old_buffer, buffer))
264 return -ENOMEM; 268 return -ENOMEM;
265 269
266 if (old_buffer)
267 auxtrace_buffer__drop_data(old_buffer);
268
269 if (buffer->use_data) { 270 if (buffer->use_data) {
270 b->len = buffer->use_size; 271 b->len = buffer->use_size;
271 b->buf = buffer->use_data; 272 b->buf = buffer->use_data;
@@ -275,6 +276,16 @@ static int intel_pt_get_trace(struct intel_pt_buffer *b, void *data)
275 } 276 }
276 b->ref_timestamp = buffer->reference; 277 b->ref_timestamp = buffer->reference;
277 278
279 /*
280 * If in snapshot mode and the buffer has no usable data, get next
281 * buffer and again check overlap against old_buffer.
282 */
283 if (ptq->pt->snapshot_mode && !b->len)
284 goto next;
285
286 if (old_buffer)
287 auxtrace_buffer__drop_data(old_buffer);
288
278 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode && 289 if (!old_buffer || ptq->pt->sampling_mode || (ptq->pt->snapshot_mode &&
279 !buffer->consecutive)) { 290 !buffer->consecutive)) {
280 b->consecutive = false; 291 b->consecutive = false;
@@ -476,7 +487,7 @@ static int intel_pt_walk_next_insn(struct intel_pt_insn *intel_pt_insn,
476 start_ip = *ip; 487 start_ip = *ip;
477 488
478 /* Load maps to ensure dso->is_64_bit has been updated */ 489 /* Load maps to ensure dso->is_64_bit has been updated */
479 map__load(al.map, machine->symbol_filter); 490 map__load(al.map);
480 491
481 x86_64 = al.map->dso->is_64_bit; 492 x86_64 = al.map->dso->is_64_bit;
482 493
@@ -540,6 +551,76 @@ out_no_cache:
540 return 0; 551 return 0;
541} 552}
542 553
554static bool intel_pt_match_pgd_ip(struct intel_pt *pt, uint64_t ip,
555 uint64_t offset, const char *filename)
556{
557 struct addr_filter *filt;
558 bool have_filter = false;
559 bool hit_tracestop = false;
560 bool hit_filter = false;
561
562 list_for_each_entry(filt, &pt->filts.head, list) {
563 if (filt->start)
564 have_filter = true;
565
566 if ((filename && !filt->filename) ||
567 (!filename && filt->filename) ||
568 (filename && strcmp(filename, filt->filename)))
569 continue;
570
571 if (!(offset >= filt->addr && offset < filt->addr + filt->size))
572 continue;
573
574 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s hit filter: %s offset %#"PRIx64" size %#"PRIx64"\n",
575 ip, offset, filename ? filename : "[kernel]",
576 filt->start ? "filter" : "stop",
577 filt->addr, filt->size);
578
579 if (filt->start)
580 hit_filter = true;
581 else
582 hit_tracestop = true;
583 }
584
585 if (!hit_tracestop && !hit_filter)
586 intel_pt_log("TIP.PGD ip %#"PRIx64" offset %#"PRIx64" in %s is not in a filter region\n",
587 ip, offset, filename ? filename : "[kernel]");
588
589 return hit_tracestop || (have_filter && !hit_filter);
590}
591
592static int __intel_pt_pgd_ip(uint64_t ip, void *data)
593{
594 struct intel_pt_queue *ptq = data;
595 struct thread *thread;
596 struct addr_location al;
597 u8 cpumode;
598 u64 offset;
599
600 if (ip >= ptq->pt->kernel_start)
601 return intel_pt_match_pgd_ip(ptq->pt, ip, ip, NULL);
602
603 cpumode = PERF_RECORD_MISC_USER;
604
605 thread = ptq->thread;
606 if (!thread)
607 return -EINVAL;
608
609 thread__find_addr_map(thread, cpumode, MAP__FUNCTION, ip, &al);
610 if (!al.map || !al.map->dso)
611 return -EINVAL;
612
613 offset = al.map->map_ip(al.map, ip);
614
615 return intel_pt_match_pgd_ip(ptq->pt, ip, offset,
616 al.map->dso->long_name);
617}
618
619static bool intel_pt_pgd_ip(uint64_t ip, void *data)
620{
621 return __intel_pt_pgd_ip(ip, data) > 0;
622}
623
543static bool intel_pt_get_config(struct intel_pt *pt, 624static bool intel_pt_get_config(struct intel_pt *pt,
544 struct perf_event_attr *attr, u64 *config) 625 struct perf_event_attr *attr, u64 *config)
545{ 626{
@@ -556,7 +637,7 @@ static bool intel_pt_exclude_kernel(struct intel_pt *pt)
556{ 637{
557 struct perf_evsel *evsel; 638 struct perf_evsel *evsel;
558 639
559 evlist__for_each(pt->session->evlist, evsel) { 640 evlist__for_each_entry(pt->session->evlist, evsel) {
560 if (intel_pt_get_config(pt, &evsel->attr, NULL) && 641 if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
561 !evsel->attr.exclude_kernel) 642 !evsel->attr.exclude_kernel)
562 return false; 643 return false;
@@ -572,7 +653,7 @@ static bool intel_pt_return_compression(struct intel_pt *pt)
572 if (!pt->noretcomp_bit) 653 if (!pt->noretcomp_bit)
573 return true; 654 return true;
574 655
575 evlist__for_each(pt->session->evlist, evsel) { 656 evlist__for_each_entry(pt->session->evlist, evsel) {
576 if (intel_pt_get_config(pt, &evsel->attr, &config) && 657 if (intel_pt_get_config(pt, &evsel->attr, &config) &&
577 (config & pt->noretcomp_bit)) 658 (config & pt->noretcomp_bit))
578 return false; 659 return false;
@@ -592,7 +673,7 @@ static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
592 for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++) 673 for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++)
593 config >>= 1; 674 config >>= 1;
594 675
595 evlist__for_each(pt->session->evlist, evsel) { 676 evlist__for_each_entry(pt->session->evlist, evsel) {
596 if (intel_pt_get_config(pt, &evsel->attr, &config)) 677 if (intel_pt_get_config(pt, &evsel->attr, &config))
597 return (config & pt->mtc_freq_bits) >> shift; 678 return (config & pt->mtc_freq_bits) >> shift;
598 } 679 }
@@ -608,7 +689,7 @@ static bool intel_pt_timeless_decoding(struct intel_pt *pt)
608 if (!pt->tsc_bit || !pt->cap_user_time_zero) 689 if (!pt->tsc_bit || !pt->cap_user_time_zero)
609 return true; 690 return true;
610 691
611 evlist__for_each(pt->session->evlist, evsel) { 692 evlist__for_each_entry(pt->session->evlist, evsel) {
612 if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME)) 693 if (!(evsel->attr.sample_type & PERF_SAMPLE_TIME))
613 return true; 694 return true;
614 if (intel_pt_get_config(pt, &evsel->attr, &config)) { 695 if (intel_pt_get_config(pt, &evsel->attr, &config)) {
@@ -625,7 +706,7 @@ static bool intel_pt_tracing_kernel(struct intel_pt *pt)
625{ 706{
626 struct perf_evsel *evsel; 707 struct perf_evsel *evsel;
627 708
628 evlist__for_each(pt->session->evlist, evsel) { 709 evlist__for_each_entry(pt->session->evlist, evsel) {
629 if (intel_pt_get_config(pt, &evsel->attr, NULL) && 710 if (intel_pt_get_config(pt, &evsel->attr, NULL) &&
630 !evsel->attr.exclude_kernel) 711 !evsel->attr.exclude_kernel)
631 return true; 712 return true;
@@ -642,7 +723,7 @@ static bool intel_pt_have_tsc(struct intel_pt *pt)
642 if (!pt->tsc_bit) 723 if (!pt->tsc_bit)
643 return false; 724 return false;
644 725
645 evlist__for_each(pt->session->evlist, evsel) { 726 evlist__for_each_entry(pt->session->evlist, evsel) {
646 if (intel_pt_get_config(pt, &evsel->attr, &config)) { 727 if (intel_pt_get_config(pt, &evsel->attr, &config)) {
647 if (config & pt->tsc_bit) 728 if (config & pt->tsc_bit)
648 have_tsc = true; 729 have_tsc = true;
@@ -716,6 +797,9 @@ static struct intel_pt_queue *intel_pt_alloc_queue(struct intel_pt *pt,
716 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n; 797 params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
717 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d; 798 params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
718 799
800 if (pt->filts.cnt > 0)
801 params.pgd_ip = intel_pt_pgd_ip;
802
719 if (pt->synth_opts.instructions) { 803 if (pt->synth_opts.instructions) {
720 if (pt->synth_opts.period) { 804 if (pt->synth_opts.period) {
721 switch (pt->synth_opts.period_type) { 805 switch (pt->synth_opts.period_type) {
@@ -1233,7 +1317,7 @@ static int intel_pt_sample(struct intel_pt_queue *ptq)
1233 if (!(state->type & INTEL_PT_BRANCH)) 1317 if (!(state->type & INTEL_PT_BRANCH))
1234 return 0; 1318 return 0;
1235 1319
1236 if (pt->synth_opts.callchain) 1320 if (pt->synth_opts.callchain || pt->synth_opts.thread_stack)
1237 thread_stack__event(ptq->thread, ptq->flags, state->from_ip, 1321 thread_stack__event(ptq->thread, ptq->flags, state->from_ip,
1238 state->to_ip, ptq->insn_len, 1322 state->to_ip, ptq->insn_len,
1239 state->trace_nr); 1323 state->trace_nr);
@@ -1293,7 +1377,7 @@ static u64 intel_pt_switch_ip(struct intel_pt *pt, u64 *ptss_ip)
1293 if (!map) 1377 if (!map)
1294 return 0; 1378 return 0;
1295 1379
1296 if (map__load(map, machine->symbol_filter)) 1380 if (map__load(map))
1297 return 0; 1381 return 0;
1298 1382
1299 start = dso__first_symbol(map->dso, MAP__FUNCTION); 1383 start = dso__first_symbol(map->dso, MAP__FUNCTION);
@@ -1766,6 +1850,8 @@ static void intel_pt_free(struct perf_session *session)
1766 intel_pt_free_events(session); 1850 intel_pt_free_events(session);
1767 session->auxtrace = NULL; 1851 session->auxtrace = NULL;
1768 thread__put(pt->unknown_thread); 1852 thread__put(pt->unknown_thread);
1853 addr_filters__exit(&pt->filts);
1854 zfree(&pt->filter);
1769 free(pt); 1855 free(pt);
1770} 1856}
1771 1857
@@ -1850,7 +1936,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1850 u64 id; 1936 u64 id;
1851 int err; 1937 int err;
1852 1938
1853 evlist__for_each(evlist, evsel) { 1939 evlist__for_each_entry(evlist, evsel) {
1854 if (evsel->attr.type == pt->pmu_type && evsel->ids) { 1940 if (evsel->attr.type == pt->pmu_type && evsel->ids) {
1855 found = true; 1941 found = true;
1856 break; 1942 break;
@@ -1930,7 +2016,7 @@ static int intel_pt_synth_events(struct intel_pt *pt,
1930 pt->sample_transactions = true; 2016 pt->sample_transactions = true;
1931 pt->transactions_id = id; 2017 pt->transactions_id = id;
1932 id += 1; 2018 id += 1;
1933 evlist__for_each(evlist, evsel) { 2019 evlist__for_each_entry(evlist, evsel) {
1934 if (evsel->id && evsel->id[0] == pt->transactions_id) { 2020 if (evsel->id && evsel->id[0] == pt->transactions_id) {
1935 if (evsel->name) 2021 if (evsel->name)
1936 zfree(&evsel->name); 2022 zfree(&evsel->name);
@@ -1968,7 +2054,7 @@ static struct perf_evsel *intel_pt_find_sched_switch(struct perf_evlist *evlist)
1968{ 2054{
1969 struct perf_evsel *evsel; 2055 struct perf_evsel *evsel;
1970 2056
1971 evlist__for_each_reverse(evlist, evsel) { 2057 evlist__for_each_entry_reverse(evlist, evsel) {
1972 const char *name = perf_evsel__name(evsel); 2058 const char *name = perf_evsel__name(evsel);
1973 2059
1974 if (!strcmp(name, "sched:sched_switch")) 2060 if (!strcmp(name, "sched:sched_switch"))
@@ -1982,7 +2068,7 @@ static bool intel_pt_find_switch(struct perf_evlist *evlist)
1982{ 2068{
1983 struct perf_evsel *evsel; 2069 struct perf_evsel *evsel;
1984 2070
1985 evlist__for_each(evlist, evsel) { 2071 evlist__for_each_entry(evlist, evsel) {
1986 if (evsel->attr.context_switch) 2072 if (evsel->attr.context_switch)
1987 return true; 2073 return true;
1988 } 2074 }
@@ -2015,6 +2101,8 @@ static const char * const intel_pt_info_fmts[] = {
2015 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n", 2101 [INTEL_PT_TSC_CTC_N] = " TSC:CTC numerator %"PRIu64"\n",
2016 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n", 2102 [INTEL_PT_TSC_CTC_D] = " TSC:CTC denominator %"PRIu64"\n",
2017 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n", 2103 [INTEL_PT_CYC_BIT] = " CYC bit %#"PRIx64"\n",
2104 [INTEL_PT_MAX_NONTURBO_RATIO] = " Max non-turbo ratio %"PRIu64"\n",
2105 [INTEL_PT_FILTER_STR_LEN] = " Filter string len. %"PRIu64"\n",
2018}; 2106};
2019 2107
2020static void intel_pt_print_info(u64 *arr, int start, int finish) 2108static void intel_pt_print_info(u64 *arr, int start, int finish)
@@ -2028,12 +2116,28 @@ static void intel_pt_print_info(u64 *arr, int start, int finish)
2028 fprintf(stdout, intel_pt_info_fmts[i], arr[i]); 2116 fprintf(stdout, intel_pt_info_fmts[i], arr[i]);
2029} 2117}
2030 2118
2119static void intel_pt_print_info_str(const char *name, const char *str)
2120{
2121 if (!dump_trace)
2122 return;
2123
2124 fprintf(stdout, " %-20s%s\n", name, str ? str : "");
2125}
2126
2127static bool intel_pt_has(struct auxtrace_info_event *auxtrace_info, int pos)
2128{
2129 return auxtrace_info->header.size >=
2130 sizeof(struct auxtrace_info_event) + (sizeof(u64) * (pos + 1));
2131}
2132
2031int intel_pt_process_auxtrace_info(union perf_event *event, 2133int intel_pt_process_auxtrace_info(union perf_event *event,
2032 struct perf_session *session) 2134 struct perf_session *session)
2033{ 2135{
2034 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info; 2136 struct auxtrace_info_event *auxtrace_info = &event->auxtrace_info;
2035 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS; 2137 size_t min_sz = sizeof(u64) * INTEL_PT_PER_CPU_MMAPS;
2036 struct intel_pt *pt; 2138 struct intel_pt *pt;
2139 void *info_end;
2140 u64 *info;
2037 int err; 2141 int err;
2038 2142
2039 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) + 2143 if (auxtrace_info->header.size < sizeof(struct auxtrace_info_event) +
@@ -2044,6 +2148,8 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2044 if (!pt) 2148 if (!pt)
2045 return -ENOMEM; 2149 return -ENOMEM;
2046 2150
2151 addr_filters__init(&pt->filts);
2152
2047 perf_config(intel_pt_perf_config, pt); 2153 perf_config(intel_pt_perf_config, pt);
2048 2154
2049 err = auxtrace_queues__init(&pt->queues); 2155 err = auxtrace_queues__init(&pt->queues);
@@ -2068,8 +2174,7 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2068 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE, 2174 intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
2069 INTEL_PT_PER_CPU_MMAPS); 2175 INTEL_PT_PER_CPU_MMAPS);
2070 2176
2071 if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) + 2177 if (intel_pt_has(auxtrace_info, INTEL_PT_CYC_BIT)) {
2072 (sizeof(u64) * INTEL_PT_CYC_BIT)) {
2073 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT]; 2178 pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
2074 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS]; 2179 pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
2075 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N]; 2180 pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
@@ -2079,6 +2184,54 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2079 INTEL_PT_CYC_BIT); 2184 INTEL_PT_CYC_BIT);
2080 } 2185 }
2081 2186
2187 if (intel_pt_has(auxtrace_info, INTEL_PT_MAX_NONTURBO_RATIO)) {
2188 pt->max_non_turbo_ratio =
2189 auxtrace_info->priv[INTEL_PT_MAX_NONTURBO_RATIO];
2190 intel_pt_print_info(&auxtrace_info->priv[0],
2191 INTEL_PT_MAX_NONTURBO_RATIO,
2192 INTEL_PT_MAX_NONTURBO_RATIO);
2193 }
2194
2195 info = &auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN] + 1;
2196 info_end = (void *)info + auxtrace_info->header.size;
2197
2198 if (intel_pt_has(auxtrace_info, INTEL_PT_FILTER_STR_LEN)) {
2199 size_t len;
2200
2201 len = auxtrace_info->priv[INTEL_PT_FILTER_STR_LEN];
2202 intel_pt_print_info(&auxtrace_info->priv[0],
2203 INTEL_PT_FILTER_STR_LEN,
2204 INTEL_PT_FILTER_STR_LEN);
2205 if (len) {
2206 const char *filter = (const char *)info;
2207
2208 len = roundup(len + 1, 8);
2209 info += len >> 3;
2210 if ((void *)info > info_end) {
2211 pr_err("%s: bad filter string length\n", __func__);
2212 err = -EINVAL;
2213 goto err_free_queues;
2214 }
2215 pt->filter = memdup(filter, len);
2216 if (!pt->filter) {
2217 err = -ENOMEM;
2218 goto err_free_queues;
2219 }
2220 if (session->header.needs_swap)
2221 mem_bswap_64(pt->filter, len);
2222 if (pt->filter[len - 1]) {
2223 pr_err("%s: filter string not null terminated\n", __func__);
2224 err = -EINVAL;
2225 goto err_free_queues;
2226 }
2227 err = addr_filters__parse_bare_filter(&pt->filts,
2228 filter);
2229 if (err)
2230 goto err_free_queues;
2231 }
2232 intel_pt_print_info_str("Filter string", pt->filter);
2233 }
2234
2082 pt->timeless_decoding = intel_pt_timeless_decoding(pt); 2235 pt->timeless_decoding = intel_pt_timeless_decoding(pt);
2083 pt->have_tsc = intel_pt_have_tsc(pt); 2236 pt->have_tsc = intel_pt_have_tsc(pt);
2084 pt->sampling_mode = false; 2237 pt->sampling_mode = false;
@@ -2120,11 +2273,13 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2120 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist); 2273 pt->switch_evsel = intel_pt_find_sched_switch(session->evlist);
2121 if (!pt->switch_evsel) { 2274 if (!pt->switch_evsel) {
2122 pr_err("%s: missing sched_switch event\n", __func__); 2275 pr_err("%s: missing sched_switch event\n", __func__);
2276 err = -EINVAL;
2123 goto err_delete_thread; 2277 goto err_delete_thread;
2124 } 2278 }
2125 } else if (pt->have_sched_switch == 2 && 2279 } else if (pt->have_sched_switch == 2 &&
2126 !intel_pt_find_switch(session->evlist)) { 2280 !intel_pt_find_switch(session->evlist)) {
2127 pr_err("%s: missing context_switch attribute flag\n", __func__); 2281 pr_err("%s: missing context_switch attribute flag\n", __func__);
2282 err = -EINVAL;
2128 goto err_delete_thread; 2283 goto err_delete_thread;
2129 } 2284 }
2130 2285
@@ -2136,6 +2291,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2136 pt->synth_opts.branches = false; 2291 pt->synth_opts.branches = false;
2137 pt->synth_opts.callchain = true; 2292 pt->synth_opts.callchain = true;
2138 } 2293 }
2294 if (session->itrace_synth_opts)
2295 pt->synth_opts.thread_stack =
2296 session->itrace_synth_opts->thread_stack;
2139 } 2297 }
2140 2298
2141 if (pt->synth_opts.log) 2299 if (pt->synth_opts.log)
@@ -2145,7 +2303,9 @@ int intel_pt_process_auxtrace_info(union perf_event *event,
2145 if (pt->tc.time_mult) { 2303 if (pt->tc.time_mult) {
2146 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000); 2304 u64 tsc_freq = intel_pt_ns_to_ticks(pt, 1000000000);
2147 2305
2148 pt->max_non_turbo_ratio = (tsc_freq + 50000000) / 100000000; 2306 if (!pt->max_non_turbo_ratio)
2307 pt->max_non_turbo_ratio =
2308 (tsc_freq + 50000000) / 100000000;
2149 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq); 2309 intel_pt_log("TSC frequency %"PRIu64"\n", tsc_freq);
2150 intel_pt_log("Maximum non-turbo ratio %u\n", 2310 intel_pt_log("Maximum non-turbo ratio %u\n",
2151 pt->max_non_turbo_ratio); 2311 pt->max_non_turbo_ratio);
@@ -2189,6 +2349,8 @@ err_free_queues:
2189 auxtrace_queues__free(&pt->queues); 2349 auxtrace_queues__free(&pt->queues);
2190 session->auxtrace = NULL; 2350 session->auxtrace = NULL;
2191err_free: 2351err_free:
2352 addr_filters__exit(&pt->filts);
2353 zfree(&pt->filter);
2192 free(pt); 2354 free(pt);
2193 return err; 2355 return err;
2194} 2356}
diff --git a/tools/perf/util/intel-pt.h b/tools/perf/util/intel-pt.h
index 0065949df693..e13b14e5a37b 100644
--- a/tools/perf/util/intel-pt.h
+++ b/tools/perf/util/intel-pt.h
@@ -34,11 +34,11 @@ enum {
34 INTEL_PT_TSC_CTC_N, 34 INTEL_PT_TSC_CTC_N,
35 INTEL_PT_TSC_CTC_D, 35 INTEL_PT_TSC_CTC_D,
36 INTEL_PT_CYC_BIT, 36 INTEL_PT_CYC_BIT,
37 INTEL_PT_MAX_NONTURBO_RATIO,
38 INTEL_PT_FILTER_STR_LEN,
37 INTEL_PT_AUXTRACE_PRIV_MAX, 39 INTEL_PT_AUXTRACE_PRIV_MAX,
38}; 40};
39 41
40#define INTEL_PT_AUXTRACE_PRIV_SIZE (INTEL_PT_AUXTRACE_PRIV_MAX * sizeof(u64))
41
42struct auxtrace_record; 42struct auxtrace_record;
43struct perf_tool; 43struct perf_tool;
44union perf_event; 44union perf_event;
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 86afe9618bb0..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>
@@ -108,7 +109,7 @@ jit_validate_events(struct perf_session *session)
108 /* 109 /*
109 * check that all events use CLOCK_MONOTONIC 110 * check that all events use CLOCK_MONOTONIC
110 */ 111 */
111 evlist__for_each(session->evlist, evsel) { 112 evlist__for_each_entry(session->evlist, evsel) {
112 if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC) 113 if (evsel->attr.use_clockid == 0 || evsel->attr.clockid != CLOCK_MONOTONIC)
113 return -1; 114 return -1;
114 } 115 }
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/lzma.c b/tools/perf/util/lzma.c
index 95a1acb61245..9ddea5cecd94 100644
--- a/tools/perf/util/lzma.c
+++ b/tools/perf/util/lzma.c
@@ -29,6 +29,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
29 lzma_action action = LZMA_RUN; 29 lzma_action action = LZMA_RUN;
30 lzma_stream strm = LZMA_STREAM_INIT; 30 lzma_stream strm = LZMA_STREAM_INIT;
31 lzma_ret ret; 31 lzma_ret ret;
32 int err = -1;
32 33
33 u8 buf_in[BUFSIZE]; 34 u8 buf_in[BUFSIZE];
34 u8 buf_out[BUFSIZE]; 35 u8 buf_out[BUFSIZE];
@@ -45,7 +46,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
45 if (ret != LZMA_OK) { 46 if (ret != LZMA_OK) {
46 pr_err("lzma: lzma_stream_decoder failed %s (%d)\n", 47 pr_err("lzma: lzma_stream_decoder failed %s (%d)\n",
47 lzma_strerror(ret), ret); 48 lzma_strerror(ret), ret);
48 return -1; 49 goto err_fclose;
49 } 50 }
50 51
51 strm.next_in = NULL; 52 strm.next_in = NULL;
@@ -60,7 +61,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
60 61
61 if (ferror(infile)) { 62 if (ferror(infile)) {
62 pr_err("lzma: read error: %s\n", strerror(errno)); 63 pr_err("lzma: read error: %s\n", strerror(errno));
63 return -1; 64 goto err_fclose;
64 } 65 }
65 66
66 if (feof(infile)) 67 if (feof(infile))
@@ -74,7 +75,7 @@ int lzma_decompress_to_file(const char *input, int output_fd)
74 75
75 if (writen(output_fd, buf_out, write_size) != write_size) { 76 if (writen(output_fd, buf_out, write_size) != write_size) {
76 pr_err("lzma: write error: %s\n", strerror(errno)); 77 pr_err("lzma: write error: %s\n", strerror(errno));
77 return -1; 78 goto err_fclose;
78 } 79 }
79 80
80 strm.next_out = buf_out; 81 strm.next_out = buf_out;
@@ -83,13 +84,15 @@ int lzma_decompress_to_file(const char *input, int output_fd)
83 84
84 if (ret != LZMA_OK) { 85 if (ret != LZMA_OK) {
85 if (ret == LZMA_STREAM_END) 86 if (ret == LZMA_STREAM_END)
86 return 0; 87 break;
87 88
88 pr_err("lzma: failed %s\n", lzma_strerror(ret)); 89 pr_err("lzma: failed %s\n", lzma_strerror(ret));
89 return -1; 90 goto err_fclose;
90 } 91 }
91 } 92 }
92 93
94 err = 0;
95err_fclose:
93 fclose(infile); 96 fclose(infile);
94 return 0; 97 return err;
95} 98}
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index b1772180c820..df85b9efd80f 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -41,7 +41,6 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
41 41
42 machine->pid = pid; 42 machine->pid = pid;
43 43
44 machine->symbol_filter = NULL;
45 machine->id_hdr_size = 0; 44 machine->id_hdr_size = 0;
46 machine->kptr_restrict_warned = false; 45 machine->kptr_restrict_warned = false;
47 machine->comm_exec = false; 46 machine->comm_exec = false;
@@ -138,15 +137,16 @@ void machine__exit(struct machine *machine)
138 137
139void machine__delete(struct machine *machine) 138void machine__delete(struct machine *machine)
140{ 139{
141 machine__exit(machine); 140 if (machine) {
142 free(machine); 141 machine__exit(machine);
142 free(machine);
143 }
143} 144}
144 145
145void machines__init(struct machines *machines) 146void machines__init(struct machines *machines)
146{ 147{
147 machine__init(&machines->host, "", HOST_KERNEL_ID); 148 machine__init(&machines->host, "", HOST_KERNEL_ID);
148 machines->guests = RB_ROOT; 149 machines->guests = RB_ROOT;
149 machines->symbol_filter = NULL;
150} 150}
151 151
152void machines__exit(struct machines *machines) 152void machines__exit(struct machines *machines)
@@ -170,8 +170,6 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
170 return NULL; 170 return NULL;
171 } 171 }
172 172
173 machine->symbol_filter = machines->symbol_filter;
174
175 while (*p != NULL) { 173 while (*p != NULL) {
176 parent = *p; 174 parent = *p;
177 pos = rb_entry(parent, struct machine, rb_node); 175 pos = rb_entry(parent, struct machine, rb_node);
@@ -187,21 +185,6 @@ struct machine *machines__add(struct machines *machines, pid_t pid,
187 return machine; 185 return machine;
188} 186}
189 187
190void machines__set_symbol_filter(struct machines *machines,
191 symbol_filter_t symbol_filter)
192{
193 struct rb_node *nd;
194
195 machines->symbol_filter = symbol_filter;
196 machines->host.symbol_filter = symbol_filter;
197
198 for (nd = rb_first(&machines->guests); nd; nd = rb_next(nd)) {
199 struct machine *machine = rb_entry(nd, struct machine, rb_node);
200
201 machine->symbol_filter = symbol_filter;
202 }
203}
204
205void machines__set_comm_exec(struct machines *machines, bool comm_exec) 188void machines__set_comm_exec(struct machines *machines, bool comm_exec)
206{ 189{
207 struct rb_node *nd; 190 struct rb_node *nd;
@@ -914,10 +897,10 @@ int machines__create_kernel_maps(struct machines *machines, pid_t pid)
914} 897}
915 898
916int __machine__load_kallsyms(struct machine *machine, const char *filename, 899int __machine__load_kallsyms(struct machine *machine, const char *filename,
917 enum map_type type, bool no_kcore, symbol_filter_t filter) 900 enum map_type type, bool no_kcore)
918{ 901{
919 struct map *map = machine__kernel_map(machine); 902 struct map *map = machine__kernel_map(machine);
920 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore, filter); 903 int ret = __dso__load_kallsyms(map->dso, filename, map, no_kcore);
921 904
922 if (ret > 0) { 905 if (ret > 0) {
923 dso__set_loaded(map->dso, type); 906 dso__set_loaded(map->dso, type);
@@ -933,16 +916,15 @@ int __machine__load_kallsyms(struct machine *machine, const char *filename,
933} 916}
934 917
935int machine__load_kallsyms(struct machine *machine, const char *filename, 918int machine__load_kallsyms(struct machine *machine, const char *filename,
936 enum map_type type, symbol_filter_t filter) 919 enum map_type type)
937{ 920{
938 return __machine__load_kallsyms(machine, filename, type, false, filter); 921 return __machine__load_kallsyms(machine, filename, type, false);
939} 922}
940 923
941int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 924int machine__load_vmlinux_path(struct machine *machine, enum map_type type)
942 symbol_filter_t filter)
943{ 925{
944 struct map *map = machine__kernel_map(machine); 926 struct map *map = machine__kernel_map(machine);
945 int ret = dso__load_vmlinux_path(map->dso, map, filter); 927 int ret = dso__load_vmlinux_path(map->dso, map);
946 928
947 if (ret > 0) 929 if (ret > 0)
948 dso__set_loaded(map->dso, type); 930 dso__set_loaded(map->dso, type);
@@ -1091,12 +1073,20 @@ static int machine__set_modules_path(struct machine *machine)
1091 1073
1092 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0); 1074 return map_groups__set_modules_path_dir(&machine->kmaps, modules_path, 0);
1093} 1075}
1076int __weak arch__fix_module_text_start(u64 *start __maybe_unused,
1077 const char *name __maybe_unused)
1078{
1079 return 0;
1080}
1094 1081
1095static int machine__create_module(void *arg, const char *name, u64 start) 1082static int machine__create_module(void *arg, const char *name, u64 start)
1096{ 1083{
1097 struct machine *machine = arg; 1084 struct machine *machine = arg;
1098 struct map *map; 1085 struct map *map;
1099 1086
1087 if (arch__fix_module_text_start(&start, name) < 0)
1088 return -1;
1089
1100 map = machine__findnew_module_map(machine, start, name); 1090 map = machine__findnew_module_map(machine, start, name);
1101 if (map == NULL) 1091 if (map == NULL)
1102 return -1; 1092 return -1;
@@ -1303,7 +1293,7 @@ static int machine__process_kernel_mmap_event(struct machine *machine,
1303 /* 1293 /*
1304 * preload dso of guest kernel and modules 1294 * preload dso of guest kernel and modules
1305 */ 1295 */
1306 dso__load(kernel, machine__kernel_map(machine), NULL); 1296 dso__load(kernel, machine__kernel_map(machine));
1307 } 1297 }
1308 } 1298 }
1309 return 0; 1299 return 0;
@@ -1353,11 +1343,16 @@ int machine__process_mmap2_event(struct machine *machine,
1353 if (map == NULL) 1343 if (map == NULL)
1354 goto out_problem_map; 1344 goto out_problem_map;
1355 1345
1356 thread__insert_map(thread, map); 1346 ret = thread__insert_map(thread, map);
1347 if (ret)
1348 goto out_problem_insert;
1349
1357 thread__put(thread); 1350 thread__put(thread);
1358 map__put(map); 1351 map__put(map);
1359 return 0; 1352 return 0;
1360 1353
1354out_problem_insert:
1355 map__put(map);
1361out_problem_map: 1356out_problem_map:
1362 thread__put(thread); 1357 thread__put(thread);
1363out_problem: 1358out_problem:
@@ -1403,11 +1398,16 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1403 if (map == NULL) 1398 if (map == NULL)
1404 goto out_problem_map; 1399 goto out_problem_map;
1405 1400
1406 thread__insert_map(thread, map); 1401 ret = thread__insert_map(thread, map);
1402 if (ret)
1403 goto out_problem_insert;
1404
1407 thread__put(thread); 1405 thread__put(thread);
1408 map__put(map); 1406 map__put(map);
1409 return 0; 1407 return 0;
1410 1408
1409out_problem_insert:
1410 map__put(map);
1411out_problem_map: 1411out_problem_map:
1412 thread__put(thread); 1412 thread__put(thread);
1413out_problem: 1413out_problem:
@@ -1745,9 +1745,8 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1745 int max_stack) 1745 int max_stack)
1746{ 1746{
1747 struct ip_callchain *chain = sample->callchain; 1747 struct ip_callchain *chain = sample->callchain;
1748 int chain_nr = min(max_stack, (int)chain->nr); 1748 int chain_nr = min(max_stack, (int)chain->nr), i;
1749 u8 cpumode = PERF_RECORD_MISC_USER; 1749 u8 cpumode = PERF_RECORD_MISC_USER;
1750 int i, j, err;
1751 u64 ip; 1750 u64 ip;
1752 1751
1753 for (i = 0; i < chain_nr; i++) { 1752 for (i = 0; i < chain_nr; i++) {
@@ -1758,7 +1757,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1758 /* LBR only affects the user callchain */ 1757 /* LBR only affects the user callchain */
1759 if (i != chain_nr) { 1758 if (i != chain_nr) {
1760 struct branch_stack *lbr_stack = sample->branch_stack; 1759 struct branch_stack *lbr_stack = sample->branch_stack;
1761 int lbr_nr = lbr_stack->nr; 1760 int lbr_nr = lbr_stack->nr, j;
1762 /* 1761 /*
1763 * LBR callstack can only get user call chain. 1762 * LBR callstack can only get user call chain.
1764 * The mix_chain_nr is kernel call chain 1763 * The mix_chain_nr is kernel call chain
@@ -1772,6 +1771,7 @@ static int resolve_lbr_callchain_sample(struct thread *thread,
1772 int mix_chain_nr = i + 1 + lbr_nr + 1; 1771 int mix_chain_nr = i + 1 + lbr_nr + 1;
1773 1772
1774 for (j = 0; j < mix_chain_nr; j++) { 1773 for (j = 0; j < mix_chain_nr; j++) {
1774 int err;
1775 if (callchain_param.order == ORDER_CALLEE) { 1775 if (callchain_param.order == ORDER_CALLEE) {
1776 if (j < i + 1) 1776 if (j < i + 1)
1777 ip = chain->ips[j]; 1777 ip = chain->ips[j];
@@ -2095,7 +2095,7 @@ int machine__get_kernel_start(struct machine *machine)
2095 */ 2095 */
2096 machine->kernel_start = 1ULL << 63; 2096 machine->kernel_start = 1ULL << 63;
2097 if (map) { 2097 if (map) {
2098 err = map__load(map, machine->symbol_filter); 2098 err = map__load(map);
2099 if (map->start) 2099 if (map->start)
2100 machine->kernel_start = map->start; 2100 machine->kernel_start = map->start;
2101 } 2101 }
@@ -2111,7 +2111,7 @@ char *machine__resolve_kernel_addr(void *vmachine, unsigned long long *addrp, ch
2111{ 2111{
2112 struct machine *machine = vmachine; 2112 struct machine *machine = vmachine;
2113 struct map *map; 2113 struct map *map;
2114 struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map, NULL); 2114 struct symbol *sym = map_groups__find_symbol(&machine->kmaps, MAP__FUNCTION, *addrp, &map);
2115 2115
2116 if (sym == NULL) 2116 if (sym == NULL)
2117 return NULL; 2117 return NULL;
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index 41ac9cfd416b..354de6e56109 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -41,7 +41,6 @@ struct machine {
41 struct map_groups kmaps; 41 struct map_groups kmaps;
42 struct map *vmlinux_maps[MAP__NR_TYPES]; 42 struct map *vmlinux_maps[MAP__NR_TYPES];
43 u64 kernel_start; 43 u64 kernel_start;
44 symbol_filter_t symbol_filter;
45 pid_t *current_tid; 44 pid_t *current_tid;
46 union { /* Tool specific area */ 45 union { /* Tool specific area */
47 void *priv; 46 void *priv;
@@ -110,7 +109,6 @@ typedef void (*machine__process_t)(struct machine *machine, void *data);
110struct machines { 109struct machines {
111 struct machine host; 110 struct machine host;
112 struct rb_root guests; 111 struct rb_root guests;
113 symbol_filter_t symbol_filter;
114}; 112};
115 113
116void machines__init(struct machines *machines); 114void machines__init(struct machines *machines);
@@ -128,8 +126,6 @@ struct machine *machines__findnew(struct machines *machines, pid_t pid);
128void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size); 126void machines__set_id_hdr_size(struct machines *machines, u16 id_hdr_size);
129char *machine__mmap_name(struct machine *machine, char *bf, size_t size); 127char *machine__mmap_name(struct machine *machine, char *bf, size_t size);
130 128
131void machines__set_symbol_filter(struct machines *machines,
132 symbol_filter_t symbol_filter);
133void machines__set_comm_exec(struct machines *machines, bool comm_exec); 129void machines__set_comm_exec(struct machines *machines, bool comm_exec);
134 130
135struct machine *machine__new_host(void); 131struct machine *machine__new_host(void);
@@ -178,51 +174,44 @@ size_t machine__fprintf(struct machine *machine, FILE *fp);
178static inline 174static inline
179struct symbol *machine__find_kernel_symbol(struct machine *machine, 175struct symbol *machine__find_kernel_symbol(struct machine *machine,
180 enum map_type type, u64 addr, 176 enum map_type type, u64 addr,
181 struct map **mapp, 177 struct map **mapp)
182 symbol_filter_t filter)
183{ 178{
184 return map_groups__find_symbol(&machine->kmaps, type, addr, 179 return map_groups__find_symbol(&machine->kmaps, type, addr, mapp);
185 mapp, filter);
186} 180}
187 181
188static inline 182static inline
189struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine, 183struct symbol *machine__find_kernel_symbol_by_name(struct machine *machine,
190 enum map_type type, const char *name, 184 enum map_type type, const char *name,
191 struct map **mapp, 185 struct map **mapp)
192 symbol_filter_t filter)
193{ 186{
194 return map_groups__find_symbol_by_name(&machine->kmaps, type, name, 187 return map_groups__find_symbol_by_name(&machine->kmaps, type, name, mapp);
195 mapp, filter);
196} 188}
197 189
198static inline 190static inline
199struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr, 191struct symbol *machine__find_kernel_function(struct machine *machine, u64 addr,
200 struct map **mapp, 192 struct map **mapp)
201 symbol_filter_t filter)
202{ 193{
203 return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr, 194 return machine__find_kernel_symbol(machine, MAP__FUNCTION, addr,
204 mapp, filter); 195 mapp);
205} 196}
206 197
207static inline 198static inline
208struct symbol *machine__find_kernel_function_by_name(struct machine *machine, 199struct symbol *machine__find_kernel_function_by_name(struct machine *machine,
209 const char *name, 200 const char *name,
210 struct map **mapp, 201 struct map **mapp)
211 symbol_filter_t filter)
212{ 202{
213 return map_groups__find_function_by_name(&machine->kmaps, name, mapp, 203 return map_groups__find_function_by_name(&machine->kmaps, name, mapp);
214 filter);
215} 204}
216 205
217struct map *machine__findnew_module_map(struct machine *machine, u64 start, 206struct map *machine__findnew_module_map(struct machine *machine, u64 start,
218 const char *filename); 207 const char *filename);
208int arch__fix_module_text_start(u64 *start, const char *name);
219 209
220int __machine__load_kallsyms(struct machine *machine, const char *filename, 210int __machine__load_kallsyms(struct machine *machine, const char *filename,
221 enum map_type type, bool no_kcore, symbol_filter_t filter); 211 enum map_type type, bool no_kcore);
222int machine__load_kallsyms(struct machine *machine, const char *filename, 212int machine__load_kallsyms(struct machine *machine, const char *filename,
223 enum map_type type, symbol_filter_t filter); 213 enum map_type type);
224int machine__load_vmlinux_path(struct machine *machine, enum map_type type, 214int machine__load_vmlinux_path(struct machine *machine, enum map_type type);
225 symbol_filter_t filter);
226 215
227size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp, 216size_t machine__fprintf_dsos_buildid(struct machine *machine, FILE *fp,
228 bool (skip)(struct dso *dso, int parm), int parm); 217 bool (skip)(struct dso *dso, int parm), int parm);
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index b19bcd3b7128..c662fef95d14 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -6,6 +6,7 @@
6#include <string.h> 6#include <string.h>
7#include <stdio.h> 7#include <stdio.h>
8#include <unistd.h> 8#include <unistd.h>
9#include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
9#include "map.h" 10#include "map.h"
10#include "thread.h" 11#include "thread.h"
11#include "strlist.h" 12#include "strlist.h"
@@ -15,6 +16,7 @@
15#include "debug.h" 16#include "debug.h"
16#include "machine.h" 17#include "machine.h"
17#include <linux/string.h> 18#include <linux/string.h>
19#include "unwind.h"
18 20
19static void __maps__insert(struct maps *maps, struct map *map); 21static void __maps__insert(struct maps *maps, struct map *map);
20 22
@@ -23,9 +25,10 @@ const char *map_type__name[MAP__NR_TYPES] = {
23 [MAP__VARIABLE] = "Variables", 25 [MAP__VARIABLE] = "Variables",
24}; 26};
25 27
26static inline int is_anon_memory(const char *filename) 28static inline int is_anon_memory(const char *filename, u32 flags)
27{ 29{
28 return !strcmp(filename, "//anon") || 30 return flags & MAP_HUGETLB ||
31 !strcmp(filename, "//anon") ||
29 !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) || 32 !strncmp(filename, "/dev/zero", sizeof("/dev/zero") - 1) ||
30 !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1); 33 !strncmp(filename, "/anon_hugepage", sizeof("/anon_hugepage") - 1);
31} 34}
@@ -154,7 +157,7 @@ struct map *map__new(struct machine *machine, u64 start, u64 len,
154 int anon, no_dso, vdso, android; 157 int anon, no_dso, vdso, android;
155 158
156 android = is_android_lib(filename); 159 android = is_android_lib(filename);
157 anon = is_anon_memory(filename); 160 anon = is_anon_memory(filename, flags);
158 vdso = is_vdso_map(filename); 161 vdso = is_vdso_map(filename);
159 no_dso = is_no_dso_memory(filename); 162 no_dso = is_no_dso_memory(filename);
160 163
@@ -278,7 +281,7 @@ void map__fixup_end(struct map *map)
278 281
279#define DSO__DELETED "(deleted)" 282#define DSO__DELETED "(deleted)"
280 283
281int map__load(struct map *map, symbol_filter_t filter) 284int map__load(struct map *map)
282{ 285{
283 const char *name = map->dso->long_name; 286 const char *name = map->dso->long_name;
284 int nr; 287 int nr;
@@ -286,7 +289,7 @@ int map__load(struct map *map, symbol_filter_t filter)
286 if (dso__loaded(map->dso, map->type)) 289 if (dso__loaded(map->dso, map->type))
287 return 0; 290 return 0;
288 291
289 nr = dso__load(map->dso, map, filter); 292 nr = dso__load(map->dso, map);
290 if (nr < 0) { 293 if (nr < 0) {
291 if (map->dso->has_build_id) { 294 if (map->dso->has_build_id) {
292 char sbuild_id[SBUILD_ID_SIZE]; 295 char sbuild_id[SBUILD_ID_SIZE];
@@ -327,19 +330,17 @@ int __weak arch__compare_symbol_names(const char *namea, const char *nameb)
327 return strcmp(namea, nameb); 330 return strcmp(namea, nameb);
328} 331}
329 332
330struct symbol *map__find_symbol(struct map *map, u64 addr, 333struct symbol *map__find_symbol(struct map *map, u64 addr)
331 symbol_filter_t filter)
332{ 334{
333 if (map__load(map, filter) < 0) 335 if (map__load(map) < 0)
334 return NULL; 336 return NULL;
335 337
336 return dso__find_symbol(map->dso, map->type, addr); 338 return dso__find_symbol(map->dso, map->type, addr);
337} 339}
338 340
339struct symbol *map__find_symbol_by_name(struct map *map, const char *name, 341struct symbol *map__find_symbol_by_name(struct map *map, const char *name)
340 symbol_filter_t filter)
341{ 342{
342 if (map__load(map, filter) < 0) 343 if (map__load(map) < 0)
343 return NULL; 344 return NULL;
344 345
345 if (!dso__sorted_by_name(map->dso, map->type)) 346 if (!dso__sorted_by_name(map->dso, map->type))
@@ -552,23 +553,22 @@ void map_groups__put(struct map_groups *mg)
552 553
553struct symbol *map_groups__find_symbol(struct map_groups *mg, 554struct symbol *map_groups__find_symbol(struct map_groups *mg,
554 enum map_type type, u64 addr, 555 enum map_type type, u64 addr,
555 struct map **mapp, 556 struct map **mapp)
556 symbol_filter_t filter)
557{ 557{
558 struct map *map = map_groups__find(mg, type, addr); 558 struct map *map = map_groups__find(mg, type, addr);
559 559
560 /* Ensure map is loaded before using map->map_ip */ 560 /* Ensure map is loaded before using map->map_ip */
561 if (map != NULL && map__load(map, filter) >= 0) { 561 if (map != NULL && map__load(map) >= 0) {
562 if (mapp != NULL) 562 if (mapp != NULL)
563 *mapp = map; 563 *mapp = map;
564 return map__find_symbol(map, map->map_ip(map, addr), filter); 564 return map__find_symbol(map, map->map_ip(map, addr));
565 } 565 }
566 566
567 return NULL; 567 return NULL;
568} 568}
569 569
570struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, 570struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
571 struct map **mapp, symbol_filter_t filter) 571 struct map **mapp)
572{ 572{
573 struct symbol *sym; 573 struct symbol *sym;
574 struct rb_node *nd; 574 struct rb_node *nd;
@@ -578,7 +578,7 @@ struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
578 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) { 578 for (nd = rb_first(&maps->entries); nd; nd = rb_next(nd)) {
579 struct map *pos = rb_entry(nd, struct map, rb_node); 579 struct map *pos = rb_entry(nd, struct map, rb_node);
580 580
581 sym = map__find_symbol_by_name(pos, name, filter); 581 sym = map__find_symbol_by_name(pos, name);
582 582
583 if (sym == NULL) 583 if (sym == NULL)
584 continue; 584 continue;
@@ -596,15 +596,14 @@ out:
596struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 596struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
597 enum map_type type, 597 enum map_type type,
598 const char *name, 598 const char *name,
599 struct map **mapp, 599 struct map **mapp)
600 symbol_filter_t filter)
601{ 600{
602 struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp, filter); 601 struct symbol *sym = maps__find_symbol_by_name(&mg->maps[type], name, mapp);
603 602
604 return sym; 603 return sym;
605} 604}
606 605
607int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter) 606int map_groups__find_ams(struct addr_map_symbol *ams)
608{ 607{
609 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) { 608 if (ams->addr < ams->map->start || ams->addr >= ams->map->end) {
610 if (ams->map->groups == NULL) 609 if (ams->map->groups == NULL)
@@ -616,7 +615,7 @@ int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter)
616 } 615 }
617 616
618 ams->al_addr = ams->map->map_ip(ams->map, ams->addr); 617 ams->al_addr = ams->map->map_ip(ams->map, ams->addr);
619 ams->sym = map__find_symbol(ams->map, ams->al_addr, filter); 618 ams->sym = map__find_symbol(ams->map, ams->al_addr);
620 619
621 return ams->sym ? 0 : -1; 620 return ams->sym ? 0 : -1;
622} 621}
@@ -744,9 +743,10 @@ int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
744/* 743/*
745 * XXX This should not really _copy_ te maps, but refcount them. 744 * XXX This should not really _copy_ te maps, but refcount them.
746 */ 745 */
747int map_groups__clone(struct map_groups *mg, 746int map_groups__clone(struct thread *thread,
748 struct map_groups *parent, enum map_type type) 747 struct map_groups *parent, enum map_type type)
749{ 748{
749 struct map_groups *mg = thread->mg;
750 int err = -ENOMEM; 750 int err = -ENOMEM;
751 struct map *map; 751 struct map *map;
752 struct maps *maps = &parent->maps[type]; 752 struct maps *maps = &parent->maps[type];
@@ -757,6 +757,11 @@ int map_groups__clone(struct map_groups *mg,
757 struct map *new = map__clone(map); 757 struct map *new = map__clone(map);
758 if (new == NULL) 758 if (new == NULL)
759 goto out_unlock; 759 goto out_unlock;
760
761 err = unwind__prepare_access(thread, new, NULL);
762 if (err)
763 goto out_unlock;
764
760 map_groups__insert(mg, new); 765 map_groups__insert(mg, new);
761 map__put(new); 766 map__put(new);
762 } 767 }
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 7309d64ce39e..abdacf800c98 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -127,17 +127,14 @@ struct thread;
127 * @map: the 'struct map *' in which symbols itereated 127 * @map: the 'struct map *' in which symbols itereated
128 * @sym_name: the symbol name 128 * @sym_name: the symbol name
129 * @pos: the 'struct symbol *' to use as a loop cursor 129 * @pos: the 'struct symbol *' to use as a loop cursor
130 * @filter: to use when loading the DSO
131 */ 130 */
132#define __map__for_each_symbol_by_name(map, sym_name, pos, filter) \ 131#define __map__for_each_symbol_by_name(map, sym_name, pos) \
133 for (pos = map__find_symbol_by_name(map, sym_name, filter); \ 132 for (pos = map__find_symbol_by_name(map, sym_name); \
134 pos && arch__compare_symbol_names(pos->name, sym_name) == 0; \ 133 pos && arch__compare_symbol_names(pos->name, sym_name) == 0; \
135 pos = symbol__next_by_name(pos)) 134 pos = symbol__next_by_name(pos))
136 135
137#define map__for_each_symbol_by_name(map, sym_name, pos) \ 136#define map__for_each_symbol_by_name(map, sym_name, pos) \
138 __map__for_each_symbol_by_name(map, sym_name, (pos), NULL) 137 __map__for_each_symbol_by_name(map, sym_name, (pos))
139
140typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
141 138
142int arch__compare_symbol_names(const char *namea, const char *nameb); 139int arch__compare_symbol_names(const char *namea, const char *nameb);
143void map__init(struct map *map, enum map_type type, 140void map__init(struct map *map, enum map_type type,
@@ -173,11 +170,9 @@ size_t map__fprintf_dsoname(struct map *map, FILE *fp);
173int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix, 170int map__fprintf_srcline(struct map *map, u64 addr, const char *prefix,
174 FILE *fp); 171 FILE *fp);
175 172
176int map__load(struct map *map, symbol_filter_t filter); 173int map__load(struct map *map);
177struct symbol *map__find_symbol(struct map *map, 174struct symbol *map__find_symbol(struct map *map, u64 addr);
178 u64 addr, symbol_filter_t filter); 175struct symbol *map__find_symbol_by_name(struct map *map, const char *name);
179struct symbol *map__find_symbol_by_name(struct map *map, const char *name,
180 symbol_filter_t filter);
181void map__fixup_start(struct map *map); 176void map__fixup_start(struct map *map);
182void map__fixup_end(struct map *map); 177void map__fixup_end(struct map *map);
183 178
@@ -191,10 +186,10 @@ struct map *maps__find(struct maps *maps, u64 addr);
191struct map *maps__first(struct maps *maps); 186struct map *maps__first(struct maps *maps);
192struct map *map__next(struct map *map); 187struct map *map__next(struct map *map);
193struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, 188struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name,
194 struct map **mapp, symbol_filter_t filter); 189 struct map **mapp);
195void map_groups__init(struct map_groups *mg, struct machine *machine); 190void map_groups__init(struct map_groups *mg, struct machine *machine);
196void map_groups__exit(struct map_groups *mg); 191void map_groups__exit(struct map_groups *mg);
197int map_groups__clone(struct map_groups *mg, 192int map_groups__clone(struct thread *thread,
198 struct map_groups *parent, enum map_type type); 193 struct map_groups *parent, enum map_type type);
199size_t map_groups__fprintf(struct map_groups *mg, FILE *fp); 194size_t map_groups__fprintf(struct map_groups *mg, FILE *fp);
200 195
@@ -231,25 +226,22 @@ static inline struct map *map_groups__next(struct map *map)
231 226
232struct symbol *map_groups__find_symbol(struct map_groups *mg, 227struct symbol *map_groups__find_symbol(struct map_groups *mg,
233 enum map_type type, u64 addr, 228 enum map_type type, u64 addr,
234 struct map **mapp, 229 struct map **mapp);
235 symbol_filter_t filter);
236 230
237struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, 231struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg,
238 enum map_type type, 232 enum map_type type,
239 const char *name, 233 const char *name,
240 struct map **mapp, 234 struct map **mapp);
241 symbol_filter_t filter);
242 235
243struct addr_map_symbol; 236struct addr_map_symbol;
244 237
245int map_groups__find_ams(struct addr_map_symbol *ams, symbol_filter_t filter); 238int map_groups__find_ams(struct addr_map_symbol *ams);
246 239
247static inline 240static inline
248struct symbol *map_groups__find_function_by_name(struct map_groups *mg, 241struct symbol *map_groups__find_function_by_name(struct map_groups *mg,
249 const char *name, struct map **mapp, 242 const char *name, struct map **mapp)
250 symbol_filter_t filter)
251{ 243{
252 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp, filter); 244 return map_groups__find_symbol_by_name(mg, MAP__FUNCTION, name, mapp);
253} 245}
254 246
255int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, 247int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map,
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/parse-events.c b/tools/perf/util/parse-events.c
index c6fd0479f4cd..4e778eae1510 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,10 @@ 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",
907 [PARSE_EVENTS__TERM_TYPE_DRV_CFG] = "driver-config",
903}; 908};
904 909
905static bool config_term_shrinked; 910static bool config_term_shrinked;
@@ -919,6 +924,7 @@ config_term_avail(int term_type, struct parse_events_error *err)
919 case PARSE_EVENTS__TERM_TYPE_CONFIG1: 924 case PARSE_EVENTS__TERM_TYPE_CONFIG1:
920 case PARSE_EVENTS__TERM_TYPE_CONFIG2: 925 case PARSE_EVENTS__TERM_TYPE_CONFIG2:
921 case PARSE_EVENTS__TERM_TYPE_NAME: 926 case PARSE_EVENTS__TERM_TYPE_NAME:
927 case PARSE_EVENTS__TERM_TYPE_SAMPLE_PERIOD:
922 return true; 928 return true;
923 default: 929 default:
924 if (!err) 930 if (!err)
@@ -992,9 +998,18 @@ do { \
992 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 998 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
993 CHECK_TYPE_VAL(NUM); 999 CHECK_TYPE_VAL(NUM);
994 break; 1000 break;
1001 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1002 CHECK_TYPE_VAL(NUM);
1003 break;
1004 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1005 CHECK_TYPE_VAL(NUM);
1006 break;
995 case PARSE_EVENTS__TERM_TYPE_NAME: 1007 case PARSE_EVENTS__TERM_TYPE_NAME:
996 CHECK_TYPE_VAL(STR); 1008 CHECK_TYPE_VAL(STR);
997 break; 1009 break;
1010 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1011 CHECK_TYPE_VAL(NUM);
1012 break;
998 default: 1013 default:
999 err->str = strdup("unknown term"); 1014 err->str = strdup("unknown term");
1000 err->idx = term->err_term; 1015 err->idx = term->err_term;
@@ -1021,7 +1036,8 @@ static int config_term_pmu(struct perf_event_attr *attr,
1021 struct parse_events_term *term, 1036 struct parse_events_term *term,
1022 struct parse_events_error *err) 1037 struct parse_events_error *err)
1023{ 1038{
1024 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER) 1039 if (term->type_term == PARSE_EVENTS__TERM_TYPE_USER ||
1040 term->type_term == PARSE_EVENTS__TERM_TYPE_DRV_CFG)
1025 /* 1041 /*
1026 * Always succeed for sysfs terms, as we dont know 1042 * Always succeed for sysfs terms, as we dont know
1027 * at this point what type they need to have. 1043 * at this point what type they need to have.
@@ -1040,6 +1056,9 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
1040 case PARSE_EVENTS__TERM_TYPE_STACKSIZE: 1056 case PARSE_EVENTS__TERM_TYPE_STACKSIZE:
1041 case PARSE_EVENTS__TERM_TYPE_INHERIT: 1057 case PARSE_EVENTS__TERM_TYPE_INHERIT:
1042 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1058 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1059 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1060 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1061 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1043 return config_term_common(attr, term, err); 1062 return config_term_common(attr, term, err);
1044 default: 1063 default:
1045 if (err) { 1064 if (err) {
@@ -1109,6 +1128,18 @@ do { \
1109 case PARSE_EVENTS__TERM_TYPE_NOINHERIT: 1128 case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
1110 ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1); 1129 ADD_CONFIG_TERM(INHERIT, inherit, term->val.num ? 0 : 1);
1111 break; 1130 break;
1131 case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
1132 ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num);
1133 break;
1134 case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
1135 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
1136 break;
1137 case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
1138 ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 0 : 1);
1139 break;
1140 case PARSE_EVENTS__TERM_TYPE_DRV_CFG:
1141 ADD_CONFIG_TERM(DRV_CFG, drv_cfg, term->val.str);
1142 break;
1112 default: 1143 default:
1113 break; 1144 break;
1114 } 1145 }
@@ -1118,7 +1149,7 @@ do { \
1118} 1149}
1119 1150
1120int parse_events_add_tracepoint(struct list_head *list, int *idx, 1151int parse_events_add_tracepoint(struct list_head *list, int *idx,
1121 char *sys, char *event, 1152 const char *sys, const char *event,
1122 struct parse_events_error *err, 1153 struct parse_events_error *err,
1123 struct list_head *head_config) 1154 struct list_head *head_config)
1124{ 1155{
@@ -1388,7 +1419,7 @@ int parse_events__modifier_event(struct list_head *list, char *str, bool add)
1388 if (!add && get_event_modifier(&mod, str, NULL)) 1419 if (!add && get_event_modifier(&mod, str, NULL))
1389 return -EINVAL; 1420 return -EINVAL;
1390 1421
1391 __evlist__for_each(list, evsel) { 1422 __evlist__for_each_entry(list, evsel) {
1392 if (add && get_event_modifier(&mod, str, evsel)) 1423 if (add && get_event_modifier(&mod, str, evsel))
1393 return -EINVAL; 1424 return -EINVAL;
1394 1425
@@ -1414,7 +1445,7 @@ int parse_events_name(struct list_head *list, char *name)
1414{ 1445{
1415 struct perf_evsel *evsel; 1446 struct perf_evsel *evsel;
1416 1447
1417 __evlist__for_each(list, evsel) { 1448 __evlist__for_each_entry(list, evsel) {
1418 if (!evsel->name) 1449 if (!evsel->name)
1419 evsel->name = strdup(name); 1450 evsel->name = strdup(name);
1420 } 1451 }
@@ -1428,7 +1459,7 @@ comp_pmu(const void *p1, const void *p2)
1428 struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1; 1459 struct perf_pmu_event_symbol *pmu1 = (struct perf_pmu_event_symbol *) p1;
1429 struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2; 1460 struct perf_pmu_event_symbol *pmu2 = (struct perf_pmu_event_symbol *) p2;
1430 1461
1431 return strcmp(pmu1->symbol, pmu2->symbol); 1462 return strcasecmp(pmu1->symbol, pmu2->symbol);
1432} 1463}
1433 1464
1434static void perf_pmu__parse_cleanup(void) 1465static void perf_pmu__parse_cleanup(void)
@@ -1730,20 +1761,49 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
1730static int set_filter(struct perf_evsel *evsel, const void *arg) 1761static int set_filter(struct perf_evsel *evsel, const void *arg)
1731{ 1762{
1732 const char *str = arg; 1763 const char *str = arg;
1764 bool found = false;
1765 int nr_addr_filters = 0;
1766 struct perf_pmu *pmu = NULL;
1733 1767
1734 if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) { 1768 if (evsel == NULL)
1735 fprintf(stderr, 1769 goto err;
1736 "--filter option should follow a -e tracepoint option\n"); 1770
1737 return -1; 1771 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
1772 if (perf_evsel__append_tp_filter(evsel, str) < 0) {
1773 fprintf(stderr,
1774 "not enough memory to hold filter string\n");
1775 return -1;
1776 }
1777
1778 return 0;
1738 } 1779 }
1739 1780
1740 if (perf_evsel__append_filter(evsel, "&&", str) < 0) { 1781 while ((pmu = perf_pmu__scan(pmu)) != NULL)
1782 if (pmu->type == evsel->attr.type) {
1783 found = true;
1784 break;
1785 }
1786
1787 if (found)
1788 perf_pmu__scan_file(pmu, "nr_addr_filters",
1789 "%d", &nr_addr_filters);
1790
1791 if (!nr_addr_filters)
1792 goto err;
1793
1794 if (perf_evsel__append_addr_filter(evsel, str) < 0) {
1741 fprintf(stderr, 1795 fprintf(stderr,
1742 "not enough memory to hold filter string\n"); 1796 "not enough memory to hold filter string\n");
1743 return -1; 1797 return -1;
1744 } 1798 }
1745 1799
1746 return 0; 1800 return 0;
1801
1802err:
1803 fprintf(stderr,
1804 "--filter option should follow a -e tracepoint or HW tracer option\n");
1805
1806 return -1;
1747} 1807}
1748 1808
1749int parse_filter(const struct option *opt, const char *str, 1809int parse_filter(const struct option *opt, const char *str,
@@ -1768,7 +1828,7 @@ static int add_exclude_perf_filter(struct perf_evsel *evsel,
1768 1828
1769 snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid()); 1829 snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
1770 1830
1771 if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) { 1831 if (perf_evsel__append_tp_filter(evsel, new_filter) < 0) {
1772 fprintf(stderr, 1832 fprintf(stderr,
1773 "not enough memory to hold filter string\n"); 1833 "not enough memory to hold filter string\n");
1774 return -1; 1834 return -1;
@@ -1976,6 +2036,85 @@ static bool is_event_supported(u8 type, unsigned config)
1976 return ret; 2036 return ret;
1977} 2037}
1978 2038
2039void print_sdt_events(const char *subsys_glob, const char *event_glob,
2040 bool name_only)
2041{
2042 struct probe_cache *pcache;
2043 struct probe_cache_entry *ent;
2044 struct strlist *bidlist, *sdtlist;
2045 struct strlist_config cfg = {.dont_dupstr = true};
2046 struct str_node *nd, *nd2;
2047 char *buf, *path, *ptr = NULL;
2048 bool show_detail = false;
2049 int ret;
2050
2051 sdtlist = strlist__new(NULL, &cfg);
2052 if (!sdtlist) {
2053 pr_debug("Failed to allocate new strlist for SDT\n");
2054 return;
2055 }
2056 bidlist = build_id_cache__list_all(true);
2057 if (!bidlist) {
2058 pr_debug("Failed to get buildids: %d\n", errno);
2059 return;
2060 }
2061 strlist__for_each_entry(nd, bidlist) {
2062 pcache = probe_cache__new(nd->s);
2063 if (!pcache)
2064 continue;
2065 list_for_each_entry(ent, &pcache->entries, node) {
2066 if (!ent->sdt)
2067 continue;
2068 if (subsys_glob &&
2069 !strglobmatch(ent->pev.group, subsys_glob))
2070 continue;
2071 if (event_glob &&
2072 !strglobmatch(ent->pev.event, event_glob))
2073 continue;
2074 ret = asprintf(&buf, "%s:%s@%s", ent->pev.group,
2075 ent->pev.event, nd->s);
2076 if (ret > 0)
2077 strlist__add(sdtlist, buf);
2078 }
2079 probe_cache__delete(pcache);
2080 }
2081 strlist__delete(bidlist);
2082
2083 strlist__for_each_entry(nd, sdtlist) {
2084 buf = strchr(nd->s, '@');
2085 if (buf)
2086 *(buf++) = '\0';
2087 if (name_only) {
2088 printf("%s ", nd->s);
2089 continue;
2090 }
2091 nd2 = strlist__next(nd);
2092 if (nd2) {
2093 ptr = strchr(nd2->s, '@');
2094 if (ptr)
2095 *ptr = '\0';
2096 if (strcmp(nd->s, nd2->s) == 0)
2097 show_detail = true;
2098 }
2099 if (show_detail) {
2100 path = build_id_cache__origname(buf);
2101 ret = asprintf(&buf, "%s@%s(%.12s)", nd->s, path, buf);
2102 if (ret > 0) {
2103 printf(" %-50s [%s]\n", buf, "SDT event");
2104 free(buf);
2105 }
2106 } else
2107 printf(" %-50s [%s]\n", nd->s, "SDT event");
2108 if (nd2) {
2109 if (strcmp(nd->s, nd2->s) != 0)
2110 show_detail = false;
2111 if (ptr)
2112 *ptr = '@';
2113 }
2114 }
2115 strlist__delete(sdtlist);
2116}
2117
1979int print_hwcache_events(const char *event_glob, bool name_only) 2118int print_hwcache_events(const char *event_glob, bool name_only)
1980{ 2119{
1981 unsigned int type, op, i, evt_i = 0, evt_num = 0; 2120 unsigned int type, op, i, evt_i = 0, evt_num = 0;
@@ -2125,7 +2264,8 @@ out_enomem:
2125/* 2264/*
2126 * Print the help text for the event symbols: 2265 * Print the help text for the event symbols:
2127 */ 2266 */
2128void print_events(const char *event_glob, bool name_only) 2267void print_events(const char *event_glob, bool name_only, bool quiet_flag,
2268 bool long_desc)
2129{ 2269{
2130 print_symbol_events(event_glob, PERF_TYPE_HARDWARE, 2270 print_symbol_events(event_glob, PERF_TYPE_HARDWARE,
2131 event_symbols_hw, PERF_COUNT_HW_MAX, name_only); 2271 event_symbols_hw, PERF_COUNT_HW_MAX, name_only);
@@ -2135,7 +2275,7 @@ void print_events(const char *event_glob, bool name_only)
2135 2275
2136 print_hwcache_events(event_glob, name_only); 2276 print_hwcache_events(event_glob, name_only);
2137 2277
2138 print_pmu_events(event_glob, name_only); 2278 print_pmu_events(event_glob, name_only, quiet_flag, long_desc);
2139 2279
2140 if (event_glob != NULL) 2280 if (event_glob != NULL)
2141 return; 2281 return;
@@ -2158,6 +2298,8 @@ void print_events(const char *event_glob, bool name_only)
2158 } 2298 }
2159 2299
2160 print_tracepoint_events(NULL, NULL, name_only); 2300 print_tracepoint_events(NULL, NULL, name_only);
2301
2302 print_sdt_events(NULL, NULL, name_only);
2161} 2303}
2162 2304
2163int parse_events__is_hardcoded_term(struct parse_events_term *term) 2305int parse_events__is_hardcoded_term(struct parse_events_term *term)
@@ -2322,9 +2464,9 @@ static void config_terms_list(char *buf, size_t buf_sz)
2322char *parse_events_formats_error_string(char *additional_terms) 2464char *parse_events_formats_error_string(char *additional_terms)
2323{ 2465{
2324 char *str; 2466 char *str;
2325 /* "branch_type" is the longest name */ 2467 /* "no-overwrite" is the longest name */
2326 char static_terms[__PARSE_EVENTS__TERM_TYPE_NR * 2468 char static_terms[__PARSE_EVENTS__TERM_TYPE_NR *
2327 (sizeof("branch_type") - 1)]; 2469 (sizeof("no-overwrite") - 1)];
2328 2470
2329 config_terms_list(static_terms, sizeof(static_terms)); 2471 config_terms_list(static_terms, sizeof(static_terms));
2330 /* valid terms */ 2472 /* valid terms */
diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
index d740c3ca9a1d..da246a3ddb69 100644
--- a/tools/perf/util/parse-events.h
+++ b/tools/perf/util/parse-events.h
@@ -68,6 +68,10 @@ 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,
74 PARSE_EVENTS__TERM_TYPE_DRV_CFG,
71 __PARSE_EVENTS__TERM_TYPE_NR, 75 __PARSE_EVENTS__TERM_TYPE_NR,
72}; 76};
73 77
@@ -133,7 +137,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); 137int parse_events__modifier_group(struct list_head *list, char *event_mod);
134int parse_events_name(struct list_head *list, char *name); 138int parse_events_name(struct list_head *list, char *name);
135int parse_events_add_tracepoint(struct list_head *list, int *idx, 139int parse_events_add_tracepoint(struct list_head *list, int *idx,
136 char *sys, char *event, 140 const char *sys, const char *event,
137 struct parse_events_error *error, 141 struct parse_events_error *error,
138 struct list_head *head_config); 142 struct list_head *head_config);
139int parse_events_load_bpf(struct parse_events_evlist *data, 143int parse_events_load_bpf(struct parse_events_evlist *data,
@@ -168,7 +172,8 @@ void parse_events_update_lists(struct list_head *list_event,
168void parse_events_evlist_error(struct parse_events_evlist *data, 172void parse_events_evlist_error(struct parse_events_evlist *data,
169 int idx, const char *str); 173 int idx, const char *str);
170 174
171void print_events(const char *event_glob, bool name_only); 175void print_events(const char *event_glob, bool name_only, bool quiet,
176 bool long_desc);
172 177
173struct event_symbol { 178struct event_symbol {
174 const char *symbol; 179 const char *symbol;
@@ -182,6 +187,8 @@ void print_symbol_events(const char *event_glob, unsigned type,
182void print_tracepoint_events(const char *subsys_glob, const char *event_glob, 187void print_tracepoint_events(const char *subsys_glob, const char *event_glob,
183 bool name_only); 188 bool name_only);
184int print_hwcache_events(const char *event_glob, bool name_only); 189int print_hwcache_events(const char *event_glob, bool name_only);
190void print_sdt_events(const char *subsys_glob, const char *event_glob,
191 bool name_only);
185int is_valid_tracepoint(const char *event_string); 192int is_valid_tracepoint(const char *event_string);
186 193
187int valid_event_mount(const char *eventfs); 194int valid_event_mount(const char *eventfs);
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 1477fbc78993..9f43fda2570f 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -53,6 +53,26 @@ static int str(yyscan_t scanner, int token)
53 return token; 53 return token;
54} 54}
55 55
56/*
57 * This function is called when the parser gets two kind of input:
58 *
59 * @cfg1 or @cfg2=config
60 *
61 * The leading '@' is stripped off before 'cfg1' and 'cfg2=config' are given to
62 * bison. In the latter case it is necessary to keep the string intact so that
63 * the PMU kernel driver can determine what configurable is associated to
64 * 'config'.
65 */
66static int drv_str(yyscan_t scanner, int token)
67{
68 YYSTYPE *yylval = parse_events_get_lval(scanner);
69 char *text = parse_events_get_text(scanner);
70
71 /* Strip off the '@' */
72 yylval->str = strdup(text + 1);
73 return token;
74}
75
56#define REWIND(__alloc) \ 76#define REWIND(__alloc) \
57do { \ 77do { \
58 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \ 78 YYSTYPE *__yylval = parse_events_get_lval(yyscanner); \
@@ -124,6 +144,7 @@ num_hex 0x[a-fA-F0-9]+
124num_raw_hex [a-fA-F0-9]+ 144num_raw_hex [a-fA-F0-9]+
125name [a-zA-Z_*?][a-zA-Z0-9_*?.]* 145name [a-zA-Z_*?][a-zA-Z0-9_*?.]*
126name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]* 146name_minus [a-zA-Z_*?][a-zA-Z0-9\-_*?.:]*
147drv_cfg_term [a-zA-Z0-9_\.]+(=[a-zA-Z0-9_*?\.:]+)?
127/* If you add a modifier you need to update check_modifier() */ 148/* If you add a modifier you need to update check_modifier() */
128modifier_event [ukhpPGHSDI]+ 149modifier_event [ukhpPGHSDI]+
129modifier_bp [rwx]{1,3} 150modifier_bp [rwx]{1,3}
@@ -199,13 +220,17 @@ branch_type { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_BRANCH_SAMPLE_TYPE
199time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); } 220time { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
200call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); } 221call-graph { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
201stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); } 222stack-size { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
223max-stack { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
202inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); } 224inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
203no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); } 225no-inherit { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
226overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }
227no-overwrite { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOOVERWRITE); }
204, { return ','; } 228, { return ','; }
205"/" { BEGIN(INITIAL); return '/'; } 229"/" { BEGIN(INITIAL); return '/'; }
206{name_minus} { return str(yyscanner, PE_NAME); } 230{name_minus} { return str(yyscanner, PE_NAME); }
207\[all\] { return PE_ARRAY_ALL; } 231\[all\] { return PE_ARRAY_ALL; }
208"[" { BEGIN(array); return '['; } 232"[" { BEGIN(array); return '['; }
233@{drv_cfg_term} { return drv_str(yyscanner, PE_DRV_CFG_TERM); }
209} 234}
210 235
211<mem>{ 236<mem>{
@@ -259,6 +284,7 @@ cycles-ct { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
259cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); } 284cycles-t { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
260mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); } 285mem-loads { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
261mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); } 286mem-stores { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
287topdown-[a-z-]+ { return str(yyscanner, PE_KERNEL_PMU_EVENT); }
262 288
263L1-dcache|l1-d|l1d|L1-data | 289L1-dcache|l1-d|l1d|L1-data |
264L1-icache|l1-i|l1i|L1-instruction | 290L1-icache|l1-i|l1i|L1-instruction |
diff --git a/tools/perf/util/parse-events.y b/tools/perf/util/parse-events.y
index 5be4a5f216d6..879115f93edc 100644
--- a/tools/perf/util/parse-events.y
+++ b/tools/perf/util/parse-events.y
@@ -49,6 +49,7 @@ static void inc_group_count(struct list_head *list,
49%token PE_ERROR 49%token PE_ERROR
50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 50%token PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
51%token PE_ARRAY_ALL PE_ARRAY_RANGE 51%token PE_ARRAY_ALL PE_ARRAY_RANGE
52%token PE_DRV_CFG_TERM
52%type <num> PE_VALUE 53%type <num> PE_VALUE
53%type <num> PE_VALUE_SYM_HW 54%type <num> PE_VALUE_SYM_HW
54%type <num> PE_VALUE_SYM_SW 55%type <num> PE_VALUE_SYM_SW
@@ -63,6 +64,7 @@ static void inc_group_count(struct list_head *list,
63%type <str> PE_MODIFIER_BP 64%type <str> PE_MODIFIER_BP
64%type <str> PE_EVENT_NAME 65%type <str> PE_EVENT_NAME
65%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT 66%type <str> PE_PMU_EVENT_PRE PE_PMU_EVENT_SUF PE_KERNEL_PMU_EVENT
67%type <str> PE_DRV_CFG_TERM
66%type <num> value_sym 68%type <num> value_sym
67%type <head> event_config 69%type <head> event_config
68%type <head> opt_event_config 70%type <head> opt_event_config
@@ -599,6 +601,15 @@ PE_NAME array '=' PE_VALUE
599 term->array = $2; 601 term->array = $2;
600 $$ = term; 602 $$ = term;
601} 603}
604|
605PE_DRV_CFG_TERM
606{
607 struct parse_events_term *term;
608
609 ABORT_ON(parse_events_term__str(&term, PARSE_EVENTS__TERM_TYPE_DRV_CFG,
610 $1, $1, &@1, NULL));
611 $$ = term;
612}
602 613
603array: 614array:
604'[' array_terms ']' 615'[' array_terms ']'
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/pmu.c b/tools/perf/util/pmu.c
index ddb0261b2577..b1474dcadfa2 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -12,6 +12,9 @@
12#include "pmu.h" 12#include "pmu.h"
13#include "parse-events.h" 13#include "parse-events.h"
14#include "cpumap.h" 14#include "cpumap.h"
15#include "header.h"
16#include "pmu-events/pmu-events.h"
17#include "cache.h"
15 18
16struct perf_pmu_format { 19struct perf_pmu_format {
17 char *name; 20 char *name;
@@ -220,7 +223,8 @@ static int perf_pmu__parse_snapshot(struct perf_pmu_alias *alias,
220} 223}
221 224
222static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name, 225static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
223 char *desc __maybe_unused, char *val) 226 char *desc, char *val, char *long_desc,
227 char *topic)
224{ 228{
225 struct perf_pmu_alias *alias; 229 struct perf_pmu_alias *alias;
226 int ret; 230 int ret;
@@ -253,6 +257,11 @@ static int __perf_pmu__new_alias(struct list_head *list, char *dir, char *name,
253 perf_pmu__parse_snapshot(alias, dir, name); 257 perf_pmu__parse_snapshot(alias, dir, name);
254 } 258 }
255 259
260 alias->desc = desc ? strdup(desc) : NULL;
261 alias->long_desc = long_desc ? strdup(long_desc) :
262 desc ? strdup(desc) : NULL;
263 alias->topic = topic ? strdup(topic) : NULL;
264
256 list_add_tail(&alias->list, list); 265 list_add_tail(&alias->list, list);
257 266
258 return 0; 267 return 0;
@@ -269,7 +278,7 @@ static int perf_pmu__new_alias(struct list_head *list, char *dir, char *name, FI
269 278
270 buf[ret] = 0; 279 buf[ret] = 0;
271 280
272 return __perf_pmu__new_alias(list, dir, name, NULL, buf); 281 return __perf_pmu__new_alias(list, dir, name, NULL, buf, NULL, NULL);
273} 282}
274 283
275static inline bool pmu_alias_info_file(char *name) 284static inline bool pmu_alias_info_file(char *name)
@@ -445,14 +454,23 @@ static struct cpu_map *pmu_cpumask(const char *name)
445 FILE *file; 454 FILE *file;
446 struct cpu_map *cpus; 455 struct cpu_map *cpus;
447 const char *sysfs = sysfs__mountpoint(); 456 const char *sysfs = sysfs__mountpoint();
457 const char *templates[] = {
458 "%s/bus/event_source/devices/%s/cpumask",
459 "%s/bus/event_source/devices/%s/cpus",
460 NULL
461 };
462 const char **template;
448 463
449 if (!sysfs) 464 if (!sysfs)
450 return NULL; 465 return NULL;
451 466
452 snprintf(path, PATH_MAX, 467 for (template = templates; *template; template++) {
453 "%s/bus/event_source/devices/%s/cpumask", sysfs, name); 468 snprintf(path, PATH_MAX, *template, sysfs, name);
469 if (stat(path, &st) == 0)
470 break;
471 }
454 472
455 if (stat(path, &st) < 0) 473 if (!*template)
456 return NULL; 474 return NULL;
457 475
458 file = fopen(path, "r"); 476 file = fopen(path, "r");
@@ -464,6 +482,68 @@ static struct cpu_map *pmu_cpumask(const char *name)
464 return cpus; 482 return cpus;
465} 483}
466 484
485/*
486 * Return the CPU id as a raw string.
487 *
488 * Each architecture should provide a more precise id string that
489 * can be use to match the architecture's "mapfile".
490 */
491char * __weak get_cpuid_str(void)
492{
493 return NULL;
494}
495
496/*
497 * From the pmu_events_map, find the table of PMU events that corresponds
498 * to the current running CPU. Then, add all PMU events from that table
499 * as aliases.
500 */
501static void pmu_add_cpu_aliases(struct list_head *head)
502{
503 int i;
504 struct pmu_events_map *map;
505 struct pmu_event *pe;
506 char *cpuid;
507
508 cpuid = getenv("PERF_CPUID");
509 if (cpuid)
510 cpuid = strdup(cpuid);
511 if (!cpuid)
512 cpuid = get_cpuid_str();
513 if (!cpuid)
514 return;
515
516 pr_debug("Using CPUID %s\n", cpuid);
517
518 i = 0;
519 while (1) {
520 map = &pmu_events_map[i++];
521 if (!map->table)
522 goto out;
523
524 if (!strcmp(map->cpuid, cpuid))
525 break;
526 }
527
528 /*
529 * Found a matching PMU events table. Create aliases
530 */
531 i = 0;
532 while (1) {
533 pe = &map->table[i++];
534 if (!pe->name)
535 break;
536
537 /* need type casts to override 'const' */
538 __perf_pmu__new_alias(head, NULL, (char *)pe->name,
539 (char *)pe->desc, (char *)pe->event,
540 (char *)pe->long_desc, (char *)pe->topic);
541 }
542
543out:
544 free(cpuid);
545}
546
467struct perf_event_attr * __weak 547struct perf_event_attr * __weak
468perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused) 548perf_pmu__get_default_config(struct perf_pmu *pmu __maybe_unused)
469{ 549{
@@ -488,6 +568,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
488 if (pmu_aliases(name, &aliases)) 568 if (pmu_aliases(name, &aliases))
489 return NULL; 569 return NULL;
490 570
571 if (!strcmp(name, "cpu"))
572 pmu_add_cpu_aliases(&aliases);
573
491 if (pmu_type(name, &type)) 574 if (pmu_type(name, &type))
492 return NULL; 575 return NULL;
493 576
@@ -974,21 +1057,63 @@ static char *format_alias_or(char *buf, int len, struct perf_pmu *pmu,
974 return buf; 1057 return buf;
975} 1058}
976 1059
977static int cmp_string(const void *a, const void *b) 1060struct sevent {
1061 char *name;
1062 char *desc;
1063 char *topic;
1064};
1065
1066static int cmp_sevent(const void *a, const void *b)
978{ 1067{
979 const char * const *as = a; 1068 const struct sevent *as = a;
980 const char * const *bs = b; 1069 const struct sevent *bs = b;
981 return strcmp(*as, *bs); 1070
1071 /* Put extra events last */
1072 if (!!as->desc != !!bs->desc)
1073 return !!as->desc - !!bs->desc;
1074 if (as->topic && bs->topic) {
1075 int n = strcmp(as->topic, bs->topic);
1076
1077 if (n)
1078 return n;
1079 }
1080 return strcmp(as->name, bs->name);
982} 1081}
983 1082
984void print_pmu_events(const char *event_glob, bool name_only) 1083static void wordwrap(char *s, int start, int max, int corr)
1084{
1085 int column = start;
1086 int n;
1087
1088 while (*s) {
1089 int wlen = strcspn(s, " \t");
1090
1091 if (column + wlen >= max && column > start) {
1092 printf("\n%*s", start, "");
1093 column = start + corr;
1094 }
1095 n = printf("%s%.*s", column > start ? " " : "", wlen, s);
1096 if (n <= 0)
1097 break;
1098 s += wlen;
1099 column += n;
1100 while (isspace(*s))
1101 s++;
1102 }
1103}
1104
1105void print_pmu_events(const char *event_glob, bool name_only, bool quiet_flag,
1106 bool long_desc)
985{ 1107{
986 struct perf_pmu *pmu; 1108 struct perf_pmu *pmu;
987 struct perf_pmu_alias *alias; 1109 struct perf_pmu_alias *alias;
988 char buf[1024]; 1110 char buf[1024];
989 int printed = 0; 1111 int printed = 0;
990 int len, j; 1112 int len, j;
991 char **aliases; 1113 struct sevent *aliases;
1114 int numdesc = 0;
1115 int columns = pager_get_columns();
1116 char *topic = NULL;
992 1117
993 pmu = NULL; 1118 pmu = NULL;
994 len = 0; 1119 len = 0;
@@ -998,14 +1123,15 @@ void print_pmu_events(const char *event_glob, bool name_only)
998 if (pmu->selectable) 1123 if (pmu->selectable)
999 len++; 1124 len++;
1000 } 1125 }
1001 aliases = zalloc(sizeof(char *) * len); 1126 aliases = zalloc(sizeof(struct sevent) * len);
1002 if (!aliases) 1127 if (!aliases)
1003 goto out_enomem; 1128 goto out_enomem;
1004 pmu = NULL; 1129 pmu = NULL;
1005 j = 0; 1130 j = 0;
1006 while ((pmu = perf_pmu__scan(pmu)) != NULL) { 1131 while ((pmu = perf_pmu__scan(pmu)) != NULL) {
1007 list_for_each_entry(alias, &pmu->aliases, list) { 1132 list_for_each_entry(alias, &pmu->aliases, list) {
1008 char *name = format_alias(buf, sizeof(buf), pmu, alias); 1133 char *name = alias->desc ? alias->name :
1134 format_alias(buf, sizeof(buf), pmu, alias);
1009 bool is_cpu = !strcmp(pmu->name, "cpu"); 1135 bool is_cpu = !strcmp(pmu->name, "cpu");
1010 1136
1011 if (event_glob != NULL && 1137 if (event_glob != NULL &&
@@ -1014,12 +1140,21 @@ void print_pmu_events(const char *event_glob, bool name_only)
1014 event_glob)))) 1140 event_glob))))
1015 continue; 1141 continue;
1016 1142
1017 if (is_cpu && !name_only) 1143 if (is_cpu && !name_only && !alias->desc)
1018 name = format_alias_or(buf, sizeof(buf), pmu, alias); 1144 name = format_alias_or(buf, sizeof(buf), pmu, alias);
1019 1145
1020 aliases[j] = strdup(name); 1146 aliases[j].name = name;
1021 if (aliases[j] == NULL) 1147 if (is_cpu && !name_only && !alias->desc)
1148 aliases[j].name = format_alias_or(buf,
1149 sizeof(buf),
1150 pmu, alias);
1151 aliases[j].name = strdup(aliases[j].name);
1152 if (!aliases[j].name)
1022 goto out_enomem; 1153 goto out_enomem;
1154
1155 aliases[j].desc = long_desc ? alias->long_desc :
1156 alias->desc;
1157 aliases[j].topic = alias->topic;
1023 j++; 1158 j++;
1024 } 1159 }
1025 if (pmu->selectable && 1160 if (pmu->selectable &&
@@ -1027,25 +1162,39 @@ void print_pmu_events(const char *event_glob, bool name_only)
1027 char *s; 1162 char *s;
1028 if (asprintf(&s, "%s//", pmu->name) < 0) 1163 if (asprintf(&s, "%s//", pmu->name) < 0)
1029 goto out_enomem; 1164 goto out_enomem;
1030 aliases[j] = s; 1165 aliases[j].name = s;
1031 j++; 1166 j++;
1032 } 1167 }
1033 } 1168 }
1034 len = j; 1169 len = j;
1035 qsort(aliases, len, sizeof(char *), cmp_string); 1170 qsort(aliases, len, sizeof(struct sevent), cmp_sevent);
1036 for (j = 0; j < len; j++) { 1171 for (j = 0; j < len; j++) {
1037 if (name_only) { 1172 if (name_only) {
1038 printf("%s ", aliases[j]); 1173 printf("%s ", aliases[j].name);
1039 continue; 1174 continue;
1040 } 1175 }
1041 printf(" %-50s [Kernel PMU event]\n", aliases[j]); 1176 if (aliases[j].desc && !quiet_flag) {
1177 if (numdesc++ == 0)
1178 printf("\n");
1179 if (aliases[j].topic && (!topic ||
1180 strcmp(topic, aliases[j].topic))) {
1181 printf("%s%s:\n", topic ? "\n" : "",
1182 aliases[j].topic);
1183 topic = aliases[j].topic;
1184 }
1185 printf(" %-50s\n", aliases[j].name);
1186 printf("%*s", 8, "[");
1187 wordwrap(aliases[j].desc, 8, columns, 0);
1188 printf("]\n");
1189 } else
1190 printf(" %-50s [Kernel PMU event]\n", aliases[j].name);
1042 printed++; 1191 printed++;
1043 } 1192 }
1044 if (printed && pager_in_use()) 1193 if (printed && pager_in_use())
1045 printf("\n"); 1194 printf("\n");
1046out_free: 1195out_free:
1047 for (j = 0; j < len; j++) 1196 for (j = 0; j < len; j++)
1048 zfree(&aliases[j]); 1197 zfree(&aliases[j].name);
1049 zfree(&aliases); 1198 zfree(&aliases);
1050 return; 1199 return;
1051 1200
diff --git a/tools/perf/util/pmu.h b/tools/perf/util/pmu.h
index 5d7e84466bee..25712034c815 100644
--- a/tools/perf/util/pmu.h
+++ b/tools/perf/util/pmu.h
@@ -4,6 +4,7 @@
4#include <linux/bitmap.h> 4#include <linux/bitmap.h>
5#include <linux/perf_event.h> 5#include <linux/perf_event.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include "evsel.h"
7#include "parse-events.h" 8#include "parse-events.h"
8 9
9enum { 10enum {
@@ -25,6 +26,7 @@ struct perf_pmu {
25 struct list_head format; /* HEAD struct perf_pmu_format -> list */ 26 struct list_head format; /* HEAD struct perf_pmu_format -> list */
26 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */ 27 struct list_head aliases; /* HEAD struct perf_pmu_alias -> list */
27 struct list_head list; /* ELEM */ 28 struct list_head list; /* ELEM */
29 int (*set_drv_config) (struct perf_evsel_config_term *term);
28}; 30};
29 31
30struct perf_pmu_info { 32struct perf_pmu_info {
@@ -38,6 +40,9 @@ struct perf_pmu_info {
38 40
39struct perf_pmu_alias { 41struct perf_pmu_alias {
40 char *name; 42 char *name;
43 char *desc;
44 char *long_desc;
45 char *topic;
41 struct list_head terms; /* HEAD struct parse_events_term -> list */ 46 struct list_head terms; /* HEAD struct parse_events_term -> list */
42 struct list_head list; /* ELEM */ 47 struct list_head list; /* ELEM */
43 char unit[UNIT_MAX_LEN+1]; 48 char unit[UNIT_MAX_LEN+1];
@@ -69,7 +74,8 @@ int perf_pmu__format_parse(char *dir, struct list_head *head);
69 74
70struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu); 75struct perf_pmu *perf_pmu__scan(struct perf_pmu *pmu);
71 76
72void print_pmu_events(const char *event_glob, bool name_only); 77void print_pmu_events(const char *event_glob, bool name_only, bool quiet,
78 bool long_desc);
73bool pmu_have_event(const char *pname, const char *name); 79bool pmu_have_event(const char *pname, const char *name);
74 80
75int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt, 81int perf_pmu__scan_file(struct perf_pmu *pmu, const char *name, const char *fmt,
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 74401a20106d..d281ae2b54e8 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,23 +102,20 @@ 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
113static struct symbol *__find_kernel_function_by_name(const char *name, 110static struct symbol *__find_kernel_function_by_name(const char *name,
114 struct map **mapp) 111 struct map **mapp)
115{ 112{
116 return machine__find_kernel_function_by_name(host_machine, name, mapp, 113 return machine__find_kernel_function_by_name(host_machine, name, mapp);
117 NULL);
118} 114}
119 115
120static struct symbol *__find_kernel_function(u64 addr, struct map **mapp) 116static struct symbol *__find_kernel_function(u64 addr, struct map **mapp)
121{ 117{
122 return machine__find_kernel_function(host_machine, addr, mapp, NULL); 118 return machine__find_kernel_function(host_machine, addr, mapp);
123} 119}
124 120
125static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void) 121static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
@@ -128,7 +124,7 @@ static struct ref_reloc_sym *kernel_get_ref_reloc_sym(void)
128 struct kmap *kmap; 124 struct kmap *kmap;
129 struct map *map = machine__kernel_map(host_machine); 125 struct map *map = machine__kernel_map(host_machine);
130 126
131 if (map__load(map, NULL) < 0) 127 if (map__load(map) < 0)
132 return NULL; 128 return NULL;
133 129
134 kmap = map__kmap(map); 130 kmap = map__kmap(map);
@@ -173,15 +169,17 @@ static struct map *kernel_get_module_map(const char *module)
173 module = "kernel"; 169 module = "kernel";
174 170
175 for (pos = maps__first(maps); pos; pos = map__next(pos)) { 171 for (pos = maps__first(maps); pos; pos = map__next(pos)) {
172 /* short_name is "[module]" */
176 if (strncmp(pos->dso->short_name + 1, module, 173 if (strncmp(pos->dso->short_name + 1, module,
177 pos->dso->short_name_len - 2) == 0) { 174 pos->dso->short_name_len - 2) == 0 &&
175 module[pos->dso->short_name_len - 2] == '\0') {
178 return pos; 176 return pos;
179 } 177 }
180 } 178 }
181 return NULL; 179 return NULL;
182} 180}
183 181
184static struct map *get_target_map(const char *target, bool user) 182struct map *get_target_map(const char *target, bool user)
185{ 183{
186 /* Init maps of given executable or kernel */ 184 /* Init maps of given executable or kernel */
187 if (user) 185 if (user)
@@ -215,9 +213,13 @@ static int convert_exec_to_group(const char *exec, char **result)
215 goto out; 213 goto out;
216 } 214 }
217 215
218 ptr2 = strpbrk(ptr1, "-._"); 216 for (ptr2 = ptr1; *ptr2 != '\0'; ptr2++) {
219 if (ptr2) 217 if (!isalnum(*ptr2) && *ptr2 != '_') {
220 *ptr2 = '\0'; 218 *ptr2 = '\0';
219 break;
220 }
221 }
222
221 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1); 223 ret = e_snprintf(buf, 64, "%s_%s", PERFPROBE_GROUP, ptr1);
222 if (ret < 0) 224 if (ret < 0)
223 goto out; 225 goto out;
@@ -352,9 +354,9 @@ static int kernel_get_module_dso(const char *module, struct dso **pdso)
352 vmlinux_name = symbol_conf.vmlinux_name; 354 vmlinux_name = symbol_conf.vmlinux_name;
353 dso->load_errno = 0; 355 dso->load_errno = 0;
354 if (vmlinux_name) 356 if (vmlinux_name)
355 ret = dso__load_vmlinux(dso, map, vmlinux_name, false, NULL); 357 ret = dso__load_vmlinux(dso, map, vmlinux_name, false);
356 else 358 else
357 ret = dso__load_vmlinux_path(dso, map, NULL); 359 ret = dso__load_vmlinux_path(dso, map);
358found: 360found:
359 *pdso = dso; 361 *pdso = dso;
360 return ret; 362 return ret;
@@ -388,7 +390,7 @@ static int find_alternative_probe_point(struct debuginfo *dinfo,
388 if (uprobes) 390 if (uprobes)
389 address = sym->start; 391 address = sym->start;
390 else 392 else
391 address = map->unmap_ip(map, sym->start); 393 address = map->unmap_ip(map, sym->start) - map->reloc;
392 break; 394 break;
393 } 395 }
394 if (!address) { 396 if (!address) {
@@ -471,7 +473,7 @@ static struct debuginfo *open_debuginfo(const char *module, bool silent)
471 err = kernel_get_module_dso(module, &dso); 473 err = kernel_get_module_dso(module, &dso);
472 if (err < 0) { 474 if (err < 0) {
473 if (!dso || dso->load_errno == 0) { 475 if (!dso || dso->load_errno == 0) {
474 if (!strerror_r(-err, reason, STRERR_BUFSIZE)) 476 if (!str_error_r(-err, reason, STRERR_BUFSIZE))
475 strcpy(reason, "(unknown)"); 477 strcpy(reason, "(unknown)");
476 } else 478 } else
477 dso__strerror_load(dso, reason, STRERR_BUFSIZE); 479 dso__strerror_load(dso, reason, STRERR_BUFSIZE);
@@ -667,21 +669,17 @@ static int add_module_to_probe_trace_events(struct probe_trace_event *tevs,
667 return ret; 669 return ret;
668} 670}
669 671
670/* Post processing the probe events */ 672static int
671static int post_process_probe_trace_events(struct probe_trace_event *tevs, 673post_process_kernel_probe_trace_events(struct probe_trace_event *tevs,
672 int ntevs, const char *module, 674 int ntevs)
673 bool uprobe)
674{ 675{
675 struct ref_reloc_sym *reloc_sym; 676 struct ref_reloc_sym *reloc_sym;
676 char *tmp; 677 char *tmp;
677 int i, skipped = 0; 678 int i, skipped = 0;
678 679
679 if (uprobe) 680 /* Skip post process if the target is an offline kernel */
680 return add_exec_to_probe_trace_events(tevs, ntevs, module); 681 if (symbol_conf.ignore_vmlinux_buildid)
681 682 return 0;
682 /* Note that currently ref_reloc_sym based probe is not for drivers */
683 if (module)
684 return add_module_to_probe_trace_events(tevs, ntevs, module);
685 683
686 reloc_sym = kernel_get_ref_reloc_sym(); 684 reloc_sym = kernel_get_ref_reloc_sym();
687 if (!reloc_sym) { 685 if (!reloc_sym) {
@@ -714,6 +712,34 @@ static int post_process_probe_trace_events(struct probe_trace_event *tevs,
714 return skipped; 712 return skipped;
715} 713}
716 714
715void __weak
716arch__post_process_probe_trace_events(struct perf_probe_event *pev __maybe_unused,
717 int ntevs __maybe_unused)
718{
719}
720
721/* Post processing the probe events */
722static int post_process_probe_trace_events(struct perf_probe_event *pev,
723 struct probe_trace_event *tevs,
724 int ntevs, const char *module,
725 bool uprobe)
726{
727 int ret;
728
729 if (uprobe)
730 ret = add_exec_to_probe_trace_events(tevs, ntevs, module);
731 else if (module)
732 /* Currently ref_reloc_sym based probe is not for drivers */
733 ret = add_module_to_probe_trace_events(tevs, ntevs, module);
734 else
735 ret = post_process_kernel_probe_trace_events(tevs, ntevs);
736
737 if (ret >= 0)
738 arch__post_process_probe_trace_events(pev, ntevs);
739
740 return ret;
741}
742
717/* Try to find perf_probe_event with debuginfo */ 743/* Try to find perf_probe_event with debuginfo */
718static int try_to_find_probe_trace_events(struct perf_probe_event *pev, 744static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
719 struct probe_trace_event **tevs) 745 struct probe_trace_event **tevs)
@@ -752,7 +778,7 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
752 778
753 if (ntevs > 0) { /* Succeeded to find trace events */ 779 if (ntevs > 0) { /* Succeeded to find trace events */
754 pr_debug("Found %d probe_trace_events.\n", ntevs); 780 pr_debug("Found %d probe_trace_events.\n", ntevs);
755 ret = post_process_probe_trace_events(*tevs, ntevs, 781 ret = post_process_probe_trace_events(pev, *tevs, ntevs,
756 pev->target, pev->uprobes); 782 pev->target, pev->uprobes);
757 if (ret < 0 || ret == ntevs) { 783 if (ret < 0 || ret == ntevs) {
758 clear_probe_trace_events(*tevs, ntevs); 784 clear_probe_trace_events(*tevs, ntevs);
@@ -809,7 +835,7 @@ static int __show_one_line(FILE *fp, int l, bool skip, bool show_num)
809error: 835error:
810 if (ferror(fp)) { 836 if (ferror(fp)) {
811 pr_warning("File read error: %s\n", 837 pr_warning("File read error: %s\n",
812 strerror_r(errno, sbuf, sizeof(sbuf))); 838 str_error_r(errno, sbuf, sizeof(sbuf)));
813 return -1; 839 return -1;
814 } 840 }
815 return 0; 841 return 0;
@@ -889,7 +915,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
889 fp = fopen(lr->path, "r"); 915 fp = fopen(lr->path, "r");
890 if (fp == NULL) { 916 if (fp == NULL) {
891 pr_warning("Failed to open %s: %s\n", lr->path, 917 pr_warning("Failed to open %s: %s\n", lr->path,
892 strerror_r(errno, sbuf, sizeof(sbuf))); 918 str_error_r(errno, sbuf, sizeof(sbuf)));
893 return -errno; 919 return -errno;
894 } 920 }
895 /* Skip to starting line number */ 921 /* Skip to starting line number */
@@ -899,7 +925,7 @@ static int __show_line_range(struct line_range *lr, const char *module,
899 goto end; 925 goto end;
900 } 926 }
901 927
902 intlist__for_each(ln, lr->line_list) { 928 intlist__for_each_entry(ln, lr->line_list) {
903 for (; ln->i > l; l++) { 929 for (; ln->i > l; l++) {
904 ret = show_one_line(fp, l - lr->offset); 930 ret = show_one_line(fp, l - lr->offset);
905 if (ret < 0) 931 if (ret < 0)
@@ -983,7 +1009,7 @@ static int show_available_vars_at(struct debuginfo *dinfo,
983 zfree(&vl->point.symbol); 1009 zfree(&vl->point.symbol);
984 nvars = 0; 1010 nvars = 0;
985 if (vl->vars) { 1011 if (vl->vars) {
986 strlist__for_each(node, vl->vars) { 1012 strlist__for_each_entry(node, vl->vars) {
987 var = strchr(node->s, '\t') + 1; 1013 var = strchr(node->s, '\t') + 1;
988 if (strfilter__compare(_filter, var)) { 1014 if (strfilter__compare(_filter, var)) {
989 fprintf(stdout, "\t\t%s\n", node->s); 1015 fprintf(stdout, "\t\t%s\n", node->s);
@@ -1200,6 +1226,34 @@ err:
1200 return err; 1226 return err;
1201} 1227}
1202 1228
1229static int parse_perf_probe_event_name(char **arg, struct perf_probe_event *pev)
1230{
1231 char *ptr;
1232
1233 ptr = strchr(*arg, ':');
1234 if (ptr) {
1235 *ptr = '\0';
1236 if (!pev->sdt && !is_c_func_name(*arg))
1237 goto ng_name;
1238 pev->group = strdup(*arg);
1239 if (!pev->group)
1240 return -ENOMEM;
1241 *arg = ptr + 1;
1242 } else
1243 pev->group = NULL;
1244 if (!pev->sdt && !is_c_func_name(*arg)) {
1245ng_name:
1246 semantic_error("%s is bad for event name -it must "
1247 "follow C symbol-naming rule.\n", *arg);
1248 return -EINVAL;
1249 }
1250 pev->event = strdup(*arg);
1251 if (pev->event == NULL)
1252 return -ENOMEM;
1253
1254 return 0;
1255}
1256
1203/* Parse probepoint definition. */ 1257/* Parse probepoint definition. */
1204static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev) 1258static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1205{ 1259{
@@ -1207,33 +1261,64 @@ static int parse_perf_probe_point(char *arg, struct perf_probe_event *pev)
1207 char *ptr, *tmp; 1261 char *ptr, *tmp;
1208 char c, nc = 0; 1262 char c, nc = 0;
1209 bool file_spec = false; 1263 bool file_spec = false;
1264 int ret;
1265
1210 /* 1266 /*
1211 * <Syntax> 1267 * <Syntax>
1212 * perf probe [EVENT=]SRC[:LN|;PTN] 1268 * perf probe [GRP:][EVENT=]SRC[:LN|;PTN]
1213 * perf probe [EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT] 1269 * perf probe [GRP:][EVENT=]FUNC[@SRC][+OFFS|%return|:LN|;PAT]
1214 * 1270 * perf probe %[GRP:]SDT_EVENT
1215 * TODO:Group name support
1216 */ 1271 */
1217 if (!arg) 1272 if (!arg)
1218 return -EINVAL; 1273 return -EINVAL;
1219 1274
1275 /*
1276 * If the probe point starts with '%',
1277 * or starts with "sdt_" and has a ':' but no '=',
1278 * then it should be a SDT/cached probe point.
1279 */
1280 if (arg[0] == '%' ||
1281 (!strncmp(arg, "sdt_", 4) &&
1282 !!strchr(arg, ':') && !strchr(arg, '='))) {
1283 pev->sdt = true;
1284 if (arg[0] == '%')
1285 arg++;
1286 }
1287
1220 ptr = strpbrk(arg, ";=@+%"); 1288 ptr = strpbrk(arg, ";=@+%");
1289 if (pev->sdt) {
1290 if (ptr) {
1291 if (*ptr != '@') {
1292 semantic_error("%s must be an SDT name.\n",
1293 arg);
1294 return -EINVAL;
1295 }
1296 /* This must be a target file name or build id */
1297 tmp = build_id_cache__complement(ptr + 1);
1298 if (tmp) {
1299 pev->target = build_id_cache__origname(tmp);
1300 free(tmp);
1301 } else
1302 pev->target = strdup(ptr + 1);
1303 if (!pev->target)
1304 return -ENOMEM;
1305 *ptr = '\0';
1306 }
1307 ret = parse_perf_probe_event_name(&arg, pev);
1308 if (ret == 0) {
1309 if (asprintf(&pev->point.function, "%%%s", pev->event) < 0)
1310 ret = -errno;
1311 }
1312 return ret;
1313 }
1314
1221 if (ptr && *ptr == '=') { /* Event name */ 1315 if (ptr && *ptr == '=') { /* Event name */
1222 *ptr = '\0'; 1316 *ptr = '\0';
1223 tmp = ptr + 1; 1317 tmp = ptr + 1;
1224 if (strchr(arg, ':')) { 1318 ret = parse_perf_probe_event_name(&arg, pev);
1225 semantic_error("Group name is not supported yet.\n"); 1319 if (ret < 0)
1226 return -ENOTSUP; 1320 return ret;
1227 } 1321
1228 if (!is_c_func_name(arg)) {
1229 semantic_error("%s is bad for event name -it must "
1230 "follow C symbol-naming rule.\n", arg);
1231 return -EINVAL;
1232 }
1233 pev->event = strdup(arg);
1234 if (pev->event == NULL)
1235 return -ENOMEM;
1236 pev->group = NULL;
1237 arg = tmp; 1322 arg = tmp;
1238 } 1323 }
1239 1324
@@ -1536,17 +1621,27 @@ out:
1536 return ret; 1621 return ret;
1537} 1622}
1538 1623
1624/* Returns true if *any* ARG is either C variable, $params or $vars. */
1625bool perf_probe_with_var(struct perf_probe_event *pev)
1626{
1627 int i = 0;
1628
1629 for (i = 0; i < pev->nargs; i++)
1630 if (is_c_varname(pev->args[i].var) ||
1631 !strcmp(pev->args[i].var, PROBE_ARG_PARAMS) ||
1632 !strcmp(pev->args[i].var, PROBE_ARG_VARS))
1633 return true;
1634 return false;
1635}
1636
1539/* Return true if this perf_probe_event requires debuginfo */ 1637/* Return true if this perf_probe_event requires debuginfo */
1540bool perf_probe_event_need_dwarf(struct perf_probe_event *pev) 1638bool perf_probe_event_need_dwarf(struct perf_probe_event *pev)
1541{ 1639{
1542 int i;
1543
1544 if (pev->point.file || pev->point.line || pev->point.lazy_line) 1640 if (pev->point.file || pev->point.line || pev->point.lazy_line)
1545 return true; 1641 return true;
1546 1642
1547 for (i = 0; i < pev->nargs; i++) 1643 if (perf_probe_with_var(pev))
1548 if (is_c_varname(pev->args[i].var)) 1644 return true;
1549 return true;
1550 1645
1551 return false; 1646 return false;
1552} 1647}
@@ -1603,6 +1698,11 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev)
1603 p = strchr(argv[1], ':'); 1698 p = strchr(argv[1], ':');
1604 if (p) { 1699 if (p) {
1605 tp->module = strndup(argv[1], p - argv[1]); 1700 tp->module = strndup(argv[1], p - argv[1]);
1701 if (!tp->module) {
1702 ret = -ENOMEM;
1703 goto out;
1704 }
1705 tev->uprobes = (tp->module[0] == '/');
1606 p++; 1706 p++;
1607 } else 1707 } else
1608 p = argv[1]; 1708 p = argv[1];
@@ -1712,7 +1812,7 @@ out:
1712} 1812}
1713 1813
1714/* Compose only probe point (not argument) */ 1814/* Compose only probe point (not argument) */
1715static char *synthesize_perf_probe_point(struct perf_probe_point *pp) 1815char *synthesize_perf_probe_point(struct perf_probe_point *pp)
1716{ 1816{
1717 struct strbuf buf; 1817 struct strbuf buf;
1718 char *tmp, *ret = NULL; 1818 char *tmp, *ret = NULL;
@@ -1751,30 +1851,36 @@ out:
1751 return ret; 1851 return ret;
1752} 1852}
1753 1853
1754#if 0
1755char *synthesize_perf_probe_command(struct perf_probe_event *pev) 1854char *synthesize_perf_probe_command(struct perf_probe_event *pev)
1756{ 1855{
1757 char *buf; 1856 struct strbuf buf;
1758 int i, len, ret; 1857 char *tmp, *ret = NULL;
1858 int i;
1759 1859
1760 buf = synthesize_perf_probe_point(&pev->point); 1860 if (strbuf_init(&buf, 64))
1761 if (!buf)
1762 return NULL; 1861 return NULL;
1862 if (pev->event)
1863 if (strbuf_addf(&buf, "%s:%s=", pev->group ?: PERFPROBE_GROUP,
1864 pev->event) < 0)
1865 goto out;
1866
1867 tmp = synthesize_perf_probe_point(&pev->point);
1868 if (!tmp || strbuf_addstr(&buf, tmp) < 0)
1869 goto out;
1870 free(tmp);
1763 1871
1764 len = strlen(buf);
1765 for (i = 0; i < pev->nargs; i++) { 1872 for (i = 0; i < pev->nargs; i++) {
1766 ret = e_snprintf(&buf[len], MAX_CMDLEN - len, " %s", 1873 tmp = synthesize_perf_probe_arg(pev->args + i);
1767 pev->args[i].name); 1874 if (!tmp || strbuf_addf(&buf, " %s", tmp) < 0)
1768 if (ret <= 0) { 1875 goto out;
1769 free(buf); 1876 free(tmp);
1770 return NULL;
1771 }
1772 len += ret;
1773 } 1877 }
1774 1878
1775 return buf; 1879 ret = strbuf_detach(&buf, NULL);
1880out:
1881 strbuf_release(&buf);
1882 return ret;
1776} 1883}
1777#endif
1778 1884
1779static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref, 1885static int __synthesize_probe_trace_arg_ref(struct probe_trace_arg_ref *ref,
1780 struct strbuf *buf, int depth) 1886 struct strbuf *buf, int depth)
@@ -1896,7 +2002,7 @@ static int find_perf_probe_point_from_map(struct probe_trace_point *tp,
1896 map = dso__new_map(tp->module); 2002 map = dso__new_map(tp->module);
1897 if (!map) 2003 if (!map)
1898 goto out; 2004 goto out;
1899 sym = map__find_symbol(map, addr, NULL); 2005 sym = map__find_symbol(map, addr);
1900 } else { 2006 } else {
1901 if (tp->symbol && !addr) { 2007 if (tp->symbol && !addr) {
1902 if (kernel_get_symbol_address_by_name(tp->symbol, 2008 if (kernel_get_symbol_address_by_name(tp->symbol,
@@ -2026,6 +2132,79 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
2026 memset(pev, 0, sizeof(*pev)); 2132 memset(pev, 0, sizeof(*pev));
2027} 2133}
2028 2134
2135#define strdup_or_goto(str, label) \
2136({ char *__p = NULL; if (str && !(__p = strdup(str))) goto label; __p; })
2137
2138static int perf_probe_point__copy(struct perf_probe_point *dst,
2139 struct perf_probe_point *src)
2140{
2141 dst->file = strdup_or_goto(src->file, out_err);
2142 dst->function = strdup_or_goto(src->function, out_err);
2143 dst->lazy_line = strdup_or_goto(src->lazy_line, out_err);
2144 dst->line = src->line;
2145 dst->retprobe = src->retprobe;
2146 dst->offset = src->offset;
2147 return 0;
2148
2149out_err:
2150 clear_perf_probe_point(dst);
2151 return -ENOMEM;
2152}
2153
2154static int perf_probe_arg__copy(struct perf_probe_arg *dst,
2155 struct perf_probe_arg *src)
2156{
2157 struct perf_probe_arg_field *field, **ppfield;
2158
2159 dst->name = strdup_or_goto(src->name, out_err);
2160 dst->var = strdup_or_goto(src->var, out_err);
2161 dst->type = strdup_or_goto(src->type, out_err);
2162
2163 field = src->field;
2164 ppfield = &(dst->field);
2165 while (field) {
2166 *ppfield = zalloc(sizeof(*field));
2167 if (!*ppfield)
2168 goto out_err;
2169 (*ppfield)->name = strdup_or_goto(field->name, out_err);
2170 (*ppfield)->index = field->index;
2171 (*ppfield)->ref = field->ref;
2172 field = field->next;
2173 ppfield = &((*ppfield)->next);
2174 }
2175 return 0;
2176out_err:
2177 return -ENOMEM;
2178}
2179
2180int perf_probe_event__copy(struct perf_probe_event *dst,
2181 struct perf_probe_event *src)
2182{
2183 int i;
2184
2185 dst->event = strdup_or_goto(src->event, out_err);
2186 dst->group = strdup_or_goto(src->group, out_err);
2187 dst->target = strdup_or_goto(src->target, out_err);
2188 dst->uprobes = src->uprobes;
2189
2190 if (perf_probe_point__copy(&dst->point, &src->point) < 0)
2191 goto out_err;
2192
2193 dst->args = zalloc(sizeof(struct perf_probe_arg) * src->nargs);
2194 if (!dst->args)
2195 goto out_err;
2196 dst->nargs = src->nargs;
2197
2198 for (i = 0; i < src->nargs; i++)
2199 if (perf_probe_arg__copy(&dst->args[i], &src->args[i]) < 0)
2200 goto out_err;
2201 return 0;
2202
2203out_err:
2204 clear_perf_probe_event(dst);
2205 return -ENOMEM;
2206}
2207
2029void clear_probe_trace_event(struct probe_trace_event *tev) 2208void clear_probe_trace_event(struct probe_trace_event *tev)
2030{ 2209{
2031 struct probe_trace_arg_ref *ref, *next; 2210 struct probe_trace_arg_ref *ref, *next;
@@ -2253,7 +2432,7 @@ static int __show_perf_probe_events(int fd, bool is_kprobe,
2253 if (!rawlist) 2432 if (!rawlist)
2254 return -ENOMEM; 2433 return -ENOMEM;
2255 2434
2256 strlist__for_each(ent, rawlist) { 2435 strlist__for_each_entry(ent, rawlist) {
2257 ret = parse_probe_trace_command(ent->s, &tev); 2436 ret = parse_probe_trace_command(ent->s, &tev);
2258 if (ret >= 0) { 2437 if (ret >= 0) {
2259 if (!filter_probe_trace_event(&tev, filter)) 2438 if (!filter_probe_trace_event(&tev, filter))
@@ -2286,6 +2465,9 @@ int show_perf_probe_events(struct strfilter *filter)
2286 2465
2287 setup_pager(); 2466 setup_pager();
2288 2467
2468 if (probe_conf.cache)
2469 return probe_cache__show_all_caches(filter);
2470
2289 ret = init_probe_symbol_maps(false); 2471 ret = init_probe_symbol_maps(false);
2290 if (ret < 0) 2472 if (ret < 0)
2291 return ret; 2473 return ret;
@@ -2394,17 +2576,24 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
2394 char buf[64]; 2576 char buf[64];
2395 int ret; 2577 int ret;
2396 2578
2397 if (pev->event) 2579 /* If probe_event or trace_event already have the name, reuse it */
2580 if (pev->event && !pev->sdt)
2398 event = pev->event; 2581 event = pev->event;
2399 else 2582 else if (tev->event)
2583 event = tev->event;
2584 else {
2585 /* Or generate new one from probe point */
2400 if (pev->point.function && 2586 if (pev->point.function &&
2401 (strncmp(pev->point.function, "0x", 2) != 0) && 2587 (strncmp(pev->point.function, "0x", 2) != 0) &&
2402 !strisglob(pev->point.function)) 2588 !strisglob(pev->point.function))
2403 event = pev->point.function; 2589 event = pev->point.function;
2404 else 2590 else
2405 event = tev->point.realname; 2591 event = tev->point.realname;
2406 if (pev->group) 2592 }
2593 if (pev->group && !pev->sdt)
2407 group = pev->group; 2594 group = pev->group;
2595 else if (tev->group)
2596 group = tev->group;
2408 else 2597 else
2409 group = PERFPROBE_GROUP; 2598 group = PERFPROBE_GROUP;
2410 2599
@@ -2426,40 +2615,60 @@ static int probe_trace_event__set_name(struct probe_trace_event *tev,
2426 return 0; 2615 return 0;
2427} 2616}
2428 2617
2429static int __add_probe_trace_events(struct perf_probe_event *pev, 2618static int __open_probe_file_and_namelist(bool uprobe,
2430 struct probe_trace_event *tevs, 2619 struct strlist **namelist)
2431 int ntevs, bool allow_suffix)
2432{ 2620{
2433 int i, fd, ret; 2621 int fd;
2434 struct probe_trace_event *tev = NULL;
2435 struct strlist *namelist;
2436 2622
2437 fd = probe_file__open(PF_FL_RW | (pev->uprobes ? PF_FL_UPROBE : 0)); 2623 fd = probe_file__open(PF_FL_RW | (uprobe ? PF_FL_UPROBE : 0));
2438 if (fd < 0) 2624 if (fd < 0)
2439 return fd; 2625 return fd;
2440 2626
2441 /* Get current event names */ 2627 /* Get current event names */
2442 namelist = probe_file__get_namelist(fd); 2628 *namelist = probe_file__get_namelist(fd);
2443 if (!namelist) { 2629 if (!(*namelist)) {
2444 pr_debug("Failed to get current event list.\n"); 2630 pr_debug("Failed to get current event list.\n");
2445 ret = -ENOMEM; 2631 close(fd);
2446 goto close_out; 2632 return -ENOMEM;
2447 } 2633 }
2634 return fd;
2635}
2636
2637static int __add_probe_trace_events(struct perf_probe_event *pev,
2638 struct probe_trace_event *tevs,
2639 int ntevs, bool allow_suffix)
2640{
2641 int i, fd[2] = {-1, -1}, up, ret;
2642 struct probe_trace_event *tev = NULL;
2643 struct probe_cache *cache = NULL;
2644 struct strlist *namelist[2] = {NULL, NULL};
2645
2646 up = pev->uprobes ? 1 : 0;
2647 fd[up] = __open_probe_file_and_namelist(up, &namelist[up]);
2648 if (fd[up] < 0)
2649 return fd[up];
2448 2650
2449 ret = 0; 2651 ret = 0;
2450 for (i = 0; i < ntevs; i++) { 2652 for (i = 0; i < ntevs; i++) {
2451 tev = &tevs[i]; 2653 tev = &tevs[i];
2654 up = tev->uprobes ? 1 : 0;
2655 if (fd[up] == -1) { /* Open the kprobe/uprobe_events */
2656 fd[up] = __open_probe_file_and_namelist(up,
2657 &namelist[up]);
2658 if (fd[up] < 0)
2659 goto close_out;
2660 }
2452 /* Skip if the symbol is out of .text or blacklisted */ 2661 /* Skip if the symbol is out of .text or blacklisted */
2453 if (!tev->point.symbol) 2662 if (!tev->point.symbol && !pev->uprobes)
2454 continue; 2663 continue;
2455 2664
2456 /* Set new name for tev (and update namelist) */ 2665 /* Set new name for tev (and update namelist) */
2457 ret = probe_trace_event__set_name(tev, pev, namelist, 2666 ret = probe_trace_event__set_name(tev, pev, namelist[up],
2458 allow_suffix); 2667 allow_suffix);
2459 if (ret < 0) 2668 if (ret < 0)
2460 break; 2669 break;
2461 2670
2462 ret = probe_file__add_event(fd, tev); 2671 ret = probe_file__add_event(fd[up], tev);
2463 if (ret < 0) 2672 if (ret < 0)
2464 break; 2673 break;
2465 2674
@@ -2473,10 +2682,21 @@ static int __add_probe_trace_events(struct perf_probe_event *pev,
2473 } 2682 }
2474 if (ret == -EINVAL && pev->uprobes) 2683 if (ret == -EINVAL && pev->uprobes)
2475 warn_uprobe_event_compat(tev); 2684 warn_uprobe_event_compat(tev);
2685 if (ret == 0 && probe_conf.cache) {
2686 cache = probe_cache__new(pev->target);
2687 if (!cache ||
2688 probe_cache__add_entry(cache, pev, tevs, ntevs) < 0 ||
2689 probe_cache__commit(cache) < 0)
2690 pr_warning("Failed to add event to probe cache\n");
2691 probe_cache__delete(cache);
2692 }
2476 2693
2477 strlist__delete(namelist);
2478close_out: 2694close_out:
2479 close(fd); 2695 for (up = 0; up < 2; up++) {
2696 strlist__delete(namelist[up]);
2697 if (fd[up] >= 0)
2698 close(fd[up]);
2699 }
2480 return ret; 2700 return ret;
2481} 2701}
2482 2702
@@ -2487,7 +2707,7 @@ static int find_probe_functions(struct map *map, char *name,
2487 struct symbol *sym; 2707 struct symbol *sym;
2488 struct rb_node *tmp; 2708 struct rb_node *tmp;
2489 2709
2490 if (map__load(map, NULL) < 0) 2710 if (map__load(map) < 0)
2491 return 0; 2711 return 0;
2492 2712
2493 map__for_each_symbol(map, sym, tmp) { 2713 map__for_each_symbol(map, sym, tmp) {
@@ -2501,9 +2721,6 @@ static int find_probe_functions(struct map *map, char *name,
2501 return found; 2721 return found;
2502} 2722}
2503 2723
2504#define strdup_or_goto(str, label) \
2505 ({ char *__p = strdup(str); if (!__p) goto label; __p; })
2506
2507void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused, 2724void __weak arch__fix_tev_from_maps(struct perf_probe_event *pev __maybe_unused,
2508 struct probe_trace_event *tev __maybe_unused, 2725 struct probe_trace_event *tev __maybe_unused,
2509 struct map *map __maybe_unused, 2726 struct map *map __maybe_unused,
@@ -2756,14 +2973,205 @@ errout:
2756 return err; 2973 return err;
2757} 2974}
2758 2975
2759bool __weak arch__prefers_symtab(void) { return false; } 2976/* Concatinate two arrays */
2977static void *memcat(void *a, size_t sz_a, void *b, size_t sz_b)
2978{
2979 void *ret;
2980
2981 ret = malloc(sz_a + sz_b);
2982 if (ret) {
2983 memcpy(ret, a, sz_a);
2984 memcpy(ret + sz_a, b, sz_b);
2985 }
2986 return ret;
2987}
2988
2989static int
2990concat_probe_trace_events(struct probe_trace_event **tevs, int *ntevs,
2991 struct probe_trace_event **tevs2, int ntevs2)
2992{
2993 struct probe_trace_event *new_tevs;
2994 int ret = 0;
2995
2996 if (ntevs == 0) {
2997 *tevs = *tevs2;
2998 *ntevs = ntevs2;
2999 *tevs2 = NULL;
3000 return 0;
3001 }
3002
3003 if (*ntevs + ntevs2 > probe_conf.max_probes)
3004 ret = -E2BIG;
3005 else {
3006 /* Concatinate the array of probe_trace_event */
3007 new_tevs = memcat(*tevs, (*ntevs) * sizeof(**tevs),
3008 *tevs2, ntevs2 * sizeof(**tevs2));
3009 if (!new_tevs)
3010 ret = -ENOMEM;
3011 else {
3012 free(*tevs);
3013 *tevs = new_tevs;
3014 *ntevs += ntevs2;
3015 }
3016 }
3017 if (ret < 0)
3018 clear_probe_trace_events(*tevs2, ntevs2);
3019 zfree(tevs2);
3020
3021 return ret;
3022}
3023
3024/*
3025 * Try to find probe_trace_event from given probe caches. Return the number
3026 * of cached events found, if an error occurs return the error.
3027 */
3028static int find_cached_events(struct perf_probe_event *pev,
3029 struct probe_trace_event **tevs,
3030 const char *target)
3031{
3032 struct probe_cache *cache;
3033 struct probe_cache_entry *entry;
3034 struct probe_trace_event *tmp_tevs = NULL;
3035 int ntevs = 0;
3036 int ret = 0;
3037
3038 cache = probe_cache__new(target);
3039 /* Return 0 ("not found") if the target has no probe cache. */
3040 if (!cache)
3041 return 0;
3042
3043 for_each_probe_cache_entry(entry, cache) {
3044 /* Skip the cache entry which has no name */
3045 if (!entry->pev.event || !entry->pev.group)
3046 continue;
3047 if ((!pev->group || strglobmatch(entry->pev.group, pev->group)) &&
3048 strglobmatch(entry->pev.event, pev->event)) {
3049 ret = probe_cache_entry__get_event(entry, &tmp_tevs);
3050 if (ret > 0)
3051 ret = concat_probe_trace_events(tevs, &ntevs,
3052 &tmp_tevs, ret);
3053 if (ret < 0)
3054 break;
3055 }
3056 }
3057 probe_cache__delete(cache);
3058 if (ret < 0) {
3059 clear_probe_trace_events(*tevs, ntevs);
3060 zfree(tevs);
3061 } else {
3062 ret = ntevs;
3063 if (ntevs > 0 && target && target[0] == '/')
3064 pev->uprobes = true;
3065 }
3066
3067 return ret;
3068}
3069
3070/* Try to find probe_trace_event from all probe caches */
3071static int find_cached_events_all(struct perf_probe_event *pev,
3072 struct probe_trace_event **tevs)
3073{
3074 struct probe_trace_event *tmp_tevs = NULL;
3075 struct strlist *bidlist;
3076 struct str_node *nd;
3077 char *pathname;
3078 int ntevs = 0;
3079 int ret;
3080
3081 /* Get the buildid list of all valid caches */
3082 bidlist = build_id_cache__list_all(true);
3083 if (!bidlist) {
3084 ret = -errno;
3085 pr_debug("Failed to get buildids: %d\n", ret);
3086 return ret;
3087 }
3088
3089 ret = 0;
3090 strlist__for_each_entry(nd, bidlist) {
3091 pathname = build_id_cache__origname(nd->s);
3092 ret = find_cached_events(pev, &tmp_tevs, pathname);
3093 /* In the case of cnt == 0, we just skip it */
3094 if (ret > 0)
3095 ret = concat_probe_trace_events(tevs, &ntevs,
3096 &tmp_tevs, ret);
3097 free(pathname);
3098 if (ret < 0)
3099 break;
3100 }
3101 strlist__delete(bidlist);
3102
3103 if (ret < 0) {
3104 clear_probe_trace_events(*tevs, ntevs);
3105 zfree(tevs);
3106 } else
3107 ret = ntevs;
3108
3109 return ret;
3110}
3111
3112static int find_probe_trace_events_from_cache(struct perf_probe_event *pev,
3113 struct probe_trace_event **tevs)
3114{
3115 struct probe_cache *cache;
3116 struct probe_cache_entry *entry;
3117 struct probe_trace_event *tev;
3118 struct str_node *node;
3119 int ret, i;
3120
3121 if (pev->sdt) {
3122 /* For SDT/cached events, we use special search functions */
3123 if (!pev->target)
3124 return find_cached_events_all(pev, tevs);
3125 else
3126 return find_cached_events(pev, tevs, pev->target);
3127 }
3128 cache = probe_cache__new(pev->target);
3129 if (!cache)
3130 return 0;
3131
3132 entry = probe_cache__find(cache, pev);
3133 if (!entry) {
3134 /* SDT must be in the cache */
3135 ret = pev->sdt ? -ENOENT : 0;
3136 goto out;
3137 }
3138
3139 ret = strlist__nr_entries(entry->tevlist);
3140 if (ret > probe_conf.max_probes) {
3141 pr_debug("Too many entries matched in the cache of %s\n",
3142 pev->target ? : "kernel");
3143 ret = -E2BIG;
3144 goto out;
3145 }
3146
3147 *tevs = zalloc(ret * sizeof(*tev));
3148 if (!*tevs) {
3149 ret = -ENOMEM;
3150 goto out;
3151 }
3152
3153 i = 0;
3154 strlist__for_each_entry(node, entry->tevlist) {
3155 tev = &(*tevs)[i++];
3156 ret = parse_probe_trace_command(node->s, tev);
3157 if (ret < 0)
3158 goto out;
3159 /* Set the uprobes attribute as same as original */
3160 tev->uprobes = pev->uprobes;
3161 }
3162 ret = i;
3163
3164out:
3165 probe_cache__delete(cache);
3166 return ret;
3167}
2760 3168
2761static int convert_to_probe_trace_events(struct perf_probe_event *pev, 3169static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2762 struct probe_trace_event **tevs) 3170 struct probe_trace_event **tevs)
2763{ 3171{
2764 int ret; 3172 int ret;
2765 3173
2766 if (!pev->group) { 3174 if (!pev->group && !pev->sdt) {
2767 /* Set group name if not given */ 3175 /* Set group name if not given */
2768 if (!pev->uprobes) { 3176 if (!pev->uprobes) {
2769 pev->group = strdup(PERFPROBE_GROUP); 3177 pev->group = strdup(PERFPROBE_GROUP);
@@ -2780,11 +3188,10 @@ static int convert_to_probe_trace_events(struct perf_probe_event *pev,
2780 if (ret > 0) 3188 if (ret > 0)
2781 return ret; 3189 return ret;
2782 3190
2783 if (arch__prefers_symtab() && !perf_probe_event_need_dwarf(pev)) { 3191 /* At first, we need to lookup cache entry */
2784 ret = find_probe_trace_events_from_map(pev, tevs); 3192 ret = find_probe_trace_events_from_cache(pev, tevs);
2785 if (ret > 0) 3193 if (ret > 0 || pev->sdt) /* SDT can be found only in the cache */
2786 return ret; /* Found in symbol table */ 3194 return ret == 0 ? -ENOENT : ret; /* Found in probe cache */
2787 }
2788 3195
2789 /* Convert perf_probe_event with debuginfo */ 3196 /* Convert perf_probe_event with debuginfo */
2790 ret = try_to_find_probe_trace_events(pev, tevs); 3197 ret = try_to_find_probe_trace_events(pev, tevs);
@@ -2815,6 +3222,52 @@ int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2815 return 0; 3222 return 0;
2816} 3223}
2817 3224
3225static int show_probe_trace_event(struct probe_trace_event *tev)
3226{
3227 char *buf = synthesize_probe_trace_command(tev);
3228
3229 if (!buf) {
3230 pr_debug("Failed to synthesize probe trace event.\n");
3231 return -EINVAL;
3232 }
3233
3234 /* Showing definition always go stdout */
3235 printf("%s\n", buf);
3236 free(buf);
3237
3238 return 0;
3239}
3240
3241int show_probe_trace_events(struct perf_probe_event *pevs, int npevs)
3242{
3243 struct strlist *namelist = strlist__new(NULL, NULL);
3244 struct probe_trace_event *tev;
3245 struct perf_probe_event *pev;
3246 int i, j, ret = 0;
3247
3248 if (!namelist)
3249 return -ENOMEM;
3250
3251 for (j = 0; j < npevs && !ret; j++) {
3252 pev = &pevs[j];
3253 for (i = 0; i < pev->ntevs && !ret; i++) {
3254 tev = &pev->tevs[i];
3255 /* Skip if the symbol is out of .text or blacklisted */
3256 if (!tev->point.symbol && !pev->uprobes)
3257 continue;
3258
3259 /* Set new name for tev (and update namelist) */
3260 ret = probe_trace_event__set_name(tev, pev,
3261 namelist, true);
3262 if (!ret)
3263 ret = show_probe_trace_event(tev);
3264 }
3265 }
3266 strlist__delete(namelist);
3267
3268 return ret;
3269}
3270
2818int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs) 3271int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs)
2819{ 3272{
2820 int i, ret = 0; 3273 int i, ret = 0;
@@ -2897,24 +3350,10 @@ out:
2897 return ret; 3350 return ret;
2898} 3351}
2899 3352
2900/* TODO: don't use a global variable for filter ... */
2901static struct strfilter *available_func_filter;
2902
2903/*
2904 * If a symbol corresponds to a function with global binding and
2905 * matches filter return 0. For all others return 1.
2906 */
2907static int filter_available_functions(struct map *map __maybe_unused,
2908 struct symbol *sym)
2909{
2910 if (strfilter__compare(available_func_filter, sym->name))
2911 return 0;
2912 return 1;
2913}
2914
2915int show_available_funcs(const char *target, struct strfilter *_filter, 3353int show_available_funcs(const char *target, struct strfilter *_filter,
2916 bool user) 3354 bool user)
2917{ 3355{
3356 struct rb_node *nd;
2918 struct map *map; 3357 struct map *map;
2919 int ret; 3358 int ret;
2920 3359
@@ -2932,10 +3371,16 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
2932 return -EINVAL; 3371 return -EINVAL;
2933 } 3372 }
2934 3373
2935 /* Load symbols with given filter */ 3374 ret = map__load(map);
2936 available_func_filter = _filter; 3375 if (ret) {
2937 if (map__load(map, filter_available_functions)) { 3376 if (ret == -2) {
2938 pr_err("Failed to load symbols in %s\n", (target) ? : "kernel"); 3377 char *str = strfilter__string(_filter);
3378 pr_err("Failed to find symbols matched to \"%s\"\n",
3379 str);
3380 free(str);
3381 } else
3382 pr_err("Failed to load symbols in %s\n",
3383 (target) ? : "kernel");
2939 goto end; 3384 goto end;
2940 } 3385 }
2941 if (!dso__sorted_by_name(map->dso, map->type)) 3386 if (!dso__sorted_by_name(map->dso, map->type))
@@ -2943,7 +3388,14 @@ int show_available_funcs(const char *target, struct strfilter *_filter,
2943 3388
2944 /* Show all (filtered) symbols */ 3389 /* Show all (filtered) symbols */
2945 setup_pager(); 3390 setup_pager();
2946 dso__fprintf_symbols_by_name(map->dso, map->type, stdout); 3391
3392 for (nd = rb_first(&map->dso->symbol_names[map->type]); nd; nd = rb_next(nd)) {
3393 struct symbol_name_rb_node *pos = rb_entry(nd, struct symbol_name_rb_node, rb_node);
3394
3395 if (strfilter__compare(_filter, pos->sym.name))
3396 printf("%s\n", pos->sym.name);
3397 }
3398
2947end: 3399end:
2948 if (user) { 3400 if (user) {
2949 map__put(map); 3401 map__put(map);
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index 5a27eb4fad05..8091d15113f7 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 */
@@ -121,6 +123,12 @@ int parse_probe_trace_command(const char *cmd, struct probe_trace_event *tev);
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);
123char *synthesize_perf_probe_arg(struct perf_probe_arg *pa); 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);
130
131bool perf_probe_with_var(struct perf_probe_event *pev);
124 132
125/* Check the perf_probe_event needs debuginfo */ 133/* Check the perf_probe_event needs debuginfo */
126bool perf_probe_event_need_dwarf(struct perf_probe_event *pev); 134bool perf_probe_event_need_dwarf(struct perf_probe_event *pev);
@@ -141,6 +149,7 @@ int line_range__init(struct line_range *lr);
141int add_perf_probe_events(struct perf_probe_event *pevs, int npevs); 149int add_perf_probe_events(struct perf_probe_event *pevs, int npevs);
142int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs); 150int convert_perf_probe_events(struct perf_probe_event *pevs, int npevs);
143int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs); 151int apply_perf_probe_events(struct perf_probe_event *pevs, int npevs);
152int show_probe_trace_events(struct perf_probe_event *pevs, int npevs);
144void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs); 153void cleanup_perf_probe_events(struct perf_probe_event *pevs, int npevs);
145int del_perf_probe_events(struct strfilter *filter); 154int del_perf_probe_events(struct strfilter *filter);
146 155
@@ -152,7 +161,6 @@ int show_line_range(struct line_range *lr, const char *module, bool user);
152int show_available_vars(struct perf_probe_event *pevs, int npevs, 161int show_available_vars(struct perf_probe_event *pevs, int npevs,
153 struct strfilter *filter); 162 struct strfilter *filter);
154int show_available_funcs(const char *module, struct strfilter *filter, bool user); 163int 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, 164void arch__fix_tev_from_maps(struct perf_probe_event *pev,
157 struct probe_trace_event *tev, struct map *map, 165 struct probe_trace_event *tev, struct map *map,
158 struct symbol *sym); 166 struct symbol *sym);
@@ -167,4 +175,9 @@ int e_snprintf(char *str, size_t size, const char *format, ...)
167int copy_to_probe_trace_arg(struct probe_trace_arg *tvar, 175int copy_to_probe_trace_arg(struct probe_trace_arg *tvar,
168 struct perf_probe_arg *pvar); 176 struct perf_probe_arg *pvar);
169 177
178struct map *get_target_map(const char *target, bool user);
179
180void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
181 int ntevs);
182
170#endif /*_PROBE_EVENT_H */ 183#endif /*_PROBE_EVENT_H */
diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c
index 3fe6214970e6..436b64731f65 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,20 +64,19 @@ 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
72static int open_probe_events(const char *trace_file, bool readwrite) 73static int open_probe_events(const char *trace_file, bool readwrite)
73{ 74{
74 char buf[PATH_MAX]; 75 char buf[PATH_MAX];
75 const char *tracing_dir = "";
76 int ret; 76 int ret;
77 77
78 ret = e_snprintf(buf, PATH_MAX, "%s/%s%s", 78 ret = e_snprintf(buf, PATH_MAX, "%s/%s",
79 tracing_path, tracing_dir, trace_file); 79 tracing_path, trace_file);
80 if (ret >= 0) { 80 if (ret >= 0) {
81 pr_debug("Opening %s write=%d\n", buf, readwrite); 81 pr_debug("Opening %s write=%d\n", buf, readwrite);
82 if (readwrite && !probe_event_dry_run) 82 if (readwrite && !probe_event_dry_run)
@@ -132,7 +132,7 @@ int probe_file__open_both(int *kfd, int *ufd, int flag)
132/* Get raw string list of current kprobe_events or uprobe_events */ 132/* Get raw string list of current kprobe_events or uprobe_events */
133struct strlist *probe_file__get_rawlist(int fd) 133struct strlist *probe_file__get_rawlist(int fd)
134{ 134{
135 int ret, idx; 135 int ret, idx, fddup;
136 FILE *fp; 136 FILE *fp;
137 char buf[MAX_CMDLEN]; 137 char buf[MAX_CMDLEN];
138 char *p; 138 char *p;
@@ -142,8 +142,17 @@ struct strlist *probe_file__get_rawlist(int fd)
142 return NULL; 142 return NULL;
143 143
144 sl = strlist__new(NULL, NULL); 144 sl = strlist__new(NULL, NULL);
145 if (sl == NULL)
146 return NULL;
147
148 fddup = dup(fd);
149 if (fddup < 0)
150 goto out_free_sl;
151
152 fp = fdopen(fddup, "r");
153 if (!fp)
154 goto out_close_fddup;
145 155
146 fp = fdopen(dup(fd), "r");
147 while (!feof(fp)) { 156 while (!feof(fp)) {
148 p = fgets(buf, MAX_CMDLEN, fp); 157 p = fgets(buf, MAX_CMDLEN, fp);
149 if (!p) 158 if (!p)
@@ -155,13 +164,21 @@ struct strlist *probe_file__get_rawlist(int fd)
155 ret = strlist__add(sl, buf); 164 ret = strlist__add(sl, buf);
156 if (ret < 0) { 165 if (ret < 0) {
157 pr_debug("strlist__add failed (%d)\n", ret); 166 pr_debug("strlist__add failed (%d)\n", ret);
158 strlist__delete(sl); 167 goto out_close_fp;
159 return NULL;
160 } 168 }
161 } 169 }
162 fclose(fp); 170 fclose(fp);
163 171
164 return sl; 172 return sl;
173
174out_close_fp:
175 fclose(fp);
176 goto out_free_sl;
177out_close_fddup:
178 close(fddup);
179out_free_sl:
180 strlist__delete(sl);
181 return NULL;
165} 182}
166 183
167static struct strlist *__probe_file__get_namelist(int fd, bool include_group) 184static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
@@ -177,7 +194,7 @@ static struct strlist *__probe_file__get_namelist(int fd, bool include_group)
177 if (!rawlist) 194 if (!rawlist)
178 return NULL; 195 return NULL;
179 sl = strlist__new(NULL, NULL); 196 sl = strlist__new(NULL, NULL);
180 strlist__for_each(ent, rawlist) { 197 strlist__for_each_entry(ent, rawlist) {
181 ret = parse_probe_trace_command(ent->s, &tev); 198 ret = parse_probe_trace_command(ent->s, &tev);
182 if (ret < 0) 199 if (ret < 0)
183 break; 200 break;
@@ -223,7 +240,7 @@ int probe_file__add_event(int fd, struct probe_trace_event *tev)
223 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) { 240 if (write(fd, buf, strlen(buf)) < (int)strlen(buf)) {
224 ret = -errno; 241 ret = -errno;
225 pr_warning("Failed to write event: %s\n", 242 pr_warning("Failed to write event: %s\n",
226 strerror_r(errno, sbuf, sizeof(sbuf))); 243 str_error_r(errno, sbuf, sizeof(sbuf)));
227 } 244 }
228 } 245 }
229 free(buf); 246 free(buf);
@@ -261,7 +278,7 @@ static int __del_trace_probe_event(int fd, struct str_node *ent)
261 return 0; 278 return 0;
262error: 279error:
263 pr_warning("Failed to delete event: %s\n", 280 pr_warning("Failed to delete event: %s\n",
264 strerror_r(-ret, buf, sizeof(buf))); 281 str_error_r(-ret, buf, sizeof(buf)));
265 return ret; 282 return ret;
266} 283}
267 284
@@ -280,7 +297,7 @@ int probe_file__get_events(int fd, struct strfilter *filter,
280 if (!namelist) 297 if (!namelist)
281 return -ENOENT; 298 return -ENOENT;
282 299
283 strlist__for_each(ent, namelist) { 300 strlist__for_each_entry(ent, namelist) {
284 p = strchr(ent->s, ':'); 301 p = strchr(ent->s, ':');
285 if ((p && strfilter__compare(filter, p + 1)) || 302 if ((p && strfilter__compare(filter, p + 1)) ||
286 strfilter__compare(filter, ent->s)) { 303 strfilter__compare(filter, ent->s)) {
@@ -298,7 +315,7 @@ int probe_file__del_strlist(int fd, struct strlist *namelist)
298 int ret = 0; 315 int ret = 0;
299 struct str_node *ent; 316 struct str_node *ent;
300 317
301 strlist__for_each(ent, namelist) { 318 strlist__for_each_entry(ent, namelist) {
302 ret = __del_trace_probe_event(fd, ent); 319 ret = __del_trace_probe_event(fd, ent);
303 if (ret < 0) 320 if (ret < 0)
304 break; 321 break;
@@ -324,3 +341,595 @@ int probe_file__del_events(int fd, struct strfilter *filter)
324 341
325 return ret; 342 return ret;
326} 343}
344
345/* Caller must ensure to remove this entry from list */
346static void probe_cache_entry__delete(struct probe_cache_entry *entry)
347{
348 if (entry) {
349 BUG_ON(!list_empty(&entry->node));
350
351 strlist__delete(entry->tevlist);
352 clear_perf_probe_event(&entry->pev);
353 zfree(&entry->spev);
354 free(entry);
355 }
356}
357
358static struct probe_cache_entry *
359probe_cache_entry__new(struct perf_probe_event *pev)
360{
361 struct probe_cache_entry *entry = zalloc(sizeof(*entry));
362
363 if (entry) {
364 INIT_LIST_HEAD(&entry->node);
365 entry->tevlist = strlist__new(NULL, NULL);
366 if (!entry->tevlist)
367 zfree(&entry);
368 else if (pev) {
369 entry->spev = synthesize_perf_probe_command(pev);
370 if (!entry->spev ||
371 perf_probe_event__copy(&entry->pev, pev) < 0) {
372 probe_cache_entry__delete(entry);
373 return NULL;
374 }
375 }
376 }
377
378 return entry;
379}
380
381int probe_cache_entry__get_event(struct probe_cache_entry *entry,
382 struct probe_trace_event **tevs)
383{
384 struct probe_trace_event *tev;
385 struct str_node *node;
386 int ret, i;
387
388 ret = strlist__nr_entries(entry->tevlist);
389 if (ret > probe_conf.max_probes)
390 return -E2BIG;
391
392 *tevs = zalloc(ret * sizeof(*tev));
393 if (!*tevs)
394 return -ENOMEM;
395
396 i = 0;
397 strlist__for_each_entry(node, entry->tevlist) {
398 tev = &(*tevs)[i++];
399 ret = parse_probe_trace_command(node->s, tev);
400 if (ret < 0)
401 break;
402 }
403 return i;
404}
405
406/* For the kernel probe caches, pass target = NULL or DSO__NAME_KALLSYMS */
407static int probe_cache__open(struct probe_cache *pcache, const char *target)
408{
409 char cpath[PATH_MAX];
410 char sbuildid[SBUILD_ID_SIZE];
411 char *dir_name = NULL;
412 bool is_kallsyms = false;
413 int ret, fd;
414
415 if (target && build_id_cache__cached(target)) {
416 /* This is a cached buildid */
417 strncpy(sbuildid, target, SBUILD_ID_SIZE);
418 dir_name = build_id_cache__linkname(sbuildid, NULL, 0);
419 goto found;
420 }
421
422 if (!target || !strcmp(target, DSO__NAME_KALLSYMS)) {
423 target = DSO__NAME_KALLSYMS;
424 is_kallsyms = true;
425 ret = sysfs__sprintf_build_id("/", sbuildid);
426 } else
427 ret = filename__sprintf_build_id(target, sbuildid);
428
429 if (ret < 0) {
430 pr_debug("Failed to get build-id from %s.\n", target);
431 return ret;
432 }
433
434 /* If we have no buildid cache, make it */
435 if (!build_id_cache__cached(sbuildid)) {
436 ret = build_id_cache__add_s(sbuildid, target,
437 is_kallsyms, NULL);
438 if (ret < 0) {
439 pr_debug("Failed to add build-id cache: %s\n", target);
440 return ret;
441 }
442 }
443
444 dir_name = build_id_cache__cachedir(sbuildid, target, is_kallsyms,
445 false);
446found:
447 if (!dir_name) {
448 pr_debug("Failed to get cache from %s\n", target);
449 return -ENOMEM;
450 }
451
452 snprintf(cpath, PATH_MAX, "%s/probes", dir_name);
453 fd = open(cpath, O_CREAT | O_RDWR, 0644);
454 if (fd < 0)
455 pr_debug("Failed to open cache(%d): %s\n", fd, cpath);
456 free(dir_name);
457 pcache->fd = fd;
458
459 return fd;
460}
461
462static int probe_cache__load(struct probe_cache *pcache)
463{
464 struct probe_cache_entry *entry = NULL;
465 char buf[MAX_CMDLEN], *p;
466 int ret = 0, fddup;
467 FILE *fp;
468
469 fddup = dup(pcache->fd);
470 if (fddup < 0)
471 return -errno;
472 fp = fdopen(fddup, "r");
473 if (!fp) {
474 close(fddup);
475 return -EINVAL;
476 }
477
478 while (!feof(fp)) {
479 if (!fgets(buf, MAX_CMDLEN, fp))
480 break;
481 p = strchr(buf, '\n');
482 if (p)
483 *p = '\0';
484 /* #perf_probe_event or %sdt_event */
485 if (buf[0] == '#' || buf[0] == '%') {
486 entry = probe_cache_entry__new(NULL);
487 if (!entry) {
488 ret = -ENOMEM;
489 goto out;
490 }
491 if (buf[0] == '%')
492 entry->sdt = true;
493 entry->spev = strdup(buf + 1);
494 if (entry->spev)
495 ret = parse_perf_probe_command(buf + 1,
496 &entry->pev);
497 else
498 ret = -ENOMEM;
499 if (ret < 0) {
500 probe_cache_entry__delete(entry);
501 goto out;
502 }
503 list_add_tail(&entry->node, &pcache->entries);
504 } else { /* trace_probe_event */
505 if (!entry) {
506 ret = -EINVAL;
507 goto out;
508 }
509 strlist__add(entry->tevlist, buf);
510 }
511 }
512out:
513 fclose(fp);
514 return ret;
515}
516
517static struct probe_cache *probe_cache__alloc(void)
518{
519 struct probe_cache *pcache = zalloc(sizeof(*pcache));
520
521 if (pcache) {
522 INIT_LIST_HEAD(&pcache->entries);
523 pcache->fd = -EINVAL;
524 }
525 return pcache;
526}
527
528void probe_cache__purge(struct probe_cache *pcache)
529{
530 struct probe_cache_entry *entry, *n;
531
532 list_for_each_entry_safe(entry, n, &pcache->entries, node) {
533 list_del_init(&entry->node);
534 probe_cache_entry__delete(entry);
535 }
536}
537
538void probe_cache__delete(struct probe_cache *pcache)
539{
540 if (!pcache)
541 return;
542
543 probe_cache__purge(pcache);
544 if (pcache->fd > 0)
545 close(pcache->fd);
546 free(pcache);
547}
548
549struct probe_cache *probe_cache__new(const char *target)
550{
551 struct probe_cache *pcache = probe_cache__alloc();
552 int ret;
553
554 if (!pcache)
555 return NULL;
556
557 ret = probe_cache__open(pcache, target);
558 if (ret < 0) {
559 pr_debug("Cache open error: %d\n", ret);
560 goto out_err;
561 }
562
563 ret = probe_cache__load(pcache);
564 if (ret < 0) {
565 pr_debug("Cache read error: %d\n", ret);
566 goto out_err;
567 }
568
569 return pcache;
570
571out_err:
572 probe_cache__delete(pcache);
573 return NULL;
574}
575
576static bool streql(const char *a, const char *b)
577{
578 if (a == b)
579 return true;
580
581 if (!a || !b)
582 return false;
583
584 return !strcmp(a, b);
585}
586
587struct probe_cache_entry *
588probe_cache__find(struct probe_cache *pcache, struct perf_probe_event *pev)
589{
590 struct probe_cache_entry *entry = NULL;
591 char *cmd = synthesize_perf_probe_command(pev);
592
593 if (!cmd)
594 return NULL;
595
596 for_each_probe_cache_entry(entry, pcache) {
597 if (pev->sdt) {
598 if (entry->pev.event &&
599 streql(entry->pev.event, pev->event) &&
600 (!pev->group ||
601 streql(entry->pev.group, pev->group)))
602 goto found;
603
604 continue;
605 }
606 /* Hit if same event name or same command-string */
607 if ((pev->event &&
608 (streql(entry->pev.group, pev->group) &&
609 streql(entry->pev.event, pev->event))) ||
610 (!strcmp(entry->spev, cmd)))
611 goto found;
612 }
613 entry = NULL;
614
615found:
616 free(cmd);
617 return entry;
618}
619
620struct probe_cache_entry *
621probe_cache__find_by_name(struct probe_cache *pcache,
622 const char *group, const char *event)
623{
624 struct probe_cache_entry *entry = NULL;
625
626 for_each_probe_cache_entry(entry, pcache) {
627 /* Hit if same event name or same command-string */
628 if (streql(entry->pev.group, group) &&
629 streql(entry->pev.event, event))
630 goto found;
631 }
632 entry = NULL;
633
634found:
635 return entry;
636}
637
638int probe_cache__add_entry(struct probe_cache *pcache,
639 struct perf_probe_event *pev,
640 struct probe_trace_event *tevs, int ntevs)
641{
642 struct probe_cache_entry *entry = NULL;
643 char *command;
644 int i, ret = 0;
645
646 if (!pcache || !pev || !tevs || ntevs <= 0) {
647 ret = -EINVAL;
648 goto out_err;
649 }
650
651 /* Remove old cache entry */
652 entry = probe_cache__find(pcache, pev);
653 if (entry) {
654 list_del_init(&entry->node);
655 probe_cache_entry__delete(entry);
656 }
657
658 ret = -ENOMEM;
659 entry = probe_cache_entry__new(pev);
660 if (!entry)
661 goto out_err;
662
663 for (i = 0; i < ntevs; i++) {
664 if (!tevs[i].point.symbol)
665 continue;
666
667 command = synthesize_probe_trace_command(&tevs[i]);
668 if (!command)
669 goto out_err;
670 strlist__add(entry->tevlist, command);
671 free(command);
672 }
673 list_add_tail(&entry->node, &pcache->entries);
674 pr_debug("Added probe cache: %d\n", ntevs);
675 return 0;
676
677out_err:
678 pr_debug("Failed to add probe caches\n");
679 probe_cache_entry__delete(entry);
680 return ret;
681}
682
683#ifdef HAVE_GELF_GETNOTE_SUPPORT
684static unsigned long long sdt_note__get_addr(struct sdt_note *note)
685{
686 return note->bit32 ? (unsigned long long)note->addr.a32[0]
687 : (unsigned long long)note->addr.a64[0];
688}
689
690int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname)
691{
692 struct probe_cache_entry *entry = NULL;
693 struct list_head sdtlist;
694 struct sdt_note *note;
695 char *buf;
696 char sdtgrp[64];
697 int ret;
698
699 INIT_LIST_HEAD(&sdtlist);
700 ret = get_sdt_note_list(&sdtlist, pathname);
701 if (ret < 0) {
702 pr_debug4("Failed to get sdt note: %d\n", ret);
703 return ret;
704 }
705 list_for_each_entry(note, &sdtlist, note_list) {
706 ret = snprintf(sdtgrp, 64, "sdt_%s", note->provider);
707 if (ret < 0)
708 break;
709 /* Try to find same-name entry */
710 entry = probe_cache__find_by_name(pcache, sdtgrp, note->name);
711 if (!entry) {
712 entry = probe_cache_entry__new(NULL);
713 if (!entry) {
714 ret = -ENOMEM;
715 break;
716 }
717 entry->sdt = true;
718 ret = asprintf(&entry->spev, "%s:%s=%s", sdtgrp,
719 note->name, note->name);
720 if (ret < 0)
721 break;
722 entry->pev.event = strdup(note->name);
723 entry->pev.group = strdup(sdtgrp);
724 list_add_tail(&entry->node, &pcache->entries);
725 }
726 ret = asprintf(&buf, "p:%s/%s %s:0x%llx",
727 sdtgrp, note->name, pathname,
728 sdt_note__get_addr(note));
729 if (ret < 0)
730 break;
731 strlist__add(entry->tevlist, buf);
732 free(buf);
733 entry = NULL;
734 }
735 if (entry) {
736 list_del_init(&entry->node);
737 probe_cache_entry__delete(entry);
738 }
739 cleanup_sdt_note_list(&sdtlist);
740 return ret;
741}
742#endif
743
744static int probe_cache_entry__write(struct probe_cache_entry *entry, int fd)
745{
746 struct str_node *snode;
747 struct stat st;
748 struct iovec iov[3];
749 const char *prefix = entry->sdt ? "%" : "#";
750 int ret;
751 /* Save stat for rollback */
752 ret = fstat(fd, &st);
753 if (ret < 0)
754 return ret;
755
756 pr_debug("Writing cache: %s%s\n", prefix, entry->spev);
757 iov[0].iov_base = (void *)prefix; iov[0].iov_len = 1;
758 iov[1].iov_base = entry->spev; iov[1].iov_len = strlen(entry->spev);
759 iov[2].iov_base = (void *)"\n"; iov[2].iov_len = 1;
760 ret = writev(fd, iov, 3);
761 if (ret < (int)iov[1].iov_len + 2)
762 goto rollback;
763
764 strlist__for_each_entry(snode, entry->tevlist) {
765 iov[0].iov_base = (void *)snode->s;
766 iov[0].iov_len = strlen(snode->s);
767 iov[1].iov_base = (void *)"\n"; iov[1].iov_len = 1;
768 ret = writev(fd, iov, 2);
769 if (ret < (int)iov[0].iov_len + 1)
770 goto rollback;
771 }
772 return 0;
773
774rollback:
775 /* Rollback to avoid cache file corruption */
776 if (ret > 0)
777 ret = -1;
778 if (ftruncate(fd, st.st_size) < 0)
779 ret = -2;
780
781 return ret;
782}
783
784int probe_cache__commit(struct probe_cache *pcache)
785{
786 struct probe_cache_entry *entry;
787 int ret = 0;
788
789 /* TBD: if we do not update existing entries, skip it */
790 ret = lseek(pcache->fd, 0, SEEK_SET);
791 if (ret < 0)
792 goto out;
793
794 ret = ftruncate(pcache->fd, 0);
795 if (ret < 0)
796 goto out;
797
798 for_each_probe_cache_entry(entry, pcache) {
799 ret = probe_cache_entry__write(entry, pcache->fd);
800 pr_debug("Cache committed: %d\n", ret);
801 if (ret < 0)
802 break;
803 }
804out:
805 return ret;
806}
807
808static bool probe_cache_entry__compare(struct probe_cache_entry *entry,
809 struct strfilter *filter)
810{
811 char buf[128], *ptr = entry->spev;
812
813 if (entry->pev.event) {
814 snprintf(buf, 128, "%s:%s", entry->pev.group, entry->pev.event);
815 ptr = buf;
816 }
817 return strfilter__compare(filter, ptr);
818}
819
820int probe_cache__filter_purge(struct probe_cache *pcache,
821 struct strfilter *filter)
822{
823 struct probe_cache_entry *entry, *tmp;
824
825 list_for_each_entry_safe(entry, tmp, &pcache->entries, node) {
826 if (probe_cache_entry__compare(entry, filter)) {
827 pr_info("Removed cached event: %s\n", entry->spev);
828 list_del_init(&entry->node);
829 probe_cache_entry__delete(entry);
830 }
831 }
832 return 0;
833}
834
835static int probe_cache__show_entries(struct probe_cache *pcache,
836 struct strfilter *filter)
837{
838 struct probe_cache_entry *entry;
839
840 for_each_probe_cache_entry(entry, pcache) {
841 if (probe_cache_entry__compare(entry, filter))
842 printf("%s\n", entry->spev);
843 }
844 return 0;
845}
846
847/* Show all cached probes */
848int probe_cache__show_all_caches(struct strfilter *filter)
849{
850 struct probe_cache *pcache;
851 struct strlist *bidlist;
852 struct str_node *nd;
853 char *buf = strfilter__string(filter);
854
855 pr_debug("list cache with filter: %s\n", buf);
856 free(buf);
857
858 bidlist = build_id_cache__list_all(true);
859 if (!bidlist) {
860 pr_debug("Failed to get buildids: %d\n", errno);
861 return -EINVAL;
862 }
863 strlist__for_each_entry(nd, bidlist) {
864 pcache = probe_cache__new(nd->s);
865 if (!pcache)
866 continue;
867 if (!list_empty(&pcache->entries)) {
868 buf = build_id_cache__origname(nd->s);
869 printf("%s (%s):\n", buf, nd->s);
870 free(buf);
871 probe_cache__show_entries(pcache, filter);
872 }
873 probe_cache__delete(pcache);
874 }
875 strlist__delete(bidlist);
876
877 return 0;
878}
879
880static struct {
881 const char *pattern;
882 bool avail;
883 bool checked;
884} probe_type_table[] = {
885#define DEFINE_TYPE(idx, pat, def_avail) \
886 [idx] = {.pattern = pat, .avail = (def_avail)}
887 DEFINE_TYPE(PROBE_TYPE_U, "* u8/16/32/64,*", true),
888 DEFINE_TYPE(PROBE_TYPE_S, "* s8/16/32/64,*", true),
889 DEFINE_TYPE(PROBE_TYPE_X, "* x8/16/32/64,*", false),
890 DEFINE_TYPE(PROBE_TYPE_STRING, "* string,*", true),
891 DEFINE_TYPE(PROBE_TYPE_BITFIELD,
892 "* b<bit-width>@<bit-offset>/<container-size>", true),
893};
894
895bool probe_type_is_available(enum probe_type type)
896{
897 FILE *fp;
898 char *buf = NULL;
899 size_t len = 0;
900 bool target_line = false;
901 bool ret = probe_type_table[type].avail;
902
903 if (type >= PROBE_TYPE_END)
904 return false;
905 /* We don't have to check the type which supported by default */
906 if (ret || probe_type_table[type].checked)
907 return ret;
908
909 if (asprintf(&buf, "%s/README", tracing_path) < 0)
910 return ret;
911
912 fp = fopen(buf, "r");
913 if (!fp)
914 goto end;
915
916 zfree(&buf);
917 while (getline(&buf, &len, fp) > 0 && !ret) {
918 if (!target_line) {
919 target_line = !!strstr(buf, " type: ");
920 if (!target_line)
921 continue;
922 } else if (strstr(buf, "\t ") != buf)
923 break;
924 ret = strglobmatch(buf, probe_type_table[type].pattern);
925 }
926 /* Cache the result */
927 probe_type_table[type].checked = true;
928 probe_type_table[type].avail = ret;
929
930 fclose(fp);
931end:
932 free(buf);
933
934 return ret;
935}
diff --git a/tools/perf/util/probe-file.h b/tools/perf/util/probe-file.h
index 18ac9cf51c34..eba44c3e9dca 100644
--- a/tools/perf/util/probe-file.h
+++ b/tools/perf/util/probe-file.h
@@ -5,9 +5,36 @@
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
22enum probe_type {
23 PROBE_TYPE_U = 0,
24 PROBE_TYPE_S,
25 PROBE_TYPE_X,
26 PROBE_TYPE_STRING,
27 PROBE_TYPE_BITFIELD,
28 PROBE_TYPE_END,
29};
30
8#define PF_FL_UPROBE 1 31#define PF_FL_UPROBE 1
9#define PF_FL_RW 2 32#define PF_FL_RW 2
33#define for_each_probe_cache_entry(entry, pcache) \
34 list_for_each_entry(entry, &pcache->entries, node)
10 35
36/* probe-file.c depends on libelf */
37#ifdef HAVE_LIBELF_SUPPORT
11int probe_file__open(int flag); 38int probe_file__open(int flag);
12int probe_file__open_both(int *kfd, int *ufd, int flag); 39int probe_file__open_both(int *kfd, int *ufd, int flag);
13struct strlist *probe_file__get_namelist(int fd); 40struct strlist *probe_file__get_namelist(int fd);
@@ -18,5 +45,30 @@ int probe_file__get_events(int fd, struct strfilter *filter,
18 struct strlist *plist); 45 struct strlist *plist);
19int probe_file__del_strlist(int fd, struct strlist *namelist); 46int probe_file__del_strlist(int fd, struct strlist *namelist);
20 47
48int probe_cache_entry__get_event(struct probe_cache_entry *entry,
49 struct probe_trace_event **tevs);
21 50
51struct probe_cache *probe_cache__new(const char *target);
52int probe_cache__add_entry(struct probe_cache *pcache,
53 struct perf_probe_event *pev,
54 struct probe_trace_event *tevs, int ntevs);
55int probe_cache__scan_sdt(struct probe_cache *pcache, const char *pathname);
56int probe_cache__commit(struct probe_cache *pcache);
57void probe_cache__purge(struct probe_cache *pcache);
58void probe_cache__delete(struct probe_cache *pcache);
59int probe_cache__filter_purge(struct probe_cache *pcache,
60 struct strfilter *filter);
61struct probe_cache_entry *probe_cache__find(struct probe_cache *pcache,
62 struct perf_probe_event *pev);
63struct probe_cache_entry *probe_cache__find_by_name(struct probe_cache *pcache,
64 const char *group, const char *event);
65int probe_cache__show_all_caches(struct strfilter *filter);
66bool probe_type_is_available(enum probe_type type);
67#else /* ! HAVE_LIBELF_SUPPORT */
68static inline struct probe_cache *probe_cache__new(const char *tgt __maybe_unused)
69{
70 return NULL;
71}
72#define probe_cache__delete(pcache) do {} while (0)
73#endif
22#endif 74#endif
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index 1259839dbf6d..df4debe564da 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -39,6 +39,7 @@
39#include "util.h" 39#include "util.h"
40#include "symbol.h" 40#include "symbol.h"
41#include "probe-finder.h" 41#include "probe-finder.h"
42#include "probe-file.h"
42 43
43/* Kprobe tracer basic type is up to u64 */ 44/* Kprobe tracer basic type is up to u64 */
44#define MAX_BASIC_TYPE_BITS 64 45#define MAX_BASIC_TYPE_BITS 64
@@ -170,6 +171,7 @@ static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs)
170 */ 171 */
171static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, 172static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr,
172 Dwarf_Op *fb_ops, Dwarf_Die *sp_die, 173 Dwarf_Op *fb_ops, Dwarf_Die *sp_die,
174 unsigned int machine,
173 struct probe_trace_arg *tvar) 175 struct probe_trace_arg *tvar)
174{ 176{
175 Dwarf_Attribute attr; 177 Dwarf_Attribute attr;
@@ -265,7 +267,7 @@ static_var:
265 if (!tvar) 267 if (!tvar)
266 return ret2; 268 return ret2;
267 269
268 regs = get_arch_regstr(regn); 270 regs = get_dwarf_regstr(regn, machine);
269 if (!regs) { 271 if (!regs) {
270 /* This should be a bug in DWARF or this tool */ 272 /* This should be a bug in DWARF or this tool */
271 pr_warning("Mapping for the register number %u " 273 pr_warning("Mapping for the register number %u "
@@ -297,10 +299,13 @@ static int convert_variable_type(Dwarf_Die *vr_die,
297 char sbuf[STRERR_BUFSIZE]; 299 char sbuf[STRERR_BUFSIZE];
298 int bsize, boffs, total; 300 int bsize, boffs, total;
299 int ret; 301 int ret;
302 char prefix;
300 303
301 /* TODO: check all types */ 304 /* TODO: check all types */
302 if (cast && strcmp(cast, "string") != 0) { 305 if (cast && strcmp(cast, "string") != 0 && strcmp(cast, "x") != 0 &&
306 strcmp(cast, "s") != 0 && strcmp(cast, "u") != 0) {
303 /* Non string type is OK */ 307 /* Non string type is OK */
308 /* and respect signedness/hexadecimal cast */
304 tvar->type = strdup(cast); 309 tvar->type = strdup(cast);
305 return (tvar->type == NULL) ? -ENOMEM : 0; 310 return (tvar->type == NULL) ? -ENOMEM : 0;
306 } 311 }
@@ -361,6 +366,17 @@ static int convert_variable_type(Dwarf_Die *vr_die,
361 return (tvar->type == NULL) ? -ENOMEM : 0; 366 return (tvar->type == NULL) ? -ENOMEM : 0;
362 } 367 }
363 368
369 if (cast && (strcmp(cast, "u") == 0))
370 prefix = 'u';
371 else if (cast && (strcmp(cast, "s") == 0))
372 prefix = 's';
373 else if (cast && (strcmp(cast, "x") == 0) &&
374 probe_type_is_available(PROBE_TYPE_X))
375 prefix = 'x';
376 else
377 prefix = die_is_signed_type(&type) ? 's' :
378 probe_type_is_available(PROBE_TYPE_X) ? 'x' : 'u';
379
364 ret = dwarf_bytesize(&type); 380 ret = dwarf_bytesize(&type);
365 if (ret <= 0) 381 if (ret <= 0)
366 /* No size ... try to use default type */ 382 /* No size ... try to use default type */
@@ -373,15 +389,14 @@ static int convert_variable_type(Dwarf_Die *vr_die,
373 dwarf_diename(&type), MAX_BASIC_TYPE_BITS); 389 dwarf_diename(&type), MAX_BASIC_TYPE_BITS);
374 ret = MAX_BASIC_TYPE_BITS; 390 ret = MAX_BASIC_TYPE_BITS;
375 } 391 }
376 ret = snprintf(buf, 16, "%c%d", 392 ret = snprintf(buf, 16, "%c%d", prefix, ret);
377 die_is_signed_type(&type) ? 's' : 'u', ret);
378 393
379formatted: 394formatted:
380 if (ret < 0 || ret >= 16) { 395 if (ret < 0 || ret >= 16) {
381 if (ret >= 16) 396 if (ret >= 16)
382 ret = -E2BIG; 397 ret = -E2BIG;
383 pr_warning("Failed to convert variable type: %s\n", 398 pr_warning("Failed to convert variable type: %s\n",
384 strerror_r(-ret, sbuf, sizeof(sbuf))); 399 str_error_r(-ret, sbuf, sizeof(sbuf)));
385 return ret; 400 return ret;
386 } 401 }
387 tvar->type = strdup(buf); 402 tvar->type = strdup(buf);
@@ -529,7 +544,7 @@ static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
529 dwarf_diename(vr_die)); 544 dwarf_diename(vr_die));
530 545
531 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 546 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops,
532 &pf->sp_die, pf->tvar); 547 &pf->sp_die, pf->machine, pf->tvar);
533 if (ret == -ENOENT || ret == -EINVAL) { 548 if (ret == -ENOENT || ret == -EINVAL) {
534 pr_err("Failed to find the location of the '%s' variable at this address.\n" 549 pr_err("Failed to find the location of the '%s' variable at this address.\n"
535 " Perhaps it has been optimized out.\n" 550 " Perhaps it has been optimized out.\n"
@@ -809,7 +824,7 @@ static int find_lazy_match_lines(struct intlist *list,
809 fp = fopen(fname, "r"); 824 fp = fopen(fname, "r");
810 if (!fp) { 825 if (!fp) {
811 pr_warning("Failed to open %s: %s\n", fname, 826 pr_warning("Failed to open %s: %s\n", fname,
812 strerror_r(errno, sbuf, sizeof(sbuf))); 827 str_error_r(errno, sbuf, sizeof(sbuf)));
813 return -errno; 828 return -errno;
814 } 829 }
815 830
@@ -892,6 +907,38 @@ static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf)
892 return die_walk_lines(sp_die, probe_point_lazy_walker, pf); 907 return die_walk_lines(sp_die, probe_point_lazy_walker, pf);
893} 908}
894 909
910static void skip_prologue(Dwarf_Die *sp_die, struct probe_finder *pf)
911{
912 struct perf_probe_point *pp = &pf->pev->point;
913
914 /* Not uprobe? */
915 if (!pf->pev->uprobes)
916 return;
917
918 /* Compiled with optimization? */
919 if (die_is_optimized_target(&pf->cu_die))
920 return;
921
922 /* Don't know entrypc? */
923 if (!pf->addr)
924 return;
925
926 /* Only FUNC and FUNC@SRC are eligible. */
927 if (!pp->function || pp->line || pp->retprobe || pp->lazy_line ||
928 pp->offset || pp->abs_address)
929 return;
930
931 /* Not interested in func parameter? */
932 if (!perf_probe_with_var(pf->pev))
933 return;
934
935 pr_info("Target program is compiled without optimization. Skipping prologue.\n"
936 "Probe on address 0x%" PRIx64 " to force probing at the function entry.\n\n",
937 pf->addr);
938
939 die_skip_prologue(sp_die, &pf->cu_die, &pf->addr);
940}
941
895static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 942static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
896{ 943{
897 struct probe_finder *pf = data; 944 struct probe_finder *pf = data;
@@ -908,6 +955,11 @@ static int probe_point_inline_cb(Dwarf_Die *in_die, void *data)
908 dwarf_diename(in_die)); 955 dwarf_diename(in_die));
909 return -ENOENT; 956 return -ENOENT;
910 } 957 }
958 if (addr == 0) {
959 pr_debug("%s has no valid entry address. skipped.\n",
960 dwarf_diename(in_die));
961 return -ENOENT;
962 }
911 pf->addr = addr; 963 pf->addr = addr;
912 pf->addr += pp->offset; 964 pf->addr += pp->offset;
913 pr_debug("found inline addr: 0x%jx\n", 965 pr_debug("found inline addr: 0x%jx\n",
@@ -941,7 +993,8 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
941 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) 993 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
942 return DWARF_CB_OK; 994 return DWARF_CB_OK;
943 995
944 pr_debug("Matched function: %s\n", dwarf_diename(sp_die)); 996 pr_debug("Matched function: %s [%lx]\n", dwarf_diename(sp_die),
997 (unsigned long)dwarf_dieoffset(sp_die));
945 pf->fname = dwarf_decl_file(sp_die); 998 pf->fname = dwarf_decl_file(sp_die);
946 if (pp->line) { /* Function relative line */ 999 if (pp->line) { /* Function relative line */
947 dwarf_decl_line(sp_die, &pf->lno); 1000 dwarf_decl_line(sp_die, &pf->lno);
@@ -950,10 +1003,16 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
950 } else if (die_is_func_instance(sp_die)) { 1003 } else if (die_is_func_instance(sp_die)) {
951 /* Instances always have the entry address */ 1004 /* Instances always have the entry address */
952 dwarf_entrypc(sp_die, &pf->addr); 1005 dwarf_entrypc(sp_die, &pf->addr);
1006 /* But in some case the entry address is 0 */
1007 if (pf->addr == 0) {
1008 pr_debug("%s has no entry PC. Skipped\n",
1009 dwarf_diename(sp_die));
1010 param->retval = 0;
953 /* Real function */ 1011 /* Real function */
954 if (pp->lazy_line) 1012 } else if (pp->lazy_line)
955 param->retval = find_probe_point_lazy(sp_die, pf); 1013 param->retval = find_probe_point_lazy(sp_die, pf);
956 else { 1014 else {
1015 skip_prologue(sp_die, pf);
957 pf->addr += pp->offset; 1016 pf->addr += pp->offset;
958 /* TODO: Check the address in this function */ 1017 /* TODO: Check the address in this function */
959 param->retval = call_probe_finder(sp_die, pf); 1018 param->retval = call_probe_finder(sp_die, pf);
@@ -963,7 +1022,7 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
963 param->retval = die_walk_instances(sp_die, 1022 param->retval = die_walk_instances(sp_die,
964 probe_point_inline_cb, (void *)pf); 1023 probe_point_inline_cb, (void *)pf);
965 /* This could be a non-existed inline definition */ 1024 /* This could be a non-existed inline definition */
966 if (param->retval == -ENOENT && strisglob(pp->function)) 1025 if (param->retval == -ENOENT)
967 param->retval = 0; 1026 param->retval = 0;
968 } 1027 }
969 1028
@@ -1092,11 +1151,8 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1092 struct probe_finder *pf) 1151 struct probe_finder *pf)
1093{ 1152{
1094 int ret = 0; 1153 int ret = 0;
1095
1096#if _ELFUTILS_PREREQ(0, 142)
1097 Elf *elf; 1154 Elf *elf;
1098 GElf_Ehdr ehdr; 1155 GElf_Ehdr ehdr;
1099 GElf_Shdr shdr;
1100 1156
1101 if (pf->cfi_eh || pf->cfi_dbg) 1157 if (pf->cfi_eh || pf->cfi_dbg)
1102 return debuginfo__find_probe_location(dbg, pf); 1158 return debuginfo__find_probe_location(dbg, pf);
@@ -1109,11 +1165,18 @@ static int debuginfo__find_probes(struct debuginfo *dbg,
1109 if (gelf_getehdr(elf, &ehdr) == NULL) 1165 if (gelf_getehdr(elf, &ehdr) == NULL)
1110 return -EINVAL; 1166 return -EINVAL;
1111 1167
1112 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) && 1168 pf->machine = ehdr.e_machine;
1113 shdr.sh_type == SHT_PROGBITS) 1169
1114 pf->cfi_eh = dwarf_getcfi_elf(elf); 1170#if _ELFUTILS_PREREQ(0, 142)
1171 do {
1172 GElf_Shdr shdr;
1173
1174 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) &&
1175 shdr.sh_type == SHT_PROGBITS)
1176 pf->cfi_eh = dwarf_getcfi_elf(elf);
1115 1177
1116 pf->cfi_dbg = dwarf_getcfi(dbg->dbg); 1178 pf->cfi_dbg = dwarf_getcfi(dbg->dbg);
1179 } while (0);
1117#endif 1180#endif
1118 1181
1119 ret = debuginfo__find_probe_location(dbg, pf); 1182 ret = debuginfo__find_probe_location(dbg, pf);
@@ -1141,7 +1204,7 @@ static int copy_variables_cb(Dwarf_Die *die_mem, void *data)
1141 (tag == DW_TAG_variable && vf->vars)) { 1204 (tag == DW_TAG_variable && vf->vars)) {
1142 if (convert_variable_location(die_mem, vf->pf->addr, 1205 if (convert_variable_location(die_mem, vf->pf->addr,
1143 vf->pf->fb_ops, &pf->sp_die, 1206 vf->pf->fb_ops, &pf->sp_die,
1144 NULL) == 0) { 1207 pf->machine, NULL) == 0) {
1145 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem); 1208 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem);
1146 if (vf->args[vf->nargs].var == NULL) { 1209 if (vf->args[vf->nargs].var == NULL) {
1147 vf->ret = -ENOMEM; 1210 vf->ret = -ENOMEM;
@@ -1304,7 +1367,7 @@ static int collect_variables_cb(Dwarf_Die *die_mem, void *data)
1304 tag == DW_TAG_variable) { 1367 tag == DW_TAG_variable) {
1305 ret = convert_variable_location(die_mem, af->pf.addr, 1368 ret = convert_variable_location(die_mem, af->pf.addr,
1306 af->pf.fb_ops, &af->pf.sp_die, 1369 af->pf.fb_ops, &af->pf.sp_die,
1307 NULL); 1370 af->pf.machine, NULL);
1308 if (ret == 0 || ret == -ERANGE) { 1371 if (ret == 0 || ret == -ERANGE) {
1309 int ret2; 1372 int ret2;
1310 bool externs = !af->child; 1373 bool externs = !af->child;
diff --git a/tools/perf/util/probe-finder.h b/tools/perf/util/probe-finder.h
index 51137fccb9c8..f1d8558f498e 100644
--- a/tools/perf/util/probe-finder.h
+++ b/tools/perf/util/probe-finder.h
@@ -80,6 +80,7 @@ struct probe_finder {
80 Dwarf_CFI *cfi_dbg; 80 Dwarf_CFI *cfi_dbg;
81#endif 81#endif
82 Dwarf_Op *fb_ops; /* Frame base attribute */ 82 Dwarf_Op *fb_ops; /* Frame base attribute */
83 unsigned int machine; /* Target machine arch */
83 struct perf_probe_arg *pvar; /* Current target variable */ 84 struct perf_probe_arg *pvar; /* Current target variable */
84 struct probe_trace_arg *tvar; /* Current result variable */ 85 struct probe_trace_arg *tvar; /* Current result variable */
85}; 86};
diff --git a/tools/perf/util/python-ext-sources b/tools/perf/util/python-ext-sources
index 36c6862119e3..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
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 c6d4ee2de752..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
diff --git a/tools/perf/util/quote.h b/tools/perf/util/quote.h
index e1ec19146fb0..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
26struct strbuf;
27
27int sq_quote_argv(struct strbuf *, const char **argv, size_t maxlen); 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
index abc76e3d3098..808cc45611fe 100644
--- a/tools/perf/util/rb_resort.h
+++ b/tools/perf/util/rb_resort.h
@@ -35,7 +35,7 @@ DEFINE_RB_RESORT_RB(threads, strcmp(a->thread->shortname,
35 35
36 struct rb_node *nd; 36 struct rb_node *nd;
37 37
38 resort_rb__for_each(nd, threads) { 38 resort_rb__for_each_entry(nd, threads) {
39 struct thread *t = threads_entry; 39 struct thread *t = threads_entry;
40 printf("%s: %d\n", t->shortname, t->tid); 40 printf("%s: %d\n", t->shortname, t->tid);
41 } 41 }
@@ -123,7 +123,7 @@ static void __name##_sorted__init_entry(struct rb_node *nd, \
123struct __name##_sorted_entry *__name##_entry; \ 123struct __name##_sorted_entry *__name##_entry; \
124struct __name##_sorted *__name = __name##_sorted__new 124struct __name##_sorted *__name = __name##_sorted__new
125 125
126#define resort_rb__for_each(__nd, __name) \ 126#define resort_rb__for_each_entry(__nd, __name) \
127 for (__nd = rb_first(&__name->entries); \ 127 for (__nd = rb_first(&__name->entries); \
128 __name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \ 128 __name##_entry = rb_entry(__nd, struct __name##_sorted_entry, \
129 rb_node), __nd; \ 129 rb_node), __nd; \
diff --git a/tools/perf/util/record.c b/tools/perf/util/record.c
index 481792c7484b..98bf584853ea 100644
--- a/tools/perf/util/record.c
+++ b/tools/perf/util/record.c
@@ -148,7 +148,7 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
148 148
149 use_comm_exec = perf_can_comm_exec(); 149 use_comm_exec = perf_can_comm_exec();
150 150
151 evlist__for_each(evlist, evsel) { 151 evlist__for_each_entry(evlist, evsel) {
152 perf_evsel__config(evsel, opts, callchain); 152 perf_evsel__config(evsel, opts, callchain);
153 if (evsel->tracking && use_comm_exec) 153 if (evsel->tracking && use_comm_exec)
154 evsel->attr.comm_exec = 1; 154 evsel->attr.comm_exec = 1;
@@ -161,18 +161,18 @@ void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts,
161 * match the id. 161 * match the id.
162 */ 162 */
163 use_sample_identifier = perf_can_sample_identifier(); 163 use_sample_identifier = perf_can_sample_identifier();
164 evlist__for_each(evlist, evsel) 164 evlist__for_each_entry(evlist, evsel)
165 perf_evsel__set_sample_id(evsel, use_sample_identifier); 165 perf_evsel__set_sample_id(evsel, use_sample_identifier);
166 } else if (evlist->nr_entries > 1) { 166 } else if (evlist->nr_entries > 1) {
167 struct perf_evsel *first = perf_evlist__first(evlist); 167 struct perf_evsel *first = perf_evlist__first(evlist);
168 168
169 evlist__for_each(evlist, evsel) { 169 evlist__for_each_entry(evlist, evsel) {
170 if (evsel->attr.sample_type == first->attr.sample_type) 170 if (evsel->attr.sample_type == first->attr.sample_type)
171 continue; 171 continue;
172 use_sample_identifier = perf_can_sample_identifier(); 172 use_sample_identifier = perf_can_sample_identifier();
173 break; 173 break;
174 } 174 }
175 evlist__for_each(evlist, evsel) 175 evlist__for_each_entry(evlist, evsel)
176 perf_evsel__set_sample_id(evsel, use_sample_identifier); 176 perf_evsel__set_sample_id(evsel, use_sample_identifier);
177 } 177 }
178 178
diff --git a/tools/perf/util/scripting-engines/trace-event-perl.c b/tools/perf/util/scripting-engines/trace-event-perl.c
index 5d1eb1ccd96c..e55a132f69b7 100644
--- a/tools/perf/util/scripting-engines/trace-event-perl.c
+++ b/tools/perf/util/scripting-engines/trace-event-perl.c
@@ -25,6 +25,7 @@
25#include <ctype.h> 25#include <ctype.h>
26#include <errno.h> 26#include <errno.h>
27#include <linux/bitmap.h> 27#include <linux/bitmap.h>
28#include <linux/time64.h>
28 29
29#include "../util.h" 30#include "../util.h"
30#include <EXTERN.h> 31#include <EXTERN.h>
@@ -359,8 +360,8 @@ static void perl_process_tracepoint(struct perf_sample *sample,
359 if (!test_and_set_bit(event->id, events_defined)) 360 if (!test_and_set_bit(event->id, events_defined))
360 define_event_symbols(event, handler, event->print_fmt.args); 361 define_event_symbols(event, handler, event->print_fmt.args);
361 362
362 s = nsecs / NSECS_PER_SEC; 363 s = nsecs / NSEC_PER_SEC;
363 ns = nsecs - s * NSECS_PER_SEC; 364 ns = nsecs - s * NSEC_PER_SEC;
364 365
365 scripting_context->event_data = data; 366 scripting_context->event_data = data;
366 scripting_context->pevent = evsel->tp_format->pevent; 367 scripting_context->pevent = evsel->tp_format->pevent;
diff --git a/tools/perf/util/scripting-engines/trace-event-python.c b/tools/perf/util/scripting-engines/trace-event-python.c
index ff134700bf30..089438da1f7f 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -27,6 +27,7 @@
27#include <stdbool.h> 27#include <stdbool.h>
28#include <errno.h> 28#include <errno.h>
29#include <linux/bitmap.h> 29#include <linux/bitmap.h>
30#include <linux/time64.h>
30 31
31#include "../../perf.h" 32#include "../../perf.h"
32#include "../debug.h" 33#include "../debug.h"
@@ -273,7 +274,7 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
273 struct format_field *field, void *data) 274 struct format_field *field, void *data)
274{ 275{
275 bool is_array = field->flags & FIELD_IS_ARRAY; 276 bool is_array = field->flags & FIELD_IS_ARRAY;
276 PyObject *obj, *list = NULL; 277 PyObject *obj = NULL, *list = NULL;
277 unsigned long long val; 278 unsigned long long val;
278 unsigned int item_size, n_items, i; 279 unsigned int item_size, n_items, i;
279 280
@@ -386,13 +387,12 @@ exit:
386 return pylist; 387 return pylist;
387} 388}
388 389
389
390static void python_process_tracepoint(struct perf_sample *sample, 390static void python_process_tracepoint(struct perf_sample *sample,
391 struct perf_evsel *evsel, 391 struct perf_evsel *evsel,
392 struct addr_location *al) 392 struct addr_location *al)
393{ 393{
394 struct event_format *event = evsel->tp_format; 394 struct event_format *event = evsel->tp_format;
395 PyObject *handler, *context, *t, *obj, *callchain; 395 PyObject *handler, *context, *t, *obj = NULL, *callchain;
396 PyObject *dict = NULL; 396 PyObject *dict = NULL;
397 static char handler_name[256]; 397 static char handler_name[256];
398 struct format_field *field; 398 struct format_field *field;
@@ -427,8 +427,8 @@ static void python_process_tracepoint(struct perf_sample *sample,
427 if (!dict) 427 if (!dict)
428 Py_FatalError("couldn't create Python dict"); 428 Py_FatalError("couldn't create Python dict");
429 } 429 }
430 s = nsecs / NSECS_PER_SEC; 430 s = nsecs / NSEC_PER_SEC;
431 ns = nsecs - s * NSECS_PER_SEC; 431 ns = nsecs - s * NSEC_PER_SEC;
432 432
433 scripting_context->event_data = data; 433 scripting_context->event_data = data;
434 scripting_context->pevent = evsel->tp_format->pevent; 434 scripting_context->pevent = evsel->tp_format->pevent;
@@ -457,14 +457,26 @@ static void python_process_tracepoint(struct perf_sample *sample,
457 pydict_set_item_string_decref(dict, "common_callchain", callchain); 457 pydict_set_item_string_decref(dict, "common_callchain", callchain);
458 } 458 }
459 for (field = event->format.fields; field; field = field->next) { 459 for (field = event->format.fields; field; field = field->next) {
460 if (field->flags & FIELD_IS_STRING) { 460 unsigned int offset, len;
461 int offset; 461 unsigned long long val;
462
463 if (field->flags & FIELD_IS_ARRAY) {
464 offset = field->offset;
465 len = field->size;
462 if (field->flags & FIELD_IS_DYNAMIC) { 466 if (field->flags & FIELD_IS_DYNAMIC) {
463 offset = *(int *)(data + field->offset); 467 val = pevent_read_number(scripting_context->pevent,
468 data + offset, len);
469 offset = val;
470 len = offset >> 16;
464 offset &= 0xffff; 471 offset &= 0xffff;
465 } else 472 }
466 offset = field->offset; 473 if (field->flags & FIELD_IS_STRING &&
467 obj = PyString_FromString((char *)data + offset); 474 is_printable_array(data + offset, len)) {
475 obj = PyString_FromString((char *) data + offset);
476 } else {
477 obj = PyByteArray_FromStringAndSize((const char *) data + offset, len);
478 field->flags &= ~FIELD_IS_STRING;
479 }
468 } else { /* FIELD_IS_NUMERIC */ 480 } else { /* FIELD_IS_NUMERIC */
469 obj = get_field_numeric_entry(event, field, data); 481 obj = get_field_numeric_entry(event, field, data);
470 } 482 }
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 5214974e841a..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);
@@ -593,6 +595,7 @@ do { \
593 if (bswap_safe(f, 0)) \ 595 if (bswap_safe(f, 0)) \
594 attr->f = bswap_##sz(attr->f); \ 596 attr->f = bswap_##sz(attr->f); \
595} while(0) 597} while(0)
598#define bswap_field_16(f) bswap_field(f, 16)
596#define bswap_field_32(f) bswap_field(f, 32) 599#define bswap_field_32(f) bswap_field(f, 32)
597#define bswap_field_64(f) bswap_field(f, 64) 600#define bswap_field_64(f) bswap_field(f, 64)
598 601
@@ -608,6 +611,7 @@ do { \
608 bswap_field_64(sample_regs_user); 611 bswap_field_64(sample_regs_user);
609 bswap_field_32(sample_stack_user); 612 bswap_field_32(sample_stack_user);
610 bswap_field_32(aux_watermark); 613 bswap_field_32(aux_watermark);
614 bswap_field_16(sample_max_stack);
611 615
612 /* 616 /*
613 * After read_format are bitfields. Check read_format because 617 * After read_format are bitfields. Check read_format because
@@ -1495,10 +1499,27 @@ int perf_session__register_idle_thread(struct perf_session *session)
1495 return err; 1499 return err;
1496} 1500}
1497 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
1498static void perf_session__warn_about_errors(const struct perf_session *session) 1520static void perf_session__warn_about_errors(const struct perf_session *session)
1499{ 1521{
1500 const struct events_stats *stats = &session->evlist->stats; 1522 const struct events_stats *stats = &session->evlist->stats;
1501 const struct ordered_events *oe = &session->ordered_events;
1502 1523
1503 if (session->tool->lost == perf_event__process_lost && 1524 if (session->tool->lost == perf_event__process_lost &&
1504 stats->nr_events[PERF_RECORD_LOST] != 0) { 1525 stats->nr_events[PERF_RECORD_LOST] != 0) {
@@ -1555,8 +1576,7 @@ static void perf_session__warn_about_errors(const struct perf_session *session)
1555 stats->nr_unprocessable_samples); 1576 stats->nr_unprocessable_samples);
1556 } 1577 }
1557 1578
1558 if (oe->nr_unordered_events != 0) 1579 perf_session__warn_order(session);
1559 ui__warning("%u out of order events recorded.\n", oe->nr_unordered_events);
1560 1580
1561 events_stats__auxtrace_error_warn(stats); 1581 events_stats__auxtrace_error_warn(stats);
1562 1582
@@ -1868,7 +1888,7 @@ bool perf_session__has_traces(struct perf_session *session, const char *msg)
1868{ 1888{
1869 struct perf_evsel *evsel; 1889 struct perf_evsel *evsel;
1870 1890
1871 evlist__for_each(session->evlist, evsel) { 1891 evlist__for_each_entry(session->evlist, evsel) {
1872 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) 1892 if (evsel->attr.type == PERF_TYPE_TRACEPOINT)
1873 return true; 1893 return true;
1874 } 1894 }
@@ -1950,7 +1970,7 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
1950{ 1970{
1951 struct perf_evsel *pos; 1971 struct perf_evsel *pos;
1952 1972
1953 evlist__for_each(session->evlist, pos) { 1973 evlist__for_each_entry(session->evlist, pos) {
1954 if (pos->attr.type == type) 1974 if (pos->attr.type == type)
1955 return pos; 1975 return pos;
1956 } 1976 }
@@ -2105,7 +2125,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool,
2105 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) / 2125 max_nr = (UINT16_MAX - sizeof(struct id_index_event)) /
2106 sizeof(struct id_index_entry); 2126 sizeof(struct id_index_entry);
2107 2127
2108 evlist__for_each(evlist, evsel) 2128 evlist__for_each_entry(evlist, evsel)
2109 nr += evsel->ids; 2129 nr += evsel->ids;
2110 2130
2111 n = nr > max_nr ? max_nr : nr; 2131 n = nr > max_nr ? max_nr : nr;
@@ -2118,7 +2138,7 @@ int perf_event__synthesize_id_index(struct perf_tool *tool,
2118 ev->id_index.header.size = sz; 2138 ev->id_index.header.size = sz;
2119 ev->id_index.nr = n; 2139 ev->id_index.nr = n;
2120 2140
2121 evlist__for_each(evlist, evsel) { 2141 evlist__for_each_entry(evlist, evsel) {
2122 u32 j; 2142 u32 j;
2123 2143
2124 for (j = 0; j < evsel->ids; j++) { 2144 for (j = 0; j < evsel->ids; j++) {
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index c4e9bd70723c..452e15a10dd2 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -11,7 +11,7 @@
11regex_t parent_regex; 11regex_t parent_regex;
12const char default_parent_pattern[] = "^sys_|^do_page_fault"; 12const char default_parent_pattern[] = "^sys_|^do_page_fault";
13const char *parent_pattern = default_parent_pattern; 13const char *parent_pattern = default_parent_pattern;
14const char default_sort_order[] = "comm,dso,symbol"; 14const char *default_sort_order = "comm,dso,symbol";
15const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles"; 15const char default_branch_sort_order[] = "comm,dso_from,symbol_from,symbol_to,cycles";
16const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked"; 16const char default_mem_sort_order[] = "local_weight,mem,sym,dso,symbol_daddr,dso_daddr,snoop,tlb,locked";
17const char default_top_sort_order[] = "dso,symbol"; 17const char default_top_sort_order[] = "dso,symbol";
@@ -79,8 +79,8 @@ static int hist_entry__thread_snprintf(struct hist_entry *he, char *bf,
79{ 79{
80 const char *comm = thread__comm_str(he->thread); 80 const char *comm = thread__comm_str(he->thread);
81 81
82 width = max(7U, width) - 6; 82 width = max(7U, width) - 8;
83 return repsep_snprintf(bf, size, "%5d:%-*.*s", he->thread->tid, 83 return repsep_snprintf(bf, size, "%7d:%-*.*s", he->thread->tid,
84 width, width, comm ?: ""); 84 width, width, comm ?: "");
85} 85}
86 86
@@ -95,7 +95,7 @@ static int hist_entry__thread_filter(struct hist_entry *he, int type, const void
95} 95}
96 96
97struct sort_entry sort_thread = { 97struct sort_entry sort_thread = {
98 .se_header = " Pid:Command", 98 .se_header = " Pid:Command",
99 .se_cmp = sort__thread_cmp, 99 .se_cmp = sort__thread_cmp,
100 .se_snprintf = hist_entry__thread_snprintf, 100 .se_snprintf = hist_entry__thread_snprintf,
101 .se_filter = hist_entry__thread_filter, 101 .se_filter = hist_entry__thread_filter,
@@ -588,7 +588,11 @@ static char *get_trace_output(struct hist_entry *he)
588 } else { 588 } else {
589 pevent_event_info(&seq, evsel->tp_format, &rec); 589 pevent_event_info(&seq, evsel->tp_format, &rec);
590 } 590 }
591 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);
592} 596}
593 597
594static int64_t 598static int64_t
@@ -863,7 +867,7 @@ struct sort_entry sort_cycles = {
863}; 867};
864 868
865/* --sort daddr_sym */ 869/* --sort daddr_sym */
866static int64_t 870int64_t
867sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right) 871sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right)
868{ 872{
869 uint64_t l = 0, r = 0; 873 uint64_t l = 0, r = 0;
@@ -892,7 +896,7 @@ static int hist_entry__daddr_snprintf(struct hist_entry *he, char *bf,
892 width); 896 width);
893} 897}
894 898
895static int64_t 899int64_t
896sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right) 900sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right)
897{ 901{
898 uint64_t l = 0, r = 0; 902 uint64_t l = 0, r = 0;
@@ -1058,7 +1062,7 @@ static int hist_entry__snoop_snprintf(struct hist_entry *he, char *bf,
1058 return repsep_snprintf(bf, size, "%-*s", width, out); 1062 return repsep_snprintf(bf, size, "%-*s", width, out);
1059} 1063}
1060 1064
1061static int64_t 1065int64_t
1062sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right) 1066sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right)
1063{ 1067{
1064 u64 l, r; 1068 u64 l, r;
@@ -1218,7 +1222,7 @@ struct sort_entry sort_mem_daddr_dso = {
1218 .se_header = "Data Object", 1222 .se_header = "Data Object",
1219 .se_cmp = sort__dso_daddr_cmp, 1223 .se_cmp = sort__dso_daddr_cmp,
1220 .se_snprintf = hist_entry__dso_daddr_snprintf, 1224 .se_snprintf = hist_entry__dso_daddr_snprintf,
1221 .se_width_idx = HISTC_MEM_DADDR_SYMBOL, 1225 .se_width_idx = HISTC_MEM_DADDR_DSO,
1222}; 1226};
1223 1227
1224struct sort_entry sort_mem_locked = { 1228struct sort_entry sort_mem_locked = {
@@ -1488,7 +1492,8 @@ void perf_hpp__reset_sort_width(struct perf_hpp_fmt *fmt, struct hists *hists)
1488} 1492}
1489 1493
1490static 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,
1491 struct perf_evsel *evsel) 1495 struct hists *hists, int line __maybe_unused,
1496 int *span __maybe_unused)
1492{ 1497{
1493 struct hpp_sort_entry *hse; 1498 struct hpp_sort_entry *hse;
1494 size_t len = fmt->user_len; 1499 size_t len = fmt->user_len;
@@ -1496,14 +1501,14 @@ static int __sort__hpp_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1496 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1501 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1497 1502
1498 if (!len) 1503 if (!len)
1499 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); 1504 len = hists__col_len(hists, hse->se->se_width_idx);
1500 1505
1501 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name); 1506 return scnprintf(hpp->buf, hpp->size, "%-*.*s", len, len, fmt->name);
1502} 1507}
1503 1508
1504static int __sort__hpp_width(struct perf_hpp_fmt *fmt, 1509static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1505 struct perf_hpp *hpp __maybe_unused, 1510 struct perf_hpp *hpp __maybe_unused,
1506 struct perf_evsel *evsel) 1511 struct hists *hists)
1507{ 1512{
1508 struct hpp_sort_entry *hse; 1513 struct hpp_sort_entry *hse;
1509 size_t len = fmt->user_len; 1514 size_t len = fmt->user_len;
@@ -1511,7 +1516,7 @@ static int __sort__hpp_width(struct perf_hpp_fmt *fmt,
1511 hse = container_of(fmt, struct hpp_sort_entry, hpp); 1516 hse = container_of(fmt, struct hpp_sort_entry, hpp);
1512 1517
1513 if (!len) 1518 if (!len)
1514 len = hists__col_len(evsel__hists(evsel), hse->se->se_width_idx); 1519 len = hists__col_len(hists, hse->se->se_width_idx);
1515 1520
1516 return len; 1521 return len;
1517} 1522}
@@ -1793,7 +1798,9 @@ static void update_dynamic_len(struct hpp_dynamic_entry *hde,
1793} 1798}
1794 1799
1795static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp, 1800static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1796 struct perf_evsel *evsel __maybe_unused) 1801 struct hists *hists __maybe_unused,
1802 int line __maybe_unused,
1803 int *span __maybe_unused)
1797{ 1804{
1798 struct hpp_dynamic_entry *hde; 1805 struct hpp_dynamic_entry *hde;
1799 size_t len = fmt->user_len; 1806 size_t len = fmt->user_len;
@@ -1808,7 +1815,7 @@ static int __sort__hde_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
1808 1815
1809static int __sort__hde_width(struct perf_hpp_fmt *fmt, 1816static int __sort__hde_width(struct perf_hpp_fmt *fmt,
1810 struct perf_hpp *hpp __maybe_unused, 1817 struct perf_hpp *hpp __maybe_unused,
1811 struct perf_evsel *evsel __maybe_unused) 1818 struct hists *hists __maybe_unused)
1812{ 1819{
1813 struct hpp_dynamic_entry *hde; 1820 struct hpp_dynamic_entry *hde;
1814 size_t len = fmt->user_len; 1821 size_t len = fmt->user_len;
@@ -2069,7 +2076,7 @@ static struct perf_evsel *find_evsel(struct perf_evlist *evlist, char *event_nam
2069 } 2076 }
2070 2077
2071 full_name = !!strchr(event_name, ':'); 2078 full_name = !!strchr(event_name, ':');
2072 evlist__for_each(evlist, pos) { 2079 evlist__for_each_entry(evlist, pos) {
2073 /* case 2 */ 2080 /* case 2 */
2074 if (full_name && !strcmp(pos->name, event_name)) 2081 if (full_name && !strcmp(pos->name, event_name))
2075 return pos; 2082 return pos;
@@ -2125,7 +2132,7 @@ static int add_all_dynamic_fields(struct perf_evlist *evlist, bool raw_trace,
2125 int ret; 2132 int ret;
2126 struct perf_evsel *evsel; 2133 struct perf_evsel *evsel;
2127 2134
2128 evlist__for_each(evlist, evsel) { 2135 evlist__for_each_entry(evlist, evsel) {
2129 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2136 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
2130 continue; 2137 continue;
2131 2138
@@ -2143,7 +2150,7 @@ static int add_all_matching_fields(struct perf_evlist *evlist,
2143 struct perf_evsel *evsel; 2150 struct perf_evsel *evsel;
2144 struct format_field *field; 2151 struct format_field *field;
2145 2152
2146 evlist__for_each(evlist, evsel) { 2153 evlist__for_each_entry(evlist, evsel) {
2147 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) 2154 if (evsel->attr.type != PERF_TYPE_TRACEPOINT)
2148 continue; 2155 continue;
2149 2156
@@ -2301,9 +2308,9 @@ int hpp_dimension__add_output(unsigned col)
2301 return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]); 2308 return __hpp_dimension__add_output(&perf_hpp_list, &hpp_sort_dimensions[col]);
2302} 2309}
2303 2310
2304static int sort_dimension__add(struct perf_hpp_list *list, const char *tok, 2311int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2305 struct perf_evlist *evlist, 2312 struct perf_evlist *evlist,
2306 int level) 2313 int level)
2307{ 2314{
2308 unsigned int i; 2315 unsigned int i;
2309 2316
@@ -2381,6 +2388,9 @@ static int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
2381 if (sort__mode != SORT_MODE__MEMORY) 2388 if (sort__mode != SORT_MODE__MEMORY)
2382 return -EINVAL; 2389 return -EINVAL;
2383 2390
2391 if (sd->entry == &sort_mem_dcacheline && cacheline_size == 0)
2392 return -EINVAL;
2393
2384 if (sd->entry == &sort_mem_daddr_sym) 2394 if (sd->entry == &sort_mem_daddr_sym)
2385 list->sym = 1; 2395 list->sym = 1;
2386 2396
@@ -2424,7 +2434,10 @@ static int setup_sort_list(struct perf_hpp_list *list, char *str,
2424 if (*tok) { 2434 if (*tok) {
2425 ret = sort_dimension__add(list, tok, evlist, level); 2435 ret = sort_dimension__add(list, tok, evlist, level);
2426 if (ret == -EINVAL) { 2436 if (ret == -EINVAL) {
2427 error("Invalid --sort key: `%s'", tok); 2437 if (!cacheline_size && !strncasecmp(tok, "dcacheline", strlen(tok)))
2438 error("The \"dcacheline\" --sort key needs to know the cacheline size and it couldn't be determined on this system");
2439 else
2440 error("Invalid --sort key: `%s'", tok);
2428 break; 2441 break;
2429 } else if (ret == -ESRCH) { 2442 } else if (ret == -ESRCH) {
2430 error("Unknown --sort key: `%s'", tok); 2443 error("Unknown --sort key: `%s'", tok);
@@ -2456,7 +2469,7 @@ static const char *get_default_sort_order(struct perf_evlist *evlist)
2456 if (evlist == NULL) 2469 if (evlist == NULL)
2457 goto out_no_evlist; 2470 goto out_no_evlist;
2458 2471
2459 evlist__for_each(evlist, evsel) { 2472 evlist__for_each_entry(evlist, evsel) {
2460 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) { 2473 if (evsel->attr.type != PERF_TYPE_TRACEPOINT) {
2461 use_trace = false; 2474 use_trace = false;
2462 break; 2475 break;
@@ -2672,7 +2685,7 @@ void sort__setup_elide(FILE *output)
2672 } 2685 }
2673} 2686}
2674 2687
2675static int output_field_add(struct perf_hpp_list *list, char *tok) 2688int output_field_add(struct perf_hpp_list *list, char *tok)
2676{ 2689{
2677 unsigned int i; 2690 unsigned int i;
2678 2691
@@ -2735,7 +2748,7 @@ static int setup_output_list(struct perf_hpp_list *list, char *str)
2735 return ret; 2748 return ret;
2736} 2749}
2737 2750
2738static void reset_dimensions(void) 2751void reset_dimensions(void)
2739{ 2752{
2740 unsigned int i; 2753 unsigned int i;
2741 2754
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
index ebb59cacd092..099c97557d33 100644
--- a/tools/perf/util/sort.h
+++ b/tools/perf/util/sort.h
@@ -28,7 +28,7 @@ extern const char *sort_order;
28extern const char *field_order; 28extern const char *field_order;
29extern const char default_parent_pattern[]; 29extern const char default_parent_pattern[];
30extern const char *parent_pattern; 30extern 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 enum sort_mode sort__mode; 34extern enum sort_mode sort__mode;
@@ -40,6 +40,7 @@ extern struct sort_entry sort_dso_from;
40extern struct sort_entry sort_dso_to; 40extern struct sort_entry sort_dso_to;
41extern struct sort_entry sort_sym_from; 41extern struct sort_entry sort_sym_from;
42extern struct sort_entry sort_sym_to; 42extern struct sort_entry sort_sym_to;
43extern struct sort_entry sort_srcline;
43extern enum sort_type sort__first_dimension; 44extern enum sort_type sort__first_dimension;
44extern const char default_mem_sort_order[]; 45extern const char default_mem_sort_order[];
45 46
@@ -67,6 +68,11 @@ struct hist_entry_diff {
67 }; 68 };
68}; 69};
69 70
71struct hist_entry_ops {
72 void *(*new)(size_t size);
73 void (*free)(void *ptr);
74};
75
70/** 76/**
71 * struct hist_entry - histogram entry 77 * struct hist_entry - histogram entry
72 * 78 *
@@ -125,6 +131,7 @@ struct hist_entry {
125 void *trace_output; 131 void *trace_output;
126 struct perf_hpp_list *hpp_list; 132 struct perf_hpp_list *hpp_list;
127 struct hist_entry *parent_he; 133 struct hist_entry *parent_he;
134 struct hist_entry_ops *ops;
128 union { 135 union {
129 /* this is for hierarchical entry structure */ 136 /* this is for hierarchical entry structure */
130 struct { 137 struct {
@@ -262,4 +269,15 @@ int report_parse_ignore_callees_opt(const struct option *opt, const char *arg, i
262bool is_strict_order(const char *order); 269bool is_strict_order(const char *order);
263 270
264int hpp_dimension__add_output(unsigned col); 271int hpp_dimension__add_output(unsigned col);
272void reset_dimensions(void);
273int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
274 struct perf_evlist *evlist,
275 int level);
276int output_field_add(struct perf_hpp_list *list, char *tok);
277int64_t
278sort__iaddr_cmp(struct hist_entry *left, struct hist_entry *right);
279int64_t
280sort__daddr_cmp(struct hist_entry *left, struct hist_entry *right);
281int64_t
282sort__dcacheline_cmp(struct hist_entry *left, struct hist_entry *right);
265#endif /* __PERF_SORT_H */ 283#endif /* __PERF_SORT_H */
diff --git a/tools/perf/util/stat-shadow.c b/tools/perf/util/stat-shadow.c
index aa9efe08762b..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/*
@@ -105,6 +115,16 @@ void perf_stat__update_shadow_stats(struct perf_evsel *counter, u64 *count,
105 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]); 115 update_stats(&runtime_transaction_stats[ctx][cpu], count[0]);
106 else if (perf_stat_evsel__is(counter, ELISION_START)) 116 else if (perf_stat_evsel__is(counter, ELISION_START))
107 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]);
108 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND)) 128 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_FRONTEND))
109 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]); 129 update_stats(&runtime_stalled_cycles_front_stats[ctx][cpu], count[0]);
110 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND)) 130 else if (perf_evsel__match(counter, HARDWARE, HW_STALLED_CYCLES_BACKEND))
@@ -302,6 +322,107 @@ static void print_ll_cache_misses(int cpu,
302 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);
303} 323}
304 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
305void perf_stat__print_shadow_stats(struct perf_evsel *evsel, 426void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
306 double avg, int cpu, 427 double avg, int cpu,
307 struct perf_stat_output_ctx *out) 428 struct perf_stat_output_ctx *out)
@@ -309,6 +430,7 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
309 void *ctxp = out->ctx; 430 void *ctxp = out->ctx;
310 print_metric_t print_metric = out->print_metric; 431 print_metric_t print_metric = out->print_metric;
311 double total, ratio = 0.0, total2; 432 double total, ratio = 0.0, total2;
433 const char *color = NULL;
312 int ctx = evsel_context(evsel); 434 int ctx = evsel_context(evsel);
313 435
314 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) { 436 if (perf_evsel__match(evsel, HARDWARE, HW_INSTRUCTIONS)) {
@@ -452,6 +574,46 @@ void perf_stat__print_shadow_stats(struct perf_evsel *evsel,
452 avg / ratio); 574 avg / ratio);
453 else 575 else
454 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);
455 } else if (runtime_nsecs_stats[cpu].n != 0) { 617 } else if (runtime_nsecs_stats[cpu].n != 0) {
456 char unit = 'M'; 618 char unit = 'M';
457 char unit_buf[10]; 619 char unit_buf[10];
diff --git a/tools/perf/util/stat.c b/tools/perf/util/stat.c
index ffa1d0653861..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 }
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 f95f682aa2b2..817593908d47 100644
--- a/tools/perf/util/strbuf.c
+++ b/tools/perf/util/strbuf.c
@@ -1,5 +1,5 @@
1#include "debug.h" 1#include "debug.h"
2#include "cache.h" 2#include "util.h"
3#include <linux/kernel.h> 3#include <linux/kernel.h>
4 4
5int prefixcmp(const char *str, const char *prefix) 5int prefixcmp(const char *str, const char *prefix)
diff --git a/tools/perf/util/strbuf.h b/tools/perf/util/strbuf.h
index 54b409297d4a..318424ea561d 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 {
@@ -63,9 +66,8 @@ static inline ssize_t strbuf_avail(const struct strbuf *sb) {
63int strbuf_grow(struct strbuf *buf, size_t); 66int strbuf_grow(struct strbuf *buf, size_t);
64 67
65static inline int strbuf_setlen(struct strbuf *sb, size_t len) { 68static inline int strbuf_setlen(struct strbuf *sb, size_t len) {
66 int ret;
67 if (!sb->alloc) { 69 if (!sb->alloc) {
68 ret = strbuf_grow(sb, 0); 70 int ret = strbuf_grow(sb, 0);
69 if (ret) 71 if (ret)
70 return ret; 72 return ret;
71 } 73 }
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/svghelper.c b/tools/perf/util/svghelper.c
index eec6c1149f44..1cbada2dc6be 100644
--- a/tools/perf/util/svghelper.c
+++ b/tools/perf/util/svghelper.c
@@ -18,6 +18,7 @@
18#include <unistd.h> 18#include <unistd.h>
19#include <string.h> 19#include <string.h>
20#include <linux/bitmap.h> 20#include <linux/bitmap.h>
21#include <linux/time64.h>
21 22
22#include "perf.h" 23#include "perf.h"
23#include "svghelper.h" 24#include "svghelper.h"
@@ -274,14 +275,14 @@ static char *time_to_string(u64 duration)
274 275
275 text[0] = 0; 276 text[0] = 0;
276 277
277 if (duration < 1000) /* less than 1 usec */ 278 if (duration < NSEC_PER_USEC) /* less than 1 usec */
278 return text; 279 return text;
279 280
280 if (duration < 1000 * 1000) { /* less than 1 msec */ 281 if (duration < NSEC_PER_MSEC) { /* less than 1 msec */
281 sprintf(text, "%.1f us", duration / 1000.0); 282 sprintf(text, "%.1f us", duration / (double)NSEC_PER_USEC);
282 return text; 283 return text;
283 } 284 }
284 sprintf(text, "%.1f ms", duration / 1000.0 / 1000); 285 sprintf(text, "%.1f ms", duration / (double)NSEC_PER_MSEC);
285 286
286 return text; 287 return text;
287} 288}
@@ -297,7 +298,7 @@ void svg_waiting(int Yslot, int cpu, u64 start, u64 end, const char *backtrace)
297 298
298 style = "waiting"; 299 style = "waiting";
299 300
300 if (end-start > 10 * 1000000) /* 10 msec */ 301 if (end-start > 10 * NSEC_PER_MSEC) /* 10 msec */
301 style = "WAITING"; 302 style = "WAITING";
302 303
303 text = time_to_string(end-start); 304 text = time_to_string(end-start);
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 87a297dd8901..99400b0e8f2a 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
@@ -196,6 +206,37 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
196 return NULL; 206 return NULL;
197} 207}
198 208
209static bool want_demangle(bool is_kernel_sym)
210{
211 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
212}
213
214static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
215{
216 int demangle_flags = verbose ? (DMGL_PARAMS | DMGL_ANSI) : DMGL_NO_OPTS;
217 char *demangled = NULL;
218
219 /*
220 * We need to figure out if the object was created from C++ sources
221 * DWARF DW_compile_unit has this, but we don't always have access
222 * to it...
223 */
224 if (!want_demangle(dso->kernel || kmodule))
225 return demangled;
226
227 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
228 if (demangled == NULL)
229 demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
230 else if (rust_is_mangled(demangled))
231 /*
232 * Input to Rust demangling is the BFD-demangled
233 * name which it Rust-demangles in place.
234 */
235 rust_demangle_sym(demangled);
236
237 return demangled;
238}
239
199#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \ 240#define elf_section__for_each_rel(reldata, pos, pos_mem, idx, nr_entries) \
200 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \ 241 for (idx = 0, pos = gelf_getrel(reldata, 0, &pos_mem); \
201 idx < nr_entries; \ 242 idx < nr_entries; \
@@ -213,8 +254,7 @@ Elf_Scn *elf_section_by_name(Elf *elf, GElf_Ehdr *ep,
213 * And always look at the original dso, not at debuginfo packages, that 254 * And always look at the original dso, not at debuginfo packages, that
214 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS). 255 * have the PLT data stripped out (shdr_rel_plt.sh_type == SHT_NOBITS).
215 */ 256 */
216int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map, 257int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *map)
217 symbol_filter_t filter)
218{ 258{
219 uint32_t nr_rel_entries, idx; 259 uint32_t nr_rel_entries, idx;
220 GElf_Sym sym; 260 GElf_Sym sym;
@@ -291,45 +331,53 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, struct map *
291 331
292 elf_section__for_each_rela(reldata, pos, pos_mem, idx, 332 elf_section__for_each_rela(reldata, pos, pos_mem, idx,
293 nr_rel_entries) { 333 nr_rel_entries) {
334 const char *elf_name = NULL;
335 char *demangled = NULL;
294 symidx = GELF_R_SYM(pos->r_info); 336 symidx = GELF_R_SYM(pos->r_info);
295 plt_offset += shdr_plt.sh_entsize; 337 plt_offset += shdr_plt.sh_entsize;
296 gelf_getsym(syms, symidx, &sym); 338 gelf_getsym(syms, symidx, &sym);
339
340 elf_name = elf_sym__name(&sym, symstrs);
341 demangled = demangle_sym(dso, 0, elf_name);
342 if (demangled != NULL)
343 elf_name = demangled;
297 snprintf(sympltname, sizeof(sympltname), 344 snprintf(sympltname, sizeof(sympltname),
298 "%s@plt", elf_sym__name(&sym, symstrs)); 345 "%s@plt", elf_name);
346 free(demangled);
299 347
300 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 348 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
301 STB_GLOBAL, sympltname); 349 STB_GLOBAL, sympltname);
302 if (!f) 350 if (!f)
303 goto out_elf_end; 351 goto out_elf_end;
304 352
305 if (filter && filter(map, f)) 353 symbols__insert(&dso->symbols[map->type], f);
306 symbol__delete(f); 354 ++nr;
307 else {
308 symbols__insert(&dso->symbols[map->type], f);
309 ++nr;
310 }
311 } 355 }
312 } else if (shdr_rel_plt.sh_type == SHT_REL) { 356 } else if (shdr_rel_plt.sh_type == SHT_REL) {
313 GElf_Rel pos_mem, *pos; 357 GElf_Rel pos_mem, *pos;
314 elf_section__for_each_rel(reldata, pos, pos_mem, idx, 358 elf_section__for_each_rel(reldata, pos, pos_mem, idx,
315 nr_rel_entries) { 359 nr_rel_entries) {
360 const char *elf_name = NULL;
361 char *demangled = NULL;
316 symidx = GELF_R_SYM(pos->r_info); 362 symidx = GELF_R_SYM(pos->r_info);
317 plt_offset += shdr_plt.sh_entsize; 363 plt_offset += shdr_plt.sh_entsize;
318 gelf_getsym(syms, symidx, &sym); 364 gelf_getsym(syms, symidx, &sym);
365
366 elf_name = elf_sym__name(&sym, symstrs);
367 demangled = demangle_sym(dso, 0, elf_name);
368 if (demangled != NULL)
369 elf_name = demangled;
319 snprintf(sympltname, sizeof(sympltname), 370 snprintf(sympltname, sizeof(sympltname),
320 "%s@plt", elf_sym__name(&sym, symstrs)); 371 "%s@plt", elf_name);
372 free(demangled);
321 373
322 f = symbol__new(plt_offset, shdr_plt.sh_entsize, 374 f = symbol__new(plt_offset, shdr_plt.sh_entsize,
323 STB_GLOBAL, sympltname); 375 STB_GLOBAL, sympltname);
324 if (!f) 376 if (!f)
325 goto out_elf_end; 377 goto out_elf_end;
326 378
327 if (filter && filter(map, f)) 379 symbols__insert(&dso->symbols[map->type], f);
328 symbol__delete(f); 380 ++nr;
329 else {
330 symbols__insert(&dso->symbols[map->type], f);
331 ++nr;
332 }
333 } 381 }
334 } 382 }
335 383
@@ -675,7 +723,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
675 } 723 }
676 724
677 /* Always reject images with a mismatched build-id: */ 725 /* Always reject images with a mismatched build-id: */
678 if (dso->has_build_id) { 726 if (dso->has_build_id && !symbol_conf.ignore_vmlinux_buildid) {
679 u8 build_id[BUILD_ID_SIZE]; 727 u8 build_id[BUILD_ID_SIZE];
680 728
681 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) { 729 if (elf_read_build_id(elf, build_id, BUILD_ID_SIZE) < 0) {
@@ -765,17 +813,11 @@ static u64 ref_reloc(struct kmap *kmap)
765 return 0; 813 return 0;
766} 814}
767 815
768static bool want_demangle(bool is_kernel_sym)
769{
770 return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
771}
772
773void __weak arch__sym_update(struct symbol *s __maybe_unused, 816void __weak arch__sym_update(struct symbol *s __maybe_unused,
774 GElf_Sym *sym __maybe_unused) { } 817 GElf_Sym *sym __maybe_unused) { }
775 818
776int dso__load_sym(struct dso *dso, struct map *map, 819int dso__load_sym(struct dso *dso, struct map *map, struct symsrc *syms_ss,
777 struct symsrc *syms_ss, struct symsrc *runtime_ss, 820 struct symsrc *runtime_ss, int kmodule)
778 symbol_filter_t filter, int kmodule)
779{ 821{
780 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL; 822 struct kmap *kmap = dso->kernel ? map__kmap(map) : NULL;
781 struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL; 823 struct map_groups *kmaps = kmap ? map__kmaps(map) : NULL;
@@ -827,7 +869,8 @@ int dso__load_sym(struct dso *dso, struct map *map,
827 sec = syms_ss->symtab; 869 sec = syms_ss->symtab;
828 shdr = syms_ss->symshdr; 870 shdr = syms_ss->symshdr;
829 871
830 if (elf_section_by_name(elf, &ehdr, &tshdr, ".text", NULL)) 872 if (elf_section_by_name(runtime_ss->elf, &runtime_ss->ehdr, &tshdr,
873 ".text", NULL))
831 dso->text_offset = tshdr.sh_addr - tshdr.sh_offset; 874 dso->text_offset = tshdr.sh_addr - tshdr.sh_offset;
832 875
833 if (runtime_ss->opdsec) 876 if (runtime_ss->opdsec)
@@ -1059,22 +1102,10 @@ int dso__load_sym(struct dso *dso, struct map *map,
1059 sym.st_value -= shdr.sh_addr - shdr.sh_offset; 1102 sym.st_value -= shdr.sh_addr - shdr.sh_offset;
1060 } 1103 }
1061new_symbol: 1104new_symbol:
1062 /* 1105 demangled = demangle_sym(dso, kmodule, elf_name);
1063 * We need to figure out if the object was created from C++ sources 1106 if (demangled != NULL)
1064 * DWARF DW_compile_unit has this, but we don't always have access 1107 elf_name = demangled;
1065 * to it... 1108
1066 */
1067 if (want_demangle(dso->kernel || kmodule)) {
1068 int demangle_flags = DMGL_NO_OPTS;
1069 if (verbose)
1070 demangle_flags = DMGL_PARAMS | DMGL_ANSI;
1071
1072 demangled = bfd_demangle(NULL, elf_name, demangle_flags);
1073 if (demangled == NULL)
1074 demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
1075 if (demangled != NULL)
1076 elf_name = demangled;
1077 }
1078 f = symbol__new(sym.st_value, sym.st_size, 1109 f = symbol__new(sym.st_value, sym.st_size,
1079 GELF_ST_BIND(sym.st_info), elf_name); 1110 GELF_ST_BIND(sym.st_info), elf_name);
1080 free(demangled); 1111 free(demangled);
@@ -1083,21 +1114,16 @@ new_symbol:
1083 1114
1084 arch__sym_update(f, &sym); 1115 arch__sym_update(f, &sym);
1085 1116
1086 if (filter && filter(curr_map, f)) 1117 __symbols__insert(&curr_dso->symbols[curr_map->type], f, dso->kernel);
1087 symbol__delete(f); 1118 nr++;
1088 else {
1089 symbols__insert(&curr_dso->symbols[curr_map->type], f);
1090 nr++;
1091 }
1092 } 1119 }
1093 1120
1094 /* 1121 /*
1095 * For misannotated, zeroed, ASM function sizes. 1122 * For misannotated, zeroed, ASM function sizes.
1096 */ 1123 */
1097 if (nr > 0) { 1124 if (nr > 0) {
1098 if (!symbol_conf.allow_aliases)
1099 symbols__fixup_duplicate(&dso->symbols[map->type]);
1100 symbols__fixup_end(&dso->symbols[map->type]); 1125 symbols__fixup_end(&dso->symbols[map->type]);
1126 symbols__fixup_duplicate(&dso->symbols[map->type]);
1101 if (kmap) { 1127 if (kmap) {
1102 /* 1128 /*
1103 * We need to fixup this here too because we create new 1129 * We need to fixup this here too because we create new
@@ -1781,6 +1807,260 @@ void kcore_extract__delete(struct kcore_extract *kce)
1781 unlink(kce->extract_filename); 1807 unlink(kce->extract_filename);
1782} 1808}
1783 1809
1810#ifdef HAVE_GELF_GETNOTE_SUPPORT
1811/**
1812 * populate_sdt_note : Parse raw data and identify SDT note
1813 * @elf: elf of the opened file
1814 * @data: raw data of a section with description offset applied
1815 * @len: note description size
1816 * @type: type of the note
1817 * @sdt_notes: List to add the SDT note
1818 *
1819 * Responsible for parsing the @data in section .note.stapsdt in @elf and
1820 * if its an SDT note, it appends to @sdt_notes list.
1821 */
1822static int populate_sdt_note(Elf **elf, const char *data, size_t len,
1823 struct list_head *sdt_notes)
1824{
1825 const char *provider, *name;
1826 struct sdt_note *tmp = NULL;
1827 GElf_Ehdr ehdr;
1828 GElf_Addr base_off = 0;
1829 GElf_Shdr shdr;
1830 int ret = -EINVAL;
1831
1832 union {
1833 Elf64_Addr a64[NR_ADDR];
1834 Elf32_Addr a32[NR_ADDR];
1835 } buf;
1836
1837 Elf_Data dst = {
1838 .d_buf = &buf, .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
1839 .d_size = gelf_fsize((*elf), ELF_T_ADDR, NR_ADDR, EV_CURRENT),
1840 .d_off = 0, .d_align = 0
1841 };
1842 Elf_Data src = {
1843 .d_buf = (void *) data, .d_type = ELF_T_ADDR,
1844 .d_version = EV_CURRENT, .d_size = dst.d_size, .d_off = 0,
1845 .d_align = 0
1846 };
1847
1848 tmp = (struct sdt_note *)calloc(1, sizeof(struct sdt_note));
1849 if (!tmp) {
1850 ret = -ENOMEM;
1851 goto out_err;
1852 }
1853
1854 INIT_LIST_HEAD(&tmp->note_list);
1855
1856 if (len < dst.d_size + 3)
1857 goto out_free_note;
1858
1859 /* Translation from file representation to memory representation */
1860 if (gelf_xlatetom(*elf, &dst, &src,
1861 elf_getident(*elf, NULL)[EI_DATA]) == NULL) {
1862 pr_err("gelf_xlatetom : %s\n", elf_errmsg(-1));
1863 goto out_free_note;
1864 }
1865
1866 /* Populate the fields of sdt_note */
1867 provider = data + dst.d_size;
1868
1869 name = (const char *)memchr(provider, '\0', data + len - provider);
1870 if (name++ == NULL)
1871 goto out_free_note;
1872
1873 tmp->provider = strdup(provider);
1874 if (!tmp->provider) {
1875 ret = -ENOMEM;
1876 goto out_free_note;
1877 }
1878 tmp->name = strdup(name);
1879 if (!tmp->name) {
1880 ret = -ENOMEM;
1881 goto out_free_prov;
1882 }
1883
1884 if (gelf_getclass(*elf) == ELFCLASS32) {
1885 memcpy(&tmp->addr, &buf, 3 * sizeof(Elf32_Addr));
1886 tmp->bit32 = true;
1887 } else {
1888 memcpy(&tmp->addr, &buf, 3 * sizeof(Elf64_Addr));
1889 tmp->bit32 = false;
1890 }
1891
1892 if (!gelf_getehdr(*elf, &ehdr)) {
1893 pr_debug("%s : cannot get elf header.\n", __func__);
1894 ret = -EBADF;
1895 goto out_free_name;
1896 }
1897
1898 /* Adjust the prelink effect :
1899 * Find out the .stapsdt.base section.
1900 * This scn will help us to handle prelinking (if present).
1901 * Compare the retrieved file offset of the base section with the
1902 * base address in the description of the SDT note. If its different,
1903 * then accordingly, adjust the note location.
1904 */
1905 if (elf_section_by_name(*elf, &ehdr, &shdr, SDT_BASE_SCN, NULL)) {
1906 base_off = shdr.sh_offset;
1907 if (base_off) {
1908 if (tmp->bit32)
1909 tmp->addr.a32[0] = tmp->addr.a32[0] + base_off -
1910 tmp->addr.a32[1];
1911 else
1912 tmp->addr.a64[0] = tmp->addr.a64[0] + base_off -
1913 tmp->addr.a64[1];
1914 }
1915 }
1916
1917 list_add_tail(&tmp->note_list, sdt_notes);
1918 return 0;
1919
1920out_free_name:
1921 free(tmp->name);
1922out_free_prov:
1923 free(tmp->provider);
1924out_free_note:
1925 free(tmp);
1926out_err:
1927 return ret;
1928}
1929
1930/**
1931 * construct_sdt_notes_list : constructs a list of SDT notes
1932 * @elf : elf to look into
1933 * @sdt_notes : empty list_head
1934 *
1935 * Scans the sections in 'elf' for the section
1936 * .note.stapsdt. It, then calls populate_sdt_note to find
1937 * out the SDT events and populates the 'sdt_notes'.
1938 */
1939static int construct_sdt_notes_list(Elf *elf, struct list_head *sdt_notes)
1940{
1941 GElf_Ehdr ehdr;
1942 Elf_Scn *scn = NULL;
1943 Elf_Data *data;
1944 GElf_Shdr shdr;
1945 size_t shstrndx, next;
1946 GElf_Nhdr nhdr;
1947 size_t name_off, desc_off, offset;
1948 int ret = 0;
1949
1950 if (gelf_getehdr(elf, &ehdr) == NULL) {
1951 ret = -EBADF;
1952 goto out_ret;
1953 }
1954 if (elf_getshdrstrndx(elf, &shstrndx) != 0) {
1955 ret = -EBADF;
1956 goto out_ret;
1957 }
1958
1959 /* Look for the required section */
1960 scn = elf_section_by_name(elf, &ehdr, &shdr, SDT_NOTE_SCN, NULL);
1961 if (!scn) {
1962 ret = -ENOENT;
1963 goto out_ret;
1964 }
1965
1966 if ((shdr.sh_type != SHT_NOTE) || (shdr.sh_flags & SHF_ALLOC)) {
1967 ret = -ENOENT;
1968 goto out_ret;
1969 }
1970
1971 data = elf_getdata(scn, NULL);
1972
1973 /* Get the SDT notes */
1974 for (offset = 0; (next = gelf_getnote(data, offset, &nhdr, &name_off,
1975 &desc_off)) > 0; offset = next) {
1976 if (nhdr.n_namesz == sizeof(SDT_NOTE_NAME) &&
1977 !memcmp(data->d_buf + name_off, SDT_NOTE_NAME,
1978 sizeof(SDT_NOTE_NAME))) {
1979 /* Check the type of the note */
1980 if (nhdr.n_type != SDT_NOTE_TYPE)
1981 goto out_ret;
1982
1983 ret = populate_sdt_note(&elf, ((data->d_buf) + desc_off),
1984 nhdr.n_descsz, sdt_notes);
1985 if (ret < 0)
1986 goto out_ret;
1987 }
1988 }
1989 if (list_empty(sdt_notes))
1990 ret = -ENOENT;
1991
1992out_ret:
1993 return ret;
1994}
1995
1996/**
1997 * get_sdt_note_list : Wrapper to construct a list of sdt notes
1998 * @head : empty list_head
1999 * @target : file to find SDT notes from
2000 *
2001 * This opens the file, initializes
2002 * the ELF and then calls construct_sdt_notes_list.
2003 */
2004int get_sdt_note_list(struct list_head *head, const char *target)
2005{
2006 Elf *elf;
2007 int fd, ret;
2008
2009 fd = open(target, O_RDONLY);
2010 if (fd < 0)
2011 return -EBADF;
2012
2013 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
2014 if (!elf) {
2015 ret = -EBADF;
2016 goto out_close;
2017 }
2018 ret = construct_sdt_notes_list(elf, head);
2019 elf_end(elf);
2020out_close:
2021 close(fd);
2022 return ret;
2023}
2024
2025/**
2026 * cleanup_sdt_note_list : free the sdt notes' list
2027 * @sdt_notes: sdt notes' list
2028 *
2029 * Free up the SDT notes in @sdt_notes.
2030 * Returns the number of SDT notes free'd.
2031 */
2032int cleanup_sdt_note_list(struct list_head *sdt_notes)
2033{
2034 struct sdt_note *tmp, *pos;
2035 int nr_free = 0;
2036
2037 list_for_each_entry_safe(pos, tmp, sdt_notes, note_list) {
2038 list_del(&pos->note_list);
2039 free(pos->name);
2040 free(pos->provider);
2041 free(pos);
2042 nr_free++;
2043 }
2044 return nr_free;
2045}
2046
2047/**
2048 * sdt_notes__get_count: Counts the number of sdt events
2049 * @start: list_head to sdt_notes list
2050 *
2051 * Returns the number of SDT notes in a list
2052 */
2053int sdt_notes__get_count(struct list_head *start)
2054{
2055 struct sdt_note *sdt_ptr;
2056 int count = 0;
2057
2058 list_for_each_entry(sdt_ptr, start, note_list)
2059 count++;
2060 return count;
2061}
2062#endif
2063
1784void symbol__elf_init(void) 2064void symbol__elf_init(void)
1785{ 2065{
1786 elf_version(EV_CURRENT); 2066 elf_version(EV_CURRENT);
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 48906333a858..11cdde980545 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -287,8 +287,7 @@ void symsrc__destroy(struct symsrc *ss)
287 287
288int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused, 288int dso__synthesize_plt_symbols(struct dso *dso __maybe_unused,
289 struct symsrc *ss __maybe_unused, 289 struct symsrc *ss __maybe_unused,
290 struct map *map __maybe_unused, 290 struct map *map __maybe_unused)
291 symbol_filter_t filter __maybe_unused)
292{ 291{
293 return 0; 292 return 0;
294} 293}
@@ -334,7 +333,6 @@ enum dso_type dso__type_fd(int fd)
334int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, 333int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
335 struct symsrc *ss, 334 struct symsrc *ss,
336 struct symsrc *runtime_ss __maybe_unused, 335 struct symsrc *runtime_ss __maybe_unused,
337 symbol_filter_t filter __maybe_unused,
338 int kmodule __maybe_unused) 336 int kmodule __maybe_unused)
339{ 337{
340 unsigned char build_id[BUILD_ID_SIZE]; 338 unsigned char build_id[BUILD_ID_SIZE];
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 20f9cb32b703..aecff69a510d 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -9,6 +9,7 @@
9#include <fcntl.h> 9#include <fcntl.h>
10#include <unistd.h> 10#include <unistd.h>
11#include <inttypes.h> 11#include <inttypes.h>
12#include "annotate.h"
12#include "build-id.h" 13#include "build-id.h"
13#include "util.h" 14#include "util.h"
14#include "debug.h" 15#include "debug.h"
@@ -23,10 +24,10 @@
23#include <symbol/kallsyms.h> 24#include <symbol/kallsyms.h>
24#include <sys/utsname.h> 25#include <sys/utsname.h>
25 26
26static int dso__load_kernel_sym(struct dso *dso, struct map *map, 27static int dso__load_kernel_sym(struct dso *dso, struct map *map);
27 symbol_filter_t filter); 28static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map);
28static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 29static bool symbol__is_idle(const char *name);
29 symbol_filter_t filter); 30
30int vmlinux_path__nr_entries; 31int vmlinux_path__nr_entries;
31char **vmlinux_path; 32char **vmlinux_path;
32 33
@@ -152,6 +153,9 @@ void symbols__fixup_duplicate(struct rb_root *symbols)
152 struct rb_node *nd; 153 struct rb_node *nd;
153 struct symbol *curr, *next; 154 struct symbol *curr, *next;
154 155
156 if (symbol_conf.allow_aliases)
157 return;
158
155 nd = rb_first(symbols); 159 nd = rb_first(symbols);
156 160
157 while (nd) { 161 while (nd) {
@@ -235,8 +239,13 @@ struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name)
235 if (sym == NULL) 239 if (sym == NULL)
236 return NULL; 240 return NULL;
237 241
238 if (symbol_conf.priv_size) 242 if (symbol_conf.priv_size) {
243 if (symbol_conf.init_annotation) {
244 struct annotation *notes = (void *)sym;
245 pthread_mutex_init(&notes->lock, NULL);
246 }
239 sym = ((void *)sym) + symbol_conf.priv_size; 247 sym = ((void *)sym) + symbol_conf.priv_size;
248 }
240 249
241 sym->start = start; 250 sym->start = start;
242 sym->end = len ? start + len : start; 251 sym->end = len ? start + len : start;
@@ -268,13 +277,24 @@ void symbols__delete(struct rb_root *symbols)
268 } 277 }
269} 278}
270 279
271void symbols__insert(struct rb_root *symbols, struct symbol *sym) 280void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel)
272{ 281{
273 struct rb_node **p = &symbols->rb_node; 282 struct rb_node **p = &symbols->rb_node;
274 struct rb_node *parent = NULL; 283 struct rb_node *parent = NULL;
275 const u64 ip = sym->start; 284 const u64 ip = sym->start;
276 struct symbol *s; 285 struct symbol *s;
277 286
287 if (kernel) {
288 const char *name = sym->name;
289 /*
290 * ppc64 uses function descriptors and appends a '.' to the
291 * start of every instruction address. Remove it.
292 */
293 if (name[0] == '.')
294 name++;
295 sym->idle = symbol__is_idle(name);
296 }
297
278 while (*p != NULL) { 298 while (*p != NULL) {
279 parent = *p; 299 parent = *p;
280 s = rb_entry(parent, struct symbol, rb_node); 300 s = rb_entry(parent, struct symbol, rb_node);
@@ -287,6 +307,11 @@ void symbols__insert(struct rb_root *symbols, struct symbol *sym)
287 rb_insert_color(&sym->rb_node, symbols); 307 rb_insert_color(&sym->rb_node, symbols);
288} 308}
289 309
310void symbols__insert(struct rb_root *symbols, struct symbol *sym)
311{
312 __symbols__insert(symbols, sym, false);
313}
314
290static struct symbol *symbols__find(struct rb_root *symbols, u64 ip) 315static struct symbol *symbols__find(struct rb_root *symbols, u64 ip)
291{ 316{
292 struct rb_node *n; 317 struct rb_node *n;
@@ -320,6 +345,16 @@ static struct symbol *symbols__first(struct rb_root *symbols)
320 return NULL; 345 return NULL;
321} 346}
322 347
348static struct symbol *symbols__last(struct rb_root *symbols)
349{
350 struct rb_node *n = rb_last(symbols);
351
352 if (n)
353 return rb_entry(n, struct symbol, rb_node);
354
355 return NULL;
356}
357
323static struct symbol *symbols__next(struct symbol *sym) 358static struct symbol *symbols__next(struct symbol *sym)
324{ 359{
325 struct rb_node *n = rb_next(&sym->rb_node); 360 struct rb_node *n = rb_next(&sym->rb_node);
@@ -415,7 +450,7 @@ void dso__reset_find_symbol_cache(struct dso *dso)
415 450
416void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym) 451void dso__insert_symbol(struct dso *dso, enum map_type type, struct symbol *sym)
417{ 452{
418 symbols__insert(&dso->symbols[type], sym); 453 __symbols__insert(&dso->symbols[type], sym, dso->kernel);
419 454
420 /* update the symbol cache if necessary */ 455 /* update the symbol cache if necessary */
421 if (dso->last_find_result[type].addr >= sym->start && 456 if (dso->last_find_result[type].addr >= sym->start &&
@@ -441,6 +476,11 @@ struct symbol *dso__first_symbol(struct dso *dso, enum map_type type)
441 return symbols__first(&dso->symbols[type]); 476 return symbols__first(&dso->symbols[type]);
442} 477}
443 478
479struct symbol *dso__last_symbol(struct dso *dso, enum map_type type)
480{
481 return symbols__last(&dso->symbols[type]);
482}
483
444struct symbol *dso__next_symbol(struct symbol *sym) 484struct symbol *dso__next_symbol(struct symbol *sym)
445{ 485{
446 return symbols__next(sym); 486 return symbols__next(sym);
@@ -537,7 +577,7 @@ struct process_kallsyms_args {
537 * These are symbols in the kernel image, so make sure that 577 * These are symbols in the kernel image, so make sure that
538 * sym is from a kernel DSO. 578 * sym is from a kernel DSO.
539 */ 579 */
540bool symbol__is_idle(struct symbol *sym) 580static bool symbol__is_idle(const char *name)
541{ 581{
542 const char * const idle_symbols[] = { 582 const char * const idle_symbols[] = {
543 "cpu_idle", 583 "cpu_idle",
@@ -554,14 +594,10 @@ bool symbol__is_idle(struct symbol *sym)
554 "pseries_dedicated_idle_sleep", 594 "pseries_dedicated_idle_sleep",
555 NULL 595 NULL
556 }; 596 };
557
558 int i; 597 int i;
559 598
560 if (!sym)
561 return false;
562
563 for (i = 0; idle_symbols[i]; i++) { 599 for (i = 0; idle_symbols[i]; i++) {
564 if (!strcmp(idle_symbols[i], sym->name)) 600 if (!strcmp(idle_symbols[i], name))
565 return true; 601 return true;
566 } 602 }
567 603
@@ -590,7 +626,7 @@ static int map__process_kallsym_symbol(void *arg, const char *name,
590 * We will pass the symbols to the filter later, in 626 * We will pass the symbols to the filter later, in
591 * map__split_kallsyms, when we have split the maps per module 627 * map__split_kallsyms, when we have split the maps per module
592 */ 628 */
593 symbols__insert(root, sym); 629 __symbols__insert(root, sym, !strchr(name, '['));
594 630
595 return 0; 631 return 0;
596} 632}
@@ -607,8 +643,7 @@ static int dso__load_all_kallsyms(struct dso *dso, const char *filename,
607 return kallsyms__parse(filename, &args, map__process_kallsym_symbol); 643 return kallsyms__parse(filename, &args, map__process_kallsym_symbol);
608} 644}
609 645
610static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map, 646static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map)
611 symbol_filter_t filter)
612{ 647{
613 struct map_groups *kmaps = map__kmaps(map); 648 struct map_groups *kmaps = map__kmaps(map);
614 struct map *curr_map; 649 struct map *curr_map;
@@ -637,7 +672,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
637 672
638 curr_map = map_groups__find(kmaps, map->type, pos->start); 673 curr_map = map_groups__find(kmaps, map->type, pos->start);
639 674
640 if (!curr_map || (filter && filter(curr_map, pos))) { 675 if (!curr_map) {
641 symbol__delete(pos); 676 symbol__delete(pos);
642 continue; 677 continue;
643 } 678 }
@@ -660,8 +695,7 @@ static int dso__split_kallsyms_for_kcore(struct dso *dso, struct map *map,
660 * kernel range is broken in several maps, named [kernel].N, as we don't have 695 * kernel range is broken in several maps, named [kernel].N, as we don't have
661 * the original ELF section names vmlinux have. 696 * the original ELF section names vmlinux have.
662 */ 697 */
663static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta, 698static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta)
664 symbol_filter_t filter)
665{ 699{
666 struct map_groups *kmaps = map__kmaps(map); 700 struct map_groups *kmaps = map__kmaps(map);
667 struct machine *machine; 701 struct machine *machine;
@@ -738,7 +772,7 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
738 772
739 if (count == 0) { 773 if (count == 0) {
740 curr_map = map; 774 curr_map = map;
741 goto filter_symbol; 775 goto add_symbol;
742 } 776 }
743 777
744 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 778 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
@@ -770,18 +804,18 @@ static int dso__split_kallsyms(struct dso *dso, struct map *map, u64 delta,
770 pos->start -= delta; 804 pos->start -= delta;
771 pos->end -= delta; 805 pos->end -= delta;
772 } 806 }
773filter_symbol: 807add_symbol:
774 if (filter && filter(curr_map, pos)) { 808 if (curr_map != map) {
775discard_symbol: rb_erase(&pos->rb_node, root); 809 rb_erase(&pos->rb_node, root);
776 symbol__delete(pos); 810 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos);
777 } else { 811 ++moved;
778 if (curr_map != map) { 812 } else
779 rb_erase(&pos->rb_node, root); 813 ++count;
780 symbols__insert(&curr_map->dso->symbols[curr_map->type], pos); 814
781 ++moved; 815 continue;
782 } else 816discard_symbol:
783 ++count; 817 rb_erase(&pos->rb_node, root);
784 } 818 symbol__delete(pos);
785 } 819 }
786 820
787 if (curr_map != map && 821 if (curr_map != map &&
@@ -1221,7 +1255,7 @@ static int kallsyms__delta(struct map *map, const char *filename, u64 *delta)
1221} 1255}
1222 1256
1223int __dso__load_kallsyms(struct dso *dso, const char *filename, 1257int __dso__load_kallsyms(struct dso *dso, const char *filename,
1224 struct map *map, bool no_kcore, symbol_filter_t filter) 1258 struct map *map, bool no_kcore)
1225{ 1259{
1226 u64 delta = 0; 1260 u64 delta = 0;
1227 1261
@@ -1234,8 +1268,8 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename,
1234 if (kallsyms__delta(map, filename, &delta)) 1268 if (kallsyms__delta(map, filename, &delta))
1235 return -1; 1269 return -1;
1236 1270
1237 symbols__fixup_duplicate(&dso->symbols[map->type]);
1238 symbols__fixup_end(&dso->symbols[map->type]); 1271 symbols__fixup_end(&dso->symbols[map->type]);
1272 symbols__fixup_duplicate(&dso->symbols[map->type]);
1239 1273
1240 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1274 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1241 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS; 1275 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
@@ -1243,19 +1277,18 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename,
1243 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS; 1277 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
1244 1278
1245 if (!no_kcore && !dso__load_kcore(dso, map, filename)) 1279 if (!no_kcore && !dso__load_kcore(dso, map, filename))
1246 return dso__split_kallsyms_for_kcore(dso, map, filter); 1280 return dso__split_kallsyms_for_kcore(dso, map);
1247 else 1281 else
1248 return dso__split_kallsyms(dso, map, delta, filter); 1282 return dso__split_kallsyms(dso, map, delta);
1249} 1283}
1250 1284
1251int dso__load_kallsyms(struct dso *dso, const char *filename, 1285int dso__load_kallsyms(struct dso *dso, const char *filename,
1252 struct map *map, symbol_filter_t filter) 1286 struct map *map)
1253{ 1287{
1254 return __dso__load_kallsyms(dso, filename, map, false, filter); 1288 return __dso__load_kallsyms(dso, filename, map, false);
1255} 1289}
1256 1290
1257static int dso__load_perf_map(struct dso *dso, struct map *map, 1291static int dso__load_perf_map(struct dso *dso, struct map *map)
1258 symbol_filter_t filter)
1259{ 1292{
1260 char *line = NULL; 1293 char *line = NULL;
1261 size_t n; 1294 size_t n;
@@ -1297,12 +1330,8 @@ static int dso__load_perf_map(struct dso *dso, struct map *map,
1297 if (sym == NULL) 1330 if (sym == NULL)
1298 goto out_delete_line; 1331 goto out_delete_line;
1299 1332
1300 if (filter && filter(map, sym)) 1333 symbols__insert(&dso->symbols[map->type], sym);
1301 symbol__delete(sym); 1334 nr_syms++;
1302 else {
1303 symbols__insert(&dso->symbols[map->type], sym);
1304 nr_syms++;
1305 }
1306 } 1335 }
1307 1336
1308 free(line); 1337 free(line);
@@ -1358,7 +1387,7 @@ static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod,
1358 } 1387 }
1359} 1388}
1360 1389
1361int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1390int dso__load(struct dso *dso, struct map *map)
1362{ 1391{
1363 char *name; 1392 char *name;
1364 int ret = -1; 1393 int ret = -1;
@@ -1381,9 +1410,9 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1381 1410
1382 if (dso->kernel) { 1411 if (dso->kernel) {
1383 if (dso->kernel == DSO_TYPE_KERNEL) 1412 if (dso->kernel == DSO_TYPE_KERNEL)
1384 ret = dso__load_kernel_sym(dso, map, filter); 1413 ret = dso__load_kernel_sym(dso, map);
1385 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 1414 else if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
1386 ret = dso__load_guest_kernel_sym(dso, map, filter); 1415 ret = dso__load_guest_kernel_sym(dso, map);
1387 1416
1388 goto out; 1417 goto out;
1389 } 1418 }
@@ -1407,7 +1436,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1407 goto out; 1436 goto out;
1408 } 1437 }
1409 1438
1410 ret = dso__load_perf_map(dso, map, filter); 1439 ret = dso__load_perf_map(dso, map);
1411 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT : 1440 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1412 DSO_BINARY_TYPE__NOT_FOUND; 1441 DSO_BINARY_TYPE__NOT_FOUND;
1413 goto out; 1442 goto out;
@@ -1430,7 +1459,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1430 * Read the build id if possible. This is required for 1459 * Read the build id if possible. This is required for
1431 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work 1460 * DSO_BINARY_TYPE__BUILDID_DEBUGINFO to work
1432 */ 1461 */
1433 if (is_regular_file(name) && 1462 if (is_regular_file(dso->long_name) &&
1434 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0) 1463 filename__read_build_id(dso->long_name, build_id, BUILD_ID_SIZE) > 0)
1435 dso__set_build_id(dso, build_id); 1464 dso__set_build_id(dso, build_id);
1436 1465
@@ -1498,14 +1527,14 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1498 kmod = true; 1527 kmod = true;
1499 1528
1500 if (syms_ss) 1529 if (syms_ss)
1501 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, filter, kmod); 1530 ret = dso__load_sym(dso, map, syms_ss, runtime_ss, kmod);
1502 else 1531 else
1503 ret = -1; 1532 ret = -1;
1504 1533
1505 if (ret > 0) { 1534 if (ret > 0) {
1506 int nr_plt; 1535 int nr_plt;
1507 1536
1508 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map, filter); 1537 nr_plt = dso__synthesize_plt_symbols(dso, runtime_ss, map);
1509 if (nr_plt > 0) 1538 if (nr_plt > 0)
1510 ret += nr_plt; 1539 ret += nr_plt;
1511 } 1540 }
@@ -1544,8 +1573,7 @@ out_unlock:
1544} 1573}
1545 1574
1546int dso__load_vmlinux(struct dso *dso, struct map *map, 1575int dso__load_vmlinux(struct dso *dso, struct map *map,
1547 const char *vmlinux, bool vmlinux_allocated, 1576 const char *vmlinux, bool vmlinux_allocated)
1548 symbol_filter_t filter)
1549{ 1577{
1550 int err = -1; 1578 int err = -1;
1551 struct symsrc ss; 1579 struct symsrc ss;
@@ -1565,7 +1593,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1565 if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type)) 1593 if (symsrc__init(&ss, dso, symfs_vmlinux, symtab_type))
1566 return -1; 1594 return -1;
1567 1595
1568 err = dso__load_sym(dso, map, &ss, &ss, filter, 0); 1596 err = dso__load_sym(dso, map, &ss, &ss, 0);
1569 symsrc__destroy(&ss); 1597 symsrc__destroy(&ss);
1570 1598
1571 if (err > 0) { 1599 if (err > 0) {
@@ -1581,8 +1609,7 @@ int dso__load_vmlinux(struct dso *dso, struct map *map,
1581 return err; 1609 return err;
1582} 1610}
1583 1611
1584int dso__load_vmlinux_path(struct dso *dso, struct map *map, 1612int dso__load_vmlinux_path(struct dso *dso, struct map *map)
1585 symbol_filter_t filter)
1586{ 1613{
1587 int i, err = 0; 1614 int i, err = 0;
1588 char *filename = NULL; 1615 char *filename = NULL;
@@ -1591,7 +1618,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1591 vmlinux_path__nr_entries + 1); 1618 vmlinux_path__nr_entries + 1);
1592 1619
1593 for (i = 0; i < vmlinux_path__nr_entries; ++i) { 1620 for (i = 0; i < vmlinux_path__nr_entries; ++i) {
1594 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false, filter); 1621 err = dso__load_vmlinux(dso, map, vmlinux_path[i], false);
1595 if (err > 0) 1622 if (err > 0)
1596 goto out; 1623 goto out;
1597 } 1624 }
@@ -1599,7 +1626,7 @@ int dso__load_vmlinux_path(struct dso *dso, struct map *map,
1599 if (!symbol_conf.ignore_vmlinux_buildid) 1626 if (!symbol_conf.ignore_vmlinux_buildid)
1600 filename = dso__build_id_filename(dso, NULL, 0); 1627 filename = dso__build_id_filename(dso, NULL, 0);
1601 if (filename != NULL) { 1628 if (filename != NULL) {
1602 err = dso__load_vmlinux(dso, map, filename, true, filter); 1629 err = dso__load_vmlinux(dso, map, filename, true);
1603 if (err > 0) 1630 if (err > 0)
1604 goto out; 1631 goto out;
1605 free(filename); 1632 free(filename);
@@ -1626,7 +1653,7 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1626 if (!dirs) 1653 if (!dirs)
1627 return -1; 1654 return -1;
1628 1655
1629 strlist__for_each(nd, dirs) { 1656 strlist__for_each_entry(nd, dirs) {
1630 scnprintf(kallsyms_filename, sizeof(kallsyms_filename), 1657 scnprintf(kallsyms_filename, sizeof(kallsyms_filename),
1631 "%s/%s/kallsyms", dir, nd->s); 1658 "%s/%s/kallsyms", dir, nd->s);
1632 if (!validate_kcore_addresses(kallsyms_filename, map)) { 1659 if (!validate_kcore_addresses(kallsyms_filename, map)) {
@@ -1641,6 +1668,20 @@ static int find_matching_kcore(struct map *map, char *dir, size_t dir_sz)
1641 return ret; 1668 return ret;
1642} 1669}
1643 1670
1671/*
1672 * Use open(O_RDONLY) to check readability directly instead of access(R_OK)
1673 * since access(R_OK) only checks with real UID/GID but open() use effective
1674 * UID/GID and actual capabilities (e.g. /proc/kcore requires CAP_SYS_RAWIO).
1675 */
1676static bool filename__readable(const char *file)
1677{
1678 int fd = open(file, O_RDONLY);
1679 if (fd < 0)
1680 return false;
1681 close(fd);
1682 return true;
1683}
1684
1644static char *dso__find_kallsyms(struct dso *dso, struct map *map) 1685static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1645{ 1686{
1646 u8 host_build_id[BUILD_ID_SIZE]; 1687 u8 host_build_id[BUILD_ID_SIZE];
@@ -1660,62 +1701,46 @@ static char *dso__find_kallsyms(struct dso *dso, struct map *map)
1660 sizeof(host_build_id)) == 0) 1701 sizeof(host_build_id)) == 0)
1661 is_host = dso__build_id_equal(dso, host_build_id); 1702 is_host = dso__build_id_equal(dso, host_build_id);
1662 1703
1663 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id); 1704 /* Try a fast path for /proc/kallsyms if possible */
1664
1665 scnprintf(path, sizeof(path), "%s/%s/%s", buildid_dir,
1666 DSO__NAME_KCORE, sbuild_id);
1667
1668 /* Use /proc/kallsyms if possible */
1669 if (is_host) { 1705 if (is_host) {
1670 DIR *d;
1671 int fd;
1672
1673 /* If no cached kcore go with /proc/kallsyms */
1674 d = opendir(path);
1675 if (!d)
1676 goto proc_kallsyms;
1677 closedir(d);
1678
1679 /* 1706 /*
1680 * Do not check the build-id cache, until we know we cannot use 1707 * Do not check the build-id cache, unless we know we cannot use
1681 * /proc/kcore. 1708 * /proc/kcore or module maps don't match to /proc/kallsyms.
1709 * To check readability of /proc/kcore, do not use access(R_OK)
1710 * since /proc/kcore requires CAP_SYS_RAWIO to read and access
1711 * can't check it.
1682 */ 1712 */
1683 fd = open("/proc/kcore", O_RDONLY); 1713 if (filename__readable("/proc/kcore") &&
1684 if (fd != -1) { 1714 !validate_kcore_addresses("/proc/kallsyms", map))
1685 close(fd); 1715 goto proc_kallsyms;
1686 /* If module maps match go with /proc/kallsyms */
1687 if (!validate_kcore_addresses("/proc/kallsyms", map))
1688 goto proc_kallsyms;
1689 }
1690
1691 /* Find kallsyms in build-id cache with kcore */
1692 if (!find_matching_kcore(map, path, sizeof(path)))
1693 return strdup(path);
1694
1695 goto proc_kallsyms;
1696 } 1716 }
1697 1717
1718 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1719
1698 /* Find kallsyms in build-id cache with kcore */ 1720 /* Find kallsyms in build-id cache with kcore */
1721 scnprintf(path, sizeof(path), "%s/%s/%s",
1722 buildid_dir, DSO__NAME_KCORE, sbuild_id);
1723
1699 if (!find_matching_kcore(map, path, sizeof(path))) 1724 if (!find_matching_kcore(map, path, sizeof(path)))
1700 return strdup(path); 1725 return strdup(path);
1701 1726
1702 scnprintf(path, sizeof(path), "%s/%s/%s", 1727 /* Use current /proc/kallsyms if possible */
1703 buildid_dir, DSO__NAME_KALLSYMS, sbuild_id); 1728 if (is_host) {
1729proc_kallsyms:
1730 return strdup("/proc/kallsyms");
1731 }
1704 1732
1705 if (access(path, F_OK)) { 1733 /* Finally, find a cache of kallsyms */
1734 if (!build_id_cache__kallsyms_path(sbuild_id, path, sizeof(path))) {
1706 pr_err("No kallsyms or vmlinux with build-id %s was found\n", 1735 pr_err("No kallsyms or vmlinux with build-id %s was found\n",
1707 sbuild_id); 1736 sbuild_id);
1708 return NULL; 1737 return NULL;
1709 } 1738 }
1710 1739
1711 return strdup(path); 1740 return strdup(path);
1712
1713proc_kallsyms:
1714 return strdup("/proc/kallsyms");
1715} 1741}
1716 1742
1717static int dso__load_kernel_sym(struct dso *dso, struct map *map, 1743static int dso__load_kernel_sym(struct dso *dso, struct map *map)
1718 symbol_filter_t filter)
1719{ 1744{
1720 int err; 1745 int err;
1721 const char *kallsyms_filename = NULL; 1746 const char *kallsyms_filename = NULL;
@@ -1741,12 +1766,11 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1741 } 1766 }
1742 1767
1743 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) { 1768 if (!symbol_conf.ignore_vmlinux && symbol_conf.vmlinux_name != NULL) {
1744 return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name, 1769 return dso__load_vmlinux(dso, map, symbol_conf.vmlinux_name, false);
1745 false, filter);
1746 } 1770 }
1747 1771
1748 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) { 1772 if (!symbol_conf.ignore_vmlinux && vmlinux_path != NULL) {
1749 err = dso__load_vmlinux_path(dso, map, filter); 1773 err = dso__load_vmlinux_path(dso, map);
1750 if (err > 0) 1774 if (err > 0)
1751 return err; 1775 return err;
1752 } 1776 }
@@ -1762,7 +1786,7 @@ static int dso__load_kernel_sym(struct dso *dso, struct map *map,
1762 kallsyms_filename = kallsyms_allocated_filename; 1786 kallsyms_filename = kallsyms_allocated_filename;
1763 1787
1764do_kallsyms: 1788do_kallsyms:
1765 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1789 err = dso__load_kallsyms(dso, kallsyms_filename, map);
1766 if (err > 0) 1790 if (err > 0)
1767 pr_debug("Using %s for symbols\n", kallsyms_filename); 1791 pr_debug("Using %s for symbols\n", kallsyms_filename);
1768 free(kallsyms_allocated_filename); 1792 free(kallsyms_allocated_filename);
@@ -1777,8 +1801,7 @@ do_kallsyms:
1777 return err; 1801 return err;
1778} 1802}
1779 1803
1780static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map, 1804static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map)
1781 symbol_filter_t filter)
1782{ 1805{
1783 int err; 1806 int err;
1784 const char *kallsyms_filename = NULL; 1807 const char *kallsyms_filename = NULL;
@@ -1800,7 +1823,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1800 if (symbol_conf.default_guest_vmlinux_name != NULL) { 1823 if (symbol_conf.default_guest_vmlinux_name != NULL) {
1801 err = dso__load_vmlinux(dso, map, 1824 err = dso__load_vmlinux(dso, map,
1802 symbol_conf.default_guest_vmlinux_name, 1825 symbol_conf.default_guest_vmlinux_name,
1803 false, filter); 1826 false);
1804 return err; 1827 return err;
1805 } 1828 }
1806 1829
@@ -1812,7 +1835,7 @@ static int dso__load_guest_kernel_sym(struct dso *dso, struct map *map,
1812 kallsyms_filename = path; 1835 kallsyms_filename = path;
1813 } 1836 }
1814 1837
1815 err = dso__load_kallsyms(dso, kallsyms_filename, map, filter); 1838 err = dso__load_kallsyms(dso, kallsyms_filename, map);
1816 if (err > 0) 1839 if (err > 0)
1817 pr_debug("Using %s for symbols\n", kallsyms_filename); 1840 pr_debug("Using %s for symbols\n", kallsyms_filename);
1818 if (err > 0 && !dso__is_kcore(dso)) { 1841 if (err > 0 && !dso__is_kcore(dso)) {
@@ -1933,22 +1956,39 @@ int setup_intlist(struct intlist **list, const char *list_str,
1933static bool symbol__read_kptr_restrict(void) 1956static bool symbol__read_kptr_restrict(void)
1934{ 1957{
1935 bool value = false; 1958 bool value = false;
1959 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r");
1936 1960
1937 if (geteuid() != 0) { 1961 if (fp != NULL) {
1938 FILE *fp = fopen("/proc/sys/kernel/kptr_restrict", "r"); 1962 char line[8];
1939 if (fp != NULL) {
1940 char line[8];
1941 1963
1942 if (fgets(line, sizeof(line), fp) != NULL) 1964 if (fgets(line, sizeof(line), fp) != NULL)
1943 value = atoi(line) != 0; 1965 value = (geteuid() != 0) ?
1966 (atoi(line) != 0) :
1967 (atoi(line) == 2);
1944 1968
1945 fclose(fp); 1969 fclose(fp);
1946 }
1947 } 1970 }
1948 1971
1949 return value; 1972 return value;
1950} 1973}
1951 1974
1975int symbol__annotation_init(void)
1976{
1977 if (symbol_conf.initialized) {
1978 pr_err("Annotation needs to be init before symbol__init()\n");
1979 return -1;
1980 }
1981
1982 if (symbol_conf.init_annotation) {
1983 pr_warning("Annotation being initialized multiple times\n");
1984 return 0;
1985 }
1986
1987 symbol_conf.priv_size += sizeof(struct annotation);
1988 symbol_conf.init_annotation = true;
1989 return 0;
1990}
1991
1952int symbol__init(struct perf_env *env) 1992int symbol__init(struct perf_env *env)
1953{ 1993{
1954 const char *symfs; 1994 const char *symfs;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index b10d558a8803..d964844eb314 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -57,7 +57,7 @@ struct symbol {
57 u64 end; 57 u64 end;
58 u16 namelen; 58 u16 namelen;
59 u8 binding; 59 u8 binding;
60 bool ignore; 60 u8 idle:1;
61 u8 arch_sym; 61 u8 arch_sym;
62 char name[0]; 62 char name[0];
63}; 63};
@@ -88,6 +88,7 @@ struct symbol_conf {
88 unsigned short priv_size; 88 unsigned short priv_size;
89 unsigned short nr_events; 89 unsigned short nr_events;
90 bool try_vmlinux_path, 90 bool try_vmlinux_path,
91 init_annotation,
91 force, 92 force,
92 ignore_vmlinux, 93 ignore_vmlinux,
93 ignore_vmlinux_buildid, 94 ignore_vmlinux_buildid,
@@ -240,16 +241,13 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
240bool symsrc__has_symtab(struct symsrc *ss); 241bool symsrc__has_symtab(struct symsrc *ss);
241bool symsrc__possibly_runtime(struct symsrc *ss); 242bool symsrc__possibly_runtime(struct symsrc *ss);
242 243
243int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter); 244int dso__load(struct dso *dso, struct map *map);
244int dso__load_vmlinux(struct dso *dso, struct map *map, 245int dso__load_vmlinux(struct dso *dso, struct map *map,
245 const char *vmlinux, bool vmlinux_allocated, 246 const char *vmlinux, bool vmlinux_allocated);
246 symbol_filter_t filter); 247int dso__load_vmlinux_path(struct dso *dso, struct map *map);
247int dso__load_vmlinux_path(struct dso *dso, struct map *map,
248 symbol_filter_t filter);
249int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 248int __dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map,
250 bool no_kcore, symbol_filter_t filter); 249 bool no_kcore);
251int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map, 250int dso__load_kallsyms(struct dso *dso, const char *filename, struct map *map);
252 symbol_filter_t filter);
253 251
254void dso__insert_symbol(struct dso *dso, enum map_type type, 252void dso__insert_symbol(struct dso *dso, enum map_type type,
255 struct symbol *sym); 253 struct symbol *sym);
@@ -261,6 +259,7 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
261struct symbol *symbol__next_by_name(struct symbol *sym); 259struct symbol *symbol__next_by_name(struct symbol *sym);
262 260
263struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); 261struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
262struct symbol *dso__last_symbol(struct dso *dso, enum map_type type);
264struct symbol *dso__next_symbol(struct symbol *sym); 263struct symbol *dso__next_symbol(struct symbol *sym);
265 264
266enum dso_type dso__type_fd(int fd); 265enum dso_type dso__type_fd(int fd);
@@ -277,6 +276,8 @@ struct perf_env;
277int symbol__init(struct perf_env *env); 276int symbol__init(struct perf_env *env);
278void symbol__exit(void); 277void symbol__exit(void);
279void symbol__elf_init(void); 278void symbol__elf_init(void);
279int symbol__annotation_init(void);
280
280struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name); 281struct symbol *symbol__new(u64 start, u64 len, u8 binding, const char *name);
281size_t __symbol__fprintf_symname_offs(const struct symbol *sym, 282size_t __symbol__fprintf_symname_offs(const struct symbol *sym,
282 const struct addr_location *al, 283 const struct addr_location *al,
@@ -291,16 +292,15 @@ size_t symbol__fprintf(struct symbol *sym, FILE *fp);
291bool symbol_type__is_a(char symbol_type, enum map_type map_type); 292bool symbol_type__is_a(char symbol_type, enum map_type map_type);
292bool symbol__restricted_filename(const char *filename, 293bool symbol__restricted_filename(const char *filename,
293 const char *restricted_filename); 294 const char *restricted_filename);
294bool symbol__is_idle(struct symbol *sym);
295int symbol__config_symfs(const struct option *opt __maybe_unused, 295int symbol__config_symfs(const struct option *opt __maybe_unused,
296 const char *dir, int unset __maybe_unused); 296 const char *dir, int unset __maybe_unused);
297 297
298int 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,
299 struct symsrc *runtime_ss, symbol_filter_t filter, 299 struct symsrc *runtime_ss, int kmodule);
300 int kmodule);
301int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss, 300int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss,
302 struct map *map, symbol_filter_t filter); 301 struct map *map);
303 302
303void __symbols__insert(struct rb_root *symbols, struct symbol *sym, bool kernel);
304void symbols__insert(struct rb_root *symbols, struct symbol *sym); 304void symbols__insert(struct rb_root *symbols, struct symbol *sym);
305void symbols__fixup_duplicate(struct rb_root *symbols); 305void symbols__fixup_duplicate(struct rb_root *symbols);
306void symbols__fixup_end(struct rb_root *symbols); 306void symbols__fixup_end(struct rb_root *symbols);
@@ -342,4 +342,26 @@ void arch__sym_update(struct symbol *s, GElf_Sym *sym);
342 342
343int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb); 343int arch__choose_best_symbol(struct symbol *syma, struct symbol *symb);
344 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
345#endif /* __PERF_SYMBOL */ 367#endif /* __PERF_SYMBOL */
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 825086aa9a08..d3301529f6a7 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -616,3 +616,10 @@ int thread_stack__process(struct thread *thread, struct comm *comm,
616 616
617 return err; 617 return err;
618} 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 ad44c7944b8e..b7e41c4ebfdd 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -87,6 +87,7 @@ void thread_stack__sample(struct thread *thread, struct ip_callchain *chain,
87 size_t sz, u64 ip); 87 size_t sz, u64 ip);
88int thread_stack__flush(struct thread *thread); 88int thread_stack__flush(struct thread *thread);
89void thread_stack__free(struct thread *thread); 89void thread_stack__free(struct thread *thread);
90size_t thread_stack__depth(struct thread *thread);
90 91
91struct call_return_processor * 92struct call_return_processor *
92call_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 45fcb715a36b..f5af87f66663 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -14,13 +14,12 @@
14 14
15int thread__init_map_groups(struct thread *thread, struct machine *machine) 15int thread__init_map_groups(struct thread *thread, struct machine *machine)
16{ 16{
17 struct thread *leader;
18 pid_t pid = thread->pid_; 17 pid_t pid = thread->pid_;
19 18
20 if (pid == thread->tid || pid == -1) { 19 if (pid == thread->tid || pid == -1) {
21 thread->mg = map_groups__new(machine); 20 thread->mg = map_groups__new(machine);
22 } else { 21 } else {
23 leader = __machine__findnew_thread(machine, pid, pid); 22 struct thread *leader = __machine__findnew_thread(machine, pid, pid);
24 if (leader) { 23 if (leader) {
25 thread->mg = map_groups__get(leader->mg); 24 thread->mg = map_groups__get(leader->mg);
26 thread__put(leader); 25 thread__put(leader);
@@ -43,9 +42,6 @@ struct thread *thread__new(pid_t pid, pid_t tid)
43 thread->cpu = -1; 42 thread->cpu = -1;
44 INIT_LIST_HEAD(&thread->comm_list); 43 INIT_LIST_HEAD(&thread->comm_list);
45 44
46 if (unwind__prepare_access(thread) < 0)
47 goto err_thread;
48
49 comm_str = malloc(32); 45 comm_str = malloc(32);
50 if (!comm_str) 46 if (!comm_str)
51 goto err_thread; 47 goto err_thread;
@@ -133,11 +129,10 @@ int __thread__set_comm(struct thread *thread, const char *str, u64 timestamp,
133 bool exec) 129 bool exec)
134{ 130{
135 struct comm *new, *curr = thread__comm(thread); 131 struct comm *new, *curr = thread__comm(thread);
136 int err;
137 132
138 /* Override the default :tid entry */ 133 /* Override the default :tid entry */
139 if (!thread->comm_set) { 134 if (!thread->comm_set) {
140 err = comm__override(curr, str, timestamp, exec); 135 int err = comm__override(curr, str, timestamp, exec);
141 if (err) 136 if (err)
142 return err; 137 return err;
143 } else { 138 } else {
@@ -201,10 +196,51 @@ size_t thread__fprintf(struct thread *thread, FILE *fp)
201 map_groups__fprintf(thread->mg, fp); 196 map_groups__fprintf(thread->mg, fp);
202} 197}
203 198
204void thread__insert_map(struct thread *thread, struct map *map) 199int thread__insert_map(struct thread *thread, struct map *map)
205{ 200{
201 int ret;
202
203 ret = unwind__prepare_access(thread, map, NULL);
204 if (ret)
205 return ret;
206
206 map_groups__fixup_overlappings(thread->mg, map, stderr); 207 map_groups__fixup_overlappings(thread->mg, map, stderr);
207 map_groups__insert(thread->mg, map); 208 map_groups__insert(thread->mg, map);
209
210 return 0;
211}
212
213static int __thread__prepare_access(struct thread *thread)
214{
215 bool initialized = false;
216 int i, err = 0;
217
218 for (i = 0; i < MAP__NR_TYPES; ++i) {
219 struct maps *maps = &thread->mg->maps[i];
220 struct map *map;
221
222 pthread_rwlock_rdlock(&maps->lock);
223
224 for (map = maps__first(maps); map; map = map__next(map)) {
225 err = unwind__prepare_access(thread, map, &initialized);
226 if (err || initialized)
227 break;
228 }
229
230 pthread_rwlock_unlock(&maps->lock);
231 }
232
233 return err;
234}
235
236static int thread__prepare_access(struct thread *thread)
237{
238 int err = 0;
239
240 if (symbol_conf.use_callchain)
241 err = __thread__prepare_access(thread);
242
243 return err;
208} 244}
209 245
210static int thread__clone_map_groups(struct thread *thread, 246static int thread__clone_map_groups(struct thread *thread,
@@ -214,7 +250,7 @@ static int thread__clone_map_groups(struct thread *thread,
214 250
215 /* This is new thread, we share map groups for process. */ 251 /* This is new thread, we share map groups for process. */
216 if (thread->pid_ == parent->pid_) 252 if (thread->pid_ == parent->pid_)
217 return 0; 253 return thread__prepare_access(thread);
218 254
219 if (thread->mg == parent->mg) { 255 if (thread->mg == parent->mg) {
220 pr_debug("broken map groups on thread %d/%d parent %d/%d\n", 256 pr_debug("broken map groups on thread %d/%d parent %d/%d\n",
@@ -224,7 +260,7 @@ static int thread__clone_map_groups(struct thread *thread,
224 260
225 /* But this one is new process, copy maps. */ 261 /* But this one is new process, copy maps. */
226 for (i = 0; i < MAP__NR_TYPES; ++i) 262 for (i = 0; i < MAP__NR_TYPES; ++i)
227 if (map_groups__clone(thread->mg, parent->mg, i) < 0) 263 if (map_groups__clone(thread, parent->mg, i) < 0)
228 return -ENOMEM; 264 return -ENOMEM;
229 265
230 return 0; 266 return 0;
@@ -232,10 +268,9 @@ static int thread__clone_map_groups(struct thread *thread,
232 268
233int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp) 269int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp)
234{ 270{
235 int err;
236
237 if (parent->comm_set) { 271 if (parent->comm_set) {
238 const char *comm = thread__comm_str(parent); 272 const char *comm = thread__comm_str(parent);
273 int err;
239 if (!comm) 274 if (!comm)
240 return -ENOMEM; 275 return -ENOMEM;
241 err = thread__set_comm(thread, comm, timestamp); 276 err = thread__set_comm(thread, comm, timestamp);
@@ -265,3 +300,14 @@ void thread__find_cpumode_addr_location(struct thread *thread,
265 break; 300 break;
266 } 301 }
267} 302}
303
304struct thread *thread__main_thread(struct machine *machine, struct thread *thread)
305{
306 if (thread->pid_ == thread->tid)
307 return thread__get(thread);
308
309 if (thread->pid_ == -1)
310 return NULL;
311
312 return machine__find_thread(machine, thread->pid_, thread->pid_);
313}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 45fba13c800b..99263cb6e6b6 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -9,11 +9,9 @@
9#include "symbol.h" 9#include "symbol.h"
10#include <strlist.h> 10#include <strlist.h>
11#include <intlist.h> 11#include <intlist.h>
12#ifdef HAVE_LIBUNWIND_SUPPORT
13#include <libunwind.h>
14#endif
15 12
16struct thread_stack; 13struct thread_stack;
14struct unwind_libunwind_ops;
17 15
18struct thread { 16struct thread {
19 union { 17 union {
@@ -36,7 +34,8 @@ struct thread {
36 void *priv; 34 void *priv;
37 struct thread_stack *ts; 35 struct thread_stack *ts;
38#ifdef HAVE_LIBUNWIND_SUPPORT 36#ifdef HAVE_LIBUNWIND_SUPPORT
39 unw_addr_space_t addr_space; 37 void *addr_space;
38 struct unwind_libunwind_ops *unwind_libunwind_ops;
40#endif 39#endif
41}; 40};
42 41
@@ -77,10 +76,12 @@ int thread__comm_len(struct thread *thread);
77struct comm *thread__comm(const struct thread *thread); 76struct comm *thread__comm(const struct thread *thread);
78struct comm *thread__exec_comm(const struct thread *thread); 77struct comm *thread__exec_comm(const struct thread *thread);
79const char *thread__comm_str(const struct thread *thread); 78const char *thread__comm_str(const struct thread *thread);
80void thread__insert_map(struct thread *thread, struct map *map); 79int thread__insert_map(struct thread *thread, struct map *map);
81int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp); 80int thread__fork(struct thread *thread, struct thread *parent, u64 timestamp);
82size_t thread__fprintf(struct thread *thread, FILE *fp); 81size_t thread__fprintf(struct thread *thread, FILE *fp);
83 82
83struct thread *thread__main_thread(struct machine *machine, struct thread *thread);
84
84void thread__find_addr_map(struct thread *thread, 85void thread__find_addr_map(struct thread *thread,
85 u8 cpumode, enum map_type type, u64 addr, 86 u8 cpumode, enum map_type type, u64 addr,
86 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 5654fe15e036..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 ||
@@ -278,7 +278,7 @@ 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 ||
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/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 63687d3a344e..6d542a4e0648 100644
--- a/tools/perf/util/unwind-libunwind.c
+++ b/tools/perf/util/unwind-libunwind.c
@@ -1,682 +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"
35#include "asm/bug.h" 5#include "arch/common.h"
36
37extern int
38UNW_OBJ(dwarf_search_unwind_table) (unw_addr_space_t as,
39 unw_word_t ip,
40 unw_dyn_info_t *di,
41 unw_proc_info_t *pi,
42 int need_unwind_info, void *arg);
43
44#define dwarf_search_unwind_table UNW_OBJ(dwarf_search_unwind_table)
45
46extern int
47UNW_OBJ(dwarf_find_debug_frame) (int found, unw_dyn_info_t *di_debug,
48 unw_word_t ip,
49 unw_word_t segbase,
50 const char *obj_name, unw_word_t start,
51 unw_word_t end);
52
53#define dwarf_find_debug_frame UNW_OBJ(dwarf_find_debug_frame)
54
55#define DW_EH_PE_FORMAT_MASK 0x0f /* format of the encoded value */
56#define DW_EH_PE_APPL_MASK 0x70 /* how the value is to be applied */
57
58/* Pointer-encoding formats: */
59#define DW_EH_PE_omit 0xff
60#define DW_EH_PE_ptr 0x00 /* pointer-sized unsigned value */
61#define DW_EH_PE_udata4 0x03 /* unsigned 32-bit value */
62#define DW_EH_PE_udata8 0x04 /* unsigned 64-bit value */
63#define DW_EH_PE_sdata4 0x0b /* signed 32-bit value */
64#define DW_EH_PE_sdata8 0x0c /* signed 64-bit value */
65
66/* Pointer-encoding application: */
67#define DW_EH_PE_absptr 0x00 /* absolute value */
68#define DW_EH_PE_pcrel 0x10 /* rel. to addr. of encoded value */
69
70/*
71 * The following are not documented by LSB v1.3, yet they are used by
72 * GCC, presumably they aren't documented by LSB since they aren't
73 * used on Linux:
74 */
75#define DW_EH_PE_funcrel 0x40 /* start-of-procedure-relative */
76#define DW_EH_PE_aligned 0x50 /* aligned pointer */
77 6
78/* Flags intentionaly not handled, since they're not needed: 7struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
79 * #define DW_EH_PE_indirect 0x80 8struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops;
80 * #define DW_EH_PE_uleb128 0x01 9struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops;
81 * #define DW_EH_PE_udata2 0x02
82 * #define DW_EH_PE_sleb128 0x09
83 * #define DW_EH_PE_sdata2 0x0a
84 * #define DW_EH_PE_textrel 0x20
85 * #define DW_EH_PE_datarel 0x30
86 */
87 10
88struct unwind_info { 11static void unwind__register_ops(struct thread *thread,
89 struct perf_sample *sample; 12 struct unwind_libunwind_ops *ops)
90 struct machine *machine;
91 struct thread *thread;
92};
93
94#define dw_read(ptr, type, end) ({ \
95 type *__p = (type *) ptr; \
96 type __v; \
97 if ((__p + 1) > (type *) end) \
98 return -EINVAL; \
99 __v = *__p++; \
100 ptr = (typeof(ptr)) __p; \
101 __v; \
102 })
103
104static int __dw_read_encoded_value(u8 **p, u8 *end, u64 *val,
105 u8 encoding)
106{ 13{
107 u8 *cur = *p; 14 thread->unwind_libunwind_ops = ops;
108 *val = 0;
109
110 switch (encoding) {
111 case DW_EH_PE_omit:
112 *val = 0;
113 goto out;
114 case DW_EH_PE_ptr:
115 *val = dw_read(cur, unsigned long, end);
116 goto out;
117 default:
118 break;
119 }
120
121 switch (encoding & DW_EH_PE_APPL_MASK) {
122 case DW_EH_PE_absptr:
123 break;
124 case DW_EH_PE_pcrel:
125 *val = (unsigned long) cur;
126 break;
127 default:
128 return -EINVAL;
129 }
130
131 if ((encoding & 0x07) == 0x00)
132 encoding |= DW_EH_PE_udata4;
133
134 switch (encoding & DW_EH_PE_FORMAT_MASK) {
135 case DW_EH_PE_sdata4:
136 *val += dw_read(cur, s32, end);
137 break;
138 case DW_EH_PE_udata4:
139 *val += dw_read(cur, u32, end);
140 break;
141 case DW_EH_PE_sdata8:
142 *val += dw_read(cur, s64, end);
143 break;
144 case DW_EH_PE_udata8:
145 *val += dw_read(cur, u64, end);
146 break;
147 default:
148 return -EINVAL;
149 }
150
151 out:
152 *p = cur;
153 return 0;
154}
155
156#define dw_read_encoded_value(ptr, end, enc) ({ \
157 u64 __v; \
158 if (__dw_read_encoded_value(&ptr, end, &__v, enc)) { \
159 return -EINVAL; \
160 } \
161 __v; \
162 })
163
164static u64 elf_section_offset(int fd, const char *name)
165{
166 Elf *elf;
167 GElf_Ehdr ehdr;
168 GElf_Shdr shdr;
169 u64 offset = 0;
170
171 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
172 if (elf == NULL)
173 return 0;
174
175 do {
176 if (gelf_getehdr(elf, &ehdr) == NULL)
177 break;
178
179 if (!elf_section_by_name(elf, &ehdr, &shdr, name, NULL))
180 break;
181
182 offset = shdr.sh_offset;
183 } while (0);
184
185 elf_end(elf);
186 return offset;
187} 15}
188 16
189#ifndef NO_LIBUNWIND_DEBUG_FRAME 17int unwind__prepare_access(struct thread *thread, struct map *map,
190static int elf_is_exec(int fd, const char *name) 18 bool *initialized)
191{ 19{
192 Elf *elf; 20 const char *arch;
193 GElf_Ehdr ehdr; 21 enum dso_type dso_type;
194 int retval = 0; 22 struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops;
23 int err;
195 24
196 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL); 25 if (thread->addr_space) {
197 if (elf == NULL) 26 pr_debug("unwind: thread map already set, dso=%s\n",
27 map->dso->name);
28 if (initialized)
29 *initialized = true;
198 return 0; 30 return 0;
199 if (gelf_getehdr(elf, &ehdr) == NULL)
200 goto out;
201
202 retval = (ehdr.e_type == ET_EXEC);
203
204out:
205 elf_end(elf);
206 pr_debug("unwind: elf_is_exec(%s): %d\n", name, retval);
207 return retval;
208}
209#endif
210
211struct table_entry {
212 u32 start_ip_offset;
213 u32 fde_offset;
214};
215
216struct eh_frame_hdr {
217 unsigned char version;
218 unsigned char eh_frame_ptr_enc;
219 unsigned char fde_count_enc;
220 unsigned char table_enc;
221
222 /*
223 * The rest of the header is variable-length and consists of the
224 * following members:
225 *
226 * encoded_t eh_frame_ptr;
227 * encoded_t fde_count;
228 */
229
230 /* A single encoded pointer should not be more than 8 bytes. */
231 u64 enc[2];
232
233 /*
234 * struct {
235 * encoded_t start_ip;
236 * encoded_t fde_addr;
237 * } binary_search_table[fde_count];
238 */
239 char data[0];
240} __packed;
241
242static int unwind_spec_ehframe(struct dso *dso, struct machine *machine,
243 u64 offset, u64 *table_data, u64 *segbase,
244 u64 *fde_count)
245{
246 struct eh_frame_hdr hdr;
247 u8 *enc = (u8 *) &hdr.enc;
248 u8 *end = (u8 *) &hdr.data;
249 ssize_t r;
250
251 r = dso__data_read_offset(dso, machine, offset,
252 (u8 *) &hdr, sizeof(hdr));
253 if (r != sizeof(hdr))
254 return -EINVAL;
255
256 /* We dont need eh_frame_ptr, just skip it. */
257 dw_read_encoded_value(enc, end, hdr.eh_frame_ptr_enc);
258
259 *fde_count = dw_read_encoded_value(enc, end, hdr.fde_count_enc);
260 *segbase = offset;
261 *table_data = (enc - (u8 *) &hdr) + offset;
262 return 0;
263}
264
265static int read_unwind_spec_eh_frame(struct dso *dso, struct machine *machine,
266 u64 *table_data, u64 *segbase,
267 u64 *fde_count)
268{
269 int ret = -EINVAL, fd;
270 u64 offset = dso->data.eh_frame_hdr_offset;
271
272 if (offset == 0) {
273 fd = dso__data_get_fd(dso, machine);
274 if (fd < 0)
275 return -EINVAL;
276
277 /* Check the .eh_frame section for unwinding info */
278 offset = elf_section_offset(fd, ".eh_frame_hdr");
279 dso->data.eh_frame_hdr_offset = offset;
280 dso__data_put_fd(dso);
281 } 31 }
282 32
283 if (offset) 33 /* env->arch is NULL for live-mode (i.e. perf top) */
284 ret = unwind_spec_ehframe(dso, machine, offset, 34 if (!thread->mg->machine->env || !thread->mg->machine->env->arch)
285 table_data, segbase, 35 goto out_register;
286 fde_count);
287 36
288 return ret; 37 dso_type = dso__type(map->dso, thread->mg->machine);
289} 38 if (dso_type == DSO__TYPE_UNKNOWN)
290
291#ifndef NO_LIBUNWIND_DEBUG_FRAME
292static int read_unwind_spec_debug_frame(struct dso *dso,
293 struct machine *machine, u64 *offset)
294{
295 int fd;
296 u64 ofs = dso->data.debug_frame_offset;
297
298 if (ofs == 0) {
299 fd = dso__data_get_fd(dso, machine);
300 if (fd < 0)
301 return -EINVAL;
302
303 /* Check the .debug_frame section for unwinding info */
304 ofs = elf_section_offset(fd, ".debug_frame");
305 dso->data.debug_frame_offset = ofs;
306 dso__data_put_fd(dso);
307 }
308
309 *offset = ofs;
310 if (*offset)
311 return 0; 39 return 0;
312 40
313 return -EINVAL; 41 arch = normalize_arch(thread->mg->machine->env->arch);
314}
315#endif
316
317static struct map *find_map(unw_word_t ip, struct unwind_info *ui)
318{
319 struct addr_location al;
320
321 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
322 MAP__FUNCTION, ip, &al);
323 if (!al.map) {
324 /*
325 * We've seen cases (softice) where DWARF unwinder went
326 * through non executable mmaps, which we need to lookup
327 * in MAP__VARIABLE tree.
328 */
329 thread__find_addr_map(ui->thread, PERF_RECORD_MISC_USER,
330 MAP__VARIABLE, ip, &al);
331 }
332 return al.map;
333}
334
335static int
336find_proc_info(unw_addr_space_t as, unw_word_t ip, unw_proc_info_t *pi,
337 int need_unwind_info, void *arg)
338{
339 struct unwind_info *ui = arg;
340 struct map *map;
341 unw_dyn_info_t di;
342 u64 table_data, segbase, fde_count;
343 int ret = -EINVAL;
344
345 map = find_map(ip, ui);
346 if (!map || !map->dso)
347 return -EINVAL;
348
349 pr_debug("unwind: find_proc_info dso %s\n", map->dso->name);
350
351 /* Check the .eh_frame section for unwinding info */
352 if (!read_unwind_spec_eh_frame(map->dso, ui->machine,
353 &table_data, &segbase, &fde_count)) {
354 memset(&di, 0, sizeof(di));
355 di.format = UNW_INFO_FORMAT_REMOTE_TABLE;
356 di.start_ip = map->start;
357 di.end_ip = map->end;
358 di.u.rti.segbase = map->start + segbase;
359 di.u.rti.table_data = map->start + table_data;
360 di.u.rti.table_len = fde_count * sizeof(struct table_entry)
361 / sizeof(unw_word_t);
362 ret = dwarf_search_unwind_table(as, ip, &di, pi,
363 need_unwind_info, arg);
364 }
365
366#ifndef NO_LIBUNWIND_DEBUG_FRAME
367 /* Check the .debug_frame section for unwinding info */
368 if (ret < 0 &&
369 !read_unwind_spec_debug_frame(map->dso, ui->machine, &segbase)) {
370 int fd = dso__data_get_fd(map->dso, ui->machine);
371 int is_exec = elf_is_exec(fd, map->dso->name);
372 unw_word_t base = is_exec ? 0 : map->start;
373 const char *symfile;
374
375 if (fd >= 0)
376 dso__data_put_fd(map->dso);
377
378 symfile = map->dso->symsrc_filename ?: map->dso->name;
379
380 memset(&di, 0, sizeof(di));
381 if (dwarf_find_debug_frame(0, &di, ip, base, symfile,
382 map->start, map->end))
383 return dwarf_search_unwind_table(as, ip, &di, pi,
384 need_unwind_info, arg);
385 }
386#endif
387
388 return ret;
389}
390
391static int access_fpreg(unw_addr_space_t __maybe_unused as,
392 unw_regnum_t __maybe_unused num,
393 unw_fpreg_t __maybe_unused *val,
394 int __maybe_unused __write,
395 void __maybe_unused *arg)
396{
397 pr_err("unwind: access_fpreg unsupported\n");
398 return -UNW_EINVAL;
399}
400
401static int get_dyn_info_list_addr(unw_addr_space_t __maybe_unused as,
402 unw_word_t __maybe_unused *dil_addr,
403 void __maybe_unused *arg)
404{
405 return -UNW_ENOINFO;
406}
407
408static int resume(unw_addr_space_t __maybe_unused as,
409 unw_cursor_t __maybe_unused *cu,
410 void __maybe_unused *arg)
411{
412 pr_err("unwind: resume unsupported\n");
413 return -UNW_EINVAL;
414}
415 42
416static int 43 if (!strcmp(arch, "x86")) {
417get_proc_name(unw_addr_space_t __maybe_unused as, 44 if (dso_type != DSO__TYPE_64BIT)
418 unw_word_t __maybe_unused addr, 45 ops = x86_32_unwind_libunwind_ops;
419 char __maybe_unused *bufp, size_t __maybe_unused buf_len, 46 } else if (!strcmp(arch, "arm64") || !strcmp(arch, "arm")) {
420 unw_word_t __maybe_unused *offp, void __maybe_unused *arg) 47 if (dso_type == DSO__TYPE_64BIT)
421{ 48 ops = arm64_unwind_libunwind_ops;
422 pr_err("unwind: get_proc_name unsupported\n");
423 return -UNW_EINVAL;
424}
425
426static int access_dso_mem(struct unwind_info *ui, unw_word_t addr,
427 unw_word_t *data)
428{
429 struct map *map;
430 ssize_t size;
431
432 map = find_map(addr, ui);
433 if (!map) {
434 pr_debug("unwind: no map for %lx\n", (unsigned long)addr);
435 return -1;
436 } 49 }
437 50
438 if (!map->dso) 51 if (!ops) {
52 pr_err("unwind: target platform=%s is not supported\n", arch);
439 return -1; 53 return -1;
440
441 size = dso__data_read_addr(map->dso, map, ui->machine,
442 addr, (u8 *) data, sizeof(*data));
443
444 return !(size == sizeof(*data));
445}
446
447static int access_mem(unw_addr_space_t __maybe_unused as,
448 unw_word_t addr, unw_word_t *valp,
449 int __write, void *arg)
450{
451 struct unwind_info *ui = arg;
452 struct stack_dump *stack = &ui->sample->user_stack;
453 u64 start, end;
454 int offset;
455 int ret;
456
457 /* Don't support write, probably not needed. */
458 if (__write || !stack || !ui->sample->user_regs.regs) {
459 *valp = 0;
460 return 0;
461 }
462
463 ret = perf_reg_value(&start, &ui->sample->user_regs, PERF_REG_SP);
464 if (ret)
465 return ret;
466
467 end = start + stack->size;
468
469 /* Check overflow. */
470 if (addr + sizeof(unw_word_t) < addr)
471 return -EINVAL;
472
473 if (addr < start || addr + sizeof(unw_word_t) >= end) {
474 ret = access_dso_mem(ui, addr, valp);
475 if (ret) {
476 pr_debug("unwind: access_mem %p not inside range"
477 " 0x%" PRIx64 "-0x%" PRIx64 "\n",
478 (void *) (uintptr_t) addr, start, end);
479 *valp = 0;
480 return ret;
481 }
482 return 0;
483 }
484
485 offset = addr - start;
486 *valp = *(unw_word_t *)&stack->data[offset];
487 pr_debug("unwind: access_mem addr %p val %lx, offset %d\n",
488 (void *) (uintptr_t) addr, (unsigned long)*valp, offset);
489 return 0;
490}
491
492static int access_reg(unw_addr_space_t __maybe_unused as,
493 unw_regnum_t regnum, unw_word_t *valp,
494 int __write, void *arg)
495{
496 struct unwind_info *ui = arg;
497 int id, ret;
498 u64 val;
499
500 /* Don't support write, I suspect we don't need it. */
501 if (__write) {
502 pr_err("unwind: access_reg w %d\n", regnum);
503 return 0;
504 }
505
506 if (!ui->sample->user_regs.regs) {
507 *valp = 0;
508 return 0;
509 }
510
511 id = libunwind__arch_reg_id(regnum);
512 if (id < 0)
513 return -EINVAL;
514
515 ret = perf_reg_value(&val, &ui->sample->user_regs, id);
516 if (ret) {
517 pr_err("unwind: can't read reg %d\n", regnum);
518 return ret;
519 }
520
521 *valp = (unw_word_t) val;
522 pr_debug("unwind: reg %d, val %lx\n", regnum, (unsigned long)*valp);
523 return 0;
524}
525
526static void put_unwind_info(unw_addr_space_t __maybe_unused as,
527 unw_proc_info_t *pi __maybe_unused,
528 void *arg __maybe_unused)
529{
530 pr_debug("unwind: put_unwind_info called\n");
531}
532
533static int entry(u64 ip, struct thread *thread,
534 unwind_entry_cb_t cb, void *arg)
535{
536 struct unwind_entry e;
537 struct addr_location al;
538
539 thread__find_addr_location(thread, PERF_RECORD_MISC_USER,
540 MAP__FUNCTION, ip, &al);
541
542 e.ip = ip;
543 e.map = al.map;
544 e.sym = al.sym;
545
546 pr_debug("unwind: %s:ip = 0x%" PRIx64 " (0x%" PRIx64 ")\n",
547 al.sym ? al.sym->name : "''",
548 ip,
549 al.map ? al.map->map_ip(al.map, ip) : (u64) 0);
550
551 return cb(&e, arg);
552}
553
554static void display_error(int err)
555{
556 switch (err) {
557 case UNW_EINVAL:
558 pr_err("unwind: Only supports local.\n");
559 break;
560 case UNW_EUNSPEC:
561 pr_err("unwind: Unspecified error.\n");
562 break;
563 case UNW_EBADREG:
564 pr_err("unwind: Register unavailable.\n");
565 break;
566 default:
567 break;
568 }
569}
570
571static unw_accessors_t accessors = {
572 .find_proc_info = find_proc_info,
573 .put_unwind_info = put_unwind_info,
574 .get_dyn_info_list_addr = get_dyn_info_list_addr,
575 .access_mem = access_mem,
576 .access_reg = access_reg,
577 .access_fpreg = access_fpreg,
578 .resume = resume,
579 .get_proc_name = get_proc_name,
580};
581
582int unwind__prepare_access(struct thread *thread)
583{
584 if (callchain_param.record_mode != CALLCHAIN_DWARF)
585 return 0;
586
587 thread->addr_space = unw_create_addr_space(&accessors, 0);
588 if (!thread->addr_space) {
589 pr_err("unwind: Can't create unwind address space.\n");
590 return -ENOMEM;
591 } 54 }
55out_register:
56 unwind__register_ops(thread, ops);
592 57
593 unw_set_caching_policy(thread->addr_space, UNW_CACHE_GLOBAL); 58 err = thread->unwind_libunwind_ops->prepare_access(thread);
594 return 0; 59 if (initialized)
60 *initialized = err ? false : true;
61 return err;
595} 62}
596 63
597void unwind__flush_access(struct thread *thread) 64void unwind__flush_access(struct thread *thread)
598{ 65{
599 if (callchain_param.record_mode != CALLCHAIN_DWARF) 66 if (thread->unwind_libunwind_ops)
600 return; 67 thread->unwind_libunwind_ops->flush_access(thread);
601
602 unw_flush_cache(thread->addr_space, 0, 0);
603} 68}
604 69
605void unwind__finish_access(struct thread *thread) 70void unwind__finish_access(struct thread *thread)
606{ 71{
607 if (callchain_param.record_mode != CALLCHAIN_DWARF) 72 if (thread->unwind_libunwind_ops)
608 return; 73 thread->unwind_libunwind_ops->finish_access(thread);
609
610 unw_destroy_addr_space(thread->addr_space);
611}
612
613static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
614 void *arg, int max_stack)
615{
616 u64 val;
617 unw_word_t ips[max_stack];
618 unw_addr_space_t addr_space;
619 unw_cursor_t c;
620 int ret, i = 0;
621
622 ret = perf_reg_value(&val, &ui->sample->user_regs, PERF_REG_IP);
623 if (ret)
624 return ret;
625
626 ips[i++] = (unw_word_t) val;
627
628 /*
629 * If we need more than one entry, do the DWARF
630 * unwind itself.
631 */
632 if (max_stack - 1 > 0) {
633 WARN_ONCE(!ui->thread, "WARNING: ui->thread is NULL");
634 addr_space = ui->thread->addr_space;
635
636 if (addr_space == NULL)
637 return -1;
638
639 ret = unw_init_remote(&c, addr_space, ui);
640 if (ret)
641 display_error(ret);
642
643 while (!ret && (unw_step(&c) > 0) && i < max_stack) {
644 unw_get_reg(&c, UNW_REG_IP, &ips[i]);
645 ++i;
646 }
647
648 max_stack = i;
649 }
650
651 /*
652 * Display what we got based on the order setup.
653 */
654 for (i = 0; i < max_stack && !ret; i++) {
655 int j = i;
656
657 if (callchain_param.order == ORDER_CALLER)
658 j = max_stack - i - 1;
659 ret = ips[j] ? entry(ips[j], ui->thread, cb, arg) : 0;
660 }
661
662 return ret;
663} 74}
664 75
665int unwind__get_entries(unwind_entry_cb_t cb, void *arg, 76int unwind__get_entries(unwind_entry_cb_t cb, void *arg,
666 struct thread *thread, 77 struct thread *thread,
667 struct perf_sample *data, int max_stack) 78 struct perf_sample *data, int max_stack)
668{ 79{
669 struct unwind_info ui = { 80 if (thread->unwind_libunwind_ops)
670 .sample = data, 81 return thread->unwind_libunwind_ops->get_entries(cb, arg, thread, data, max_stack);
671 .thread = thread, 82 return 0;
672 .machine = thread->mg->machine,
673 };
674
675 if (!data->user_regs.regs)
676 return -EINVAL;
677
678 if (max_stack <= 0)
679 return -EINVAL;
680
681 return get_entries(&ui, cb, arg, max_stack);
682} 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 23504ad5d6dd..85c56800f17a 100644
--- a/tools/perf/util/util.c
+++ b/tools/perf/util/util.c
@@ -15,16 +15,24 @@
15#include <byteswap.h> 15#include <byteswap.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/log2.h> 17#include <linux/log2.h>
18#include <linux/time64.h>
18#include <unistd.h> 19#include <unistd.h>
19#include "callchain.h" 20#include "callchain.h"
20#include "strlist.h" 21#include "strlist.h"
21 22
22struct callchain_param callchain_param = { 23#define CALLCHAIN_PARAM_DEFAULT \
23 .mode = CHAIN_GRAPH_ABS, 24 .mode = CHAIN_GRAPH_ABS, \
24 .min_percent = 0.5, 25 .min_percent = 0.5, \
25 .order = ORDER_CALLEE, 26 .order = ORDER_CALLEE, \
26 .key = CCKEY_FUNCTION, 27 .key = CCKEY_FUNCTION, \
27 .value = CCVAL_PERCENT, 28 .value = CCVAL_PERCENT, \
29
30struct callchain_param callchain_param = {
31 CALLCHAIN_PARAM_DEFAULT
32};
33
34struct callchain_param callchain_param_default = {
35 CALLCHAIN_PARAM_DEFAULT
28}; 36};
29 37
30/* 38/*
@@ -97,20 +105,17 @@ int rm_rf(char *path)
97 scnprintf(namebuf, sizeof(namebuf), "%s/%s", 105 scnprintf(namebuf, sizeof(namebuf), "%s/%s",
98 path, d->d_name); 106 path, d->d_name);
99 107
100 ret = stat(namebuf, &statbuf); 108 /* We have to check symbolic link itself */
109 ret = lstat(namebuf, &statbuf);
101 if (ret < 0) { 110 if (ret < 0) {
102 pr_debug("stat failed: %s\n", namebuf); 111 pr_debug("stat failed: %s\n", namebuf);
103 break; 112 break;
104 } 113 }
105 114
106 if (S_ISREG(statbuf.st_mode)) 115 if (S_ISDIR(statbuf.st_mode))
107 ret = unlink(namebuf);
108 else if (S_ISDIR(statbuf.st_mode))
109 ret = rm_rf(namebuf); 116 ret = rm_rf(namebuf);
110 else { 117 else
111 pr_debug("unknown file: %s\n", namebuf); 118 ret = unlink(namebuf);
112 ret = -1;
113 }
114 } 119 }
115 closedir(dir); 120 closedir(dir);
116 121
@@ -742,3 +747,19 @@ void print_binary(unsigned char *data, size_t len,
742 } 747 }
743 printer(BINARY_PRINT_DATA_END, -1, extra); 748 printer(BINARY_PRINT_DATA_END, -1, extra);
744} 749}
750
751int is_printable_array(char *p, unsigned int len)
752{
753 unsigned int i;
754
755 if (!p || !len || p[len - 1] != 0)
756 return 0;
757
758 len--;
759
760 for (i = 0; i < len; i++) {
761 if (!isprint(p[i]) && !isspace(p[i]))
762 return 0;
763 }
764 return 1;
765}
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 1e8c3167b9fb..43899e0d6fa1 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -72,7 +72,6 @@
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>
@@ -180,10 +179,6 @@ static inline void *zalloc(size_t size)
180#undef tolower 179#undef tolower
181#undef toupper 180#undef toupper
182 181
183#ifndef NSEC_PER_MSEC
184#define NSEC_PER_MSEC 1000000L
185#endif
186
187int parse_nsec_time(const char *str, u64 *ptime); 182int parse_nsec_time(const char *str, u64 *ptime);
188 183
189extern unsigned char sane_ctype[256]; 184extern unsigned char sane_ctype[256];
@@ -360,4 +355,10 @@ typedef void (*print_binary_t)(enum binary_printer_ops,
360void print_binary(unsigned char *data, size_t len, 355void print_binary(unsigned char *data, size_t len,
361 size_t bytes_per_line, print_binary_t printer, 356 size_t bytes_per_line, print_binary_t printer,
362 void *extra); 357 void *extra);
358
359#if !defined(__GLIBC__) && !defined(__ANDROID__)
360extern int sched_getcpu(void);
361#endif
362
363int is_printable_array(char *p, unsigned int len);
363#endif /* GIT_COMPAT_UTIL_H */ 364#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;