aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorMark Brown <broonie@kernel.org>2016-11-04 14:16:38 -0400
committerMark Brown <broonie@kernel.org>2016-11-04 14:16:38 -0400
commitcc9b94029e9ef51787af908e9856b1eed314bc00 (patch)
tree9675310b89d0f6fb1f7bd9423f0638c4ee5226fd /tools
parent13bed58ce8748d430a26e353a09b89f9d613a71f (diff)
parent1b5b42216469b05ef4b5916cb40b127dfab1da88 (diff)
Merge branch 'topic/error' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator into regulator-fixed
Diffstat (limited to 'tools')
-rw-r--r--tools/Makefile7
-rw-r--r--tools/accounting/.gitignore1
-rw-r--r--tools/accounting/Makefile9
-rw-r--r--tools/accounting/getdelays.c550
-rw-r--r--tools/arch/alpha/include/uapi/asm/bitsperlong.h8
-rw-r--r--tools/arch/alpha/include/uapi/asm/mman.h47
-rw-r--r--tools/arch/arc/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/arm/include/uapi/asm/kvm.h224
-rw-r--r--tools/arch/arm/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/arm/include/uapi/asm/perf_regs.h23
-rw-r--r--tools/arch/arm64/include/uapi/asm/bitsperlong.h23
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h260
-rw-r--r--tools/arch/arm64/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/arm64/include/uapi/asm/perf_regs.h40
-rw-r--r--tools/arch/frv/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/frv/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/h8300/include/asm/bitsperlong.h14
-rw-r--r--tools/arch/h8300/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/hexagon/include/uapi/asm/bitsperlong.h26
-rw-r--r--tools/arch/hexagon/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/ia64/include/uapi/asm/bitsperlong.h8
-rw-r--r--tools/arch/ia64/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/m32r/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/m32r/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/microblaze/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/microblaze/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/mips/include/uapi/asm/bitsperlong.h8
-rw-r--r--tools/arch/mips/include/uapi/asm/kvm.h208
-rw-r--r--tools/arch/mips/include/uapi/asm/mman.h46
-rw-r--r--tools/arch/mn10300/include/uapi/asm/bitsperlong.h1
-rw-r--r--tools/arch/mn10300/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/parisc/include/uapi/asm/bitsperlong.h14
-rw-r--r--tools/arch/parisc/include/uapi/asm/mman.h47
-rw-r--r--tools/arch/powerpc/include/uapi/asm/bitsperlong.h12
-rw-r--r--tools/arch/powerpc/include/uapi/asm/kvm.h612
-rw-r--r--tools/arch/powerpc/include/uapi/asm/mman.h15
-rw-r--r--tools/arch/powerpc/include/uapi/asm/perf_regs.h50
-rw-r--r--tools/arch/s390/include/uapi/asm/bitsperlong.h12
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm.h233
-rw-r--r--tools/arch/s390/include/uapi/asm/kvm_perf.h25
-rw-r--r--tools/arch/s390/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/s390/include/uapi/asm/sie.h251
-rw-r--r--tools/arch/score/include/uapi/asm/bitsperlong.h6
-rw-r--r--tools/arch/score/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/sh/include/uapi/asm/mman.h6
-rw-r--r--tools/arch/sparc/include/uapi/asm/bitsperlong.h12
-rw-r--r--tools/arch/sparc/include/uapi/asm/mman.h15
-rw-r--r--tools/arch/tile/include/uapi/asm/bitsperlong.h26
-rw-r--r--tools/arch/tile/include/uapi/asm/mman.h15
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h312
-rw-r--r--tools/arch/x86/include/asm/disabled-features.h62
-rw-r--r--tools/arch/x86/include/asm/required-features.h105
-rw-r--r--tools/arch/x86/include/asm/unistd_32.h12
-rw-r--r--tools/arch/x86/include/asm/unistd_64.h12
-rw-r--r--tools/arch/x86/include/uapi/asm/bitsperlong.h12
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h360
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm_perf.h16
-rw-r--r--tools/arch/x86/include/uapi/asm/mman.h5
-rw-r--r--tools/arch/x86/include/uapi/asm/perf_regs.h33
-rw-r--r--tools/arch/x86/include/uapi/asm/svm.h178
-rw-r--r--tools/arch/x86/include/uapi/asm/vmx.h134
-rw-r--r--tools/arch/x86/lib/memcpy_64.S297
-rw-r--r--tools/arch/x86/lib/memset_64.S138
-rw-r--r--tools/arch/xtensa/include/uapi/asm/mman.h47
-rw-r--r--tools/build/Build2
-rw-r--r--tools/build/Build.include6
-rw-r--r--tools/build/Makefile8
-rw-r--r--tools/build/Makefile.build26
-rw-r--r--tools/build/Makefile.feature7
-rw-r--r--tools/build/Makefile.include4
-rw-r--r--tools/build/feature/Makefile22
-rw-r--r--tools/build/feature/test-all.c15
-rw-r--r--tools/build/feature/test-cxx.cpp15
-rw-r--r--tools/build/feature/test-libelf-gelf_getnote.c7
-rw-r--r--tools/build/feature/test-libelf-getshdrstrndx.c8
-rw-r--r--tools/build/feature/test-sdt.c7
-rw-r--r--tools/gpio/Build3
-rw-r--r--tools/gpio/Makefile75
-rw-r--r--tools/gpio/gpio-event-mon.c192
-rw-r--r--tools/gpio/gpio-hammer.c189
-rwxr-xr-xtools/hv/bondvf.sh193
-rw-r--r--tools/hv/hv_kvp_daemon.c2
-rw-r--r--tools/hv/hv_vss_daemon.c3
-rw-r--r--tools/iio/Makefile21
-rw-r--r--tools/iio/iio_generic_buffer.c (renamed from tools/iio/generic_buffer.c)263
-rw-r--r--tools/iio/iio_utils.c11
-rw-r--r--tools/iio/lsiio.c3
-rw-r--r--tools/include/asm-generic/bitops/__ffs.h1
-rw-r--r--tools/include/asm-generic/bitops/__fls.h44
-rw-r--r--tools/include/asm-generic/bitops/arch_hweight.h26
-rw-r--r--tools/include/asm-generic/bitops/atomic.h1
-rw-r--r--tools/include/asm-generic/bitops/const_hweight.h44
-rw-r--r--tools/include/asm-generic/bitops/fls.h42
-rw-r--r--tools/include/asm-generic/bitops/fls64.h37
-rw-r--r--tools/include/asm-generic/bitsperlong.h20
-rw-r--r--tools/include/asm/alternative-asm.h (renamed from tools/perf/util/include/asm/alternative-asm.h)4
-rw-r--r--tools/include/linux/bitmap.h37
-rw-r--r--tools/include/linux/bitops.h4
-rw-r--r--tools/include/linux/compiler.h11
-rw-r--r--tools/include/linux/coresight-pmu.h39
-rw-r--r--tools/include/linux/hash.h105
-rw-r--r--tools/include/linux/kernel.h28
-rw-r--r--tools/include/linux/poison.h91
-rw-r--r--tools/include/linux/string.h8
-rw-r--r--tools/include/linux/time64.h12
-rw-r--r--tools/include/uapi/asm-generic/bitsperlong.h15
-rw-r--r--tools/include/uapi/asm-generic/mman-common.h75
-rw-r--r--tools/include/uapi/asm-generic/mman.h22
-rw-r--r--tools/include/uapi/linux/bpf.h473
-rw-r--r--tools/include/uapi/linux/bpf_common.h55
-rw-r--r--tools/include/uapi/linux/hw_breakpoint.h30
-rw-r--r--tools/include/uapi/linux/mman.h13
-rw-r--r--tools/include/uapi/linux/perf_event.h983
-rw-r--r--tools/laptop/dslm/.gitignore1
-rw-r--r--tools/laptop/dslm/Makefile9
-rw-r--r--tools/laptop/dslm/dslm.c166
-rw-r--r--tools/lguest/lguest.c6
-rw-r--r--tools/lib/api/Build5
-rw-r--r--tools/lib/api/Makefile10
-rw-r--r--tools/lib/api/fd/array.c5
-rw-r--r--tools/lib/api/fd/array.h4
-rw-r--r--tools/lib/api/fs/fs.c22
-rw-r--r--tools/lib/api/fs/fs.h1
-rw-r--r--tools/lib/api/fs/tracing_path.c3
-rw-r--r--tools/lib/bitmap.c44
-rw-r--r--tools/lib/bpf/Makefile8
-rw-r--r--tools/lib/bpf/bpf.c13
-rw-r--r--tools/lib/bpf/bpf.h13
-rw-r--r--tools/lib/bpf/libbpf.c156
-rw-r--r--tools/lib/bpf/libbpf.h50
-rw-r--r--tools/lib/str_error_r.c26
-rw-r--r--tools/lib/subcmd/Makefile8
-rw-r--r--tools/lib/subcmd/pager.c16
-rw-r--r--tools/lib/subcmd/pager.h1
-rw-r--r--tools/lib/subcmd/run-command.c5
-rw-r--r--tools/lib/traceevent/.gitignore1
-rw-r--r--tools/lib/traceevent/event-parse.c11
-rw-r--r--tools/lib/traceevent/kbuffer-parse.c1
-rw-r--r--tools/lib/traceevent/parse-filter.c18
-rw-r--r--tools/lib/vsprintf.c24
-rw-r--r--tools/objtool/.gitignore1
-rw-r--r--tools/objtool/Build7
-rw-r--r--tools/objtool/Makefile15
-rw-r--r--tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk11
-rw-r--r--tools/objtool/arch/x86/insn/inat.h17
-rw-r--r--tools/objtool/arch/x86/insn/insn.c18
-rw-r--r--tools/objtool/arch/x86/insn/insn.h12
-rw-r--r--tools/objtool/arch/x86/insn/x86-opcode-map.txt265
-rw-r--r--tools/objtool/builtin-check.c150
-rw-r--r--tools/objtool/elf.c7
-rw-r--r--tools/pcmcia/.gitignore1
-rw-r--r--tools/pcmcia/Makefile9
-rw-r--r--tools/pcmcia/crc32hash.c32
-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/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
-rw-r--r--tools/power/acpi/Makefile.config7
-rw-r--r--tools/power/acpi/common/cmfsize.c13
-rw-r--r--tools/power/acpi/common/getopt.c4
-rw-r--r--tools/power/acpi/os_specific/service_layers/oslibcfs.c217
-rw-r--r--tools/power/acpi/os_specific/service_layers/osunixxf.c3
-rw-r--r--tools/power/acpi/tools/acpidump/Makefile3
-rw-r--r--tools/power/acpi/tools/acpidump/acpidump.h12
-rw-r--r--tools/power/acpi/tools/acpidump/apdump.c75
-rw-r--r--tools/power/acpi/tools/acpidump/apfiles.c56
-rw-r--r--tools/power/acpi/tools/acpidump/apmain.c37
-rw-r--r--tools/power/x86/turbostat/Makefile4
-rw-r--r--tools/power/x86/turbostat/turbostat.82
-rw-r--r--tools/power/x86/turbostat/turbostat.c2
-rw-r--r--tools/scripts/Makefile.arch41
-rw-r--r--tools/spi/Makefile2
-rw-r--r--tools/spi/spidev_test.c3
-rw-r--r--tools/testing/nvdimm/Kbuild11
-rw-r--r--tools/testing/nvdimm/config_check.c2
-rw-r--r--tools/testing/nvdimm/pmem-dax.c54
-rw-r--r--tools/testing/nvdimm/test/Kbuild2
-rw-r--r--tools/testing/nvdimm/test/iomap.c189
-rw-r--r--tools/testing/nvdimm/test/nfit.c352
-rw-r--r--tools/testing/nvdimm/test/nfit_test.h14
-rw-r--r--tools/testing/radix-tree/Makefile5
-rw-r--r--tools/testing/radix-tree/iteration_check.c180
-rw-r--r--tools/testing/radix-tree/linux/cpu.h13
-rw-r--r--tools/testing/radix-tree/linux/gfp.h2
-rw-r--r--tools/testing/radix-tree/main.c1
-rw-r--r--tools/testing/radix-tree/multiorder.c16
-rw-r--r--tools/testing/radix-tree/regression1.c2
-rw-r--r--tools/testing/radix-tree/tag_check.c2
-rw-r--r--tools/testing/radix-tree/test.h1
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/exec/Makefile3
-rw-r--r--tools/testing/selftests/filesystems/.gitignore1
-rw-r--r--tools/testing/selftests/filesystems/Makefile7
-rw-r--r--tools/testing/selftests/filesystems/dnotify_test.c34
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc9
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc9
-rw-r--r--tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc9
-rwxr-xr-xtools/testing/selftests/futex/functional/run.sh2
-rwxr-xr-xtools/testing/selftests/futex/run.sh2
-rw-r--r--tools/testing/selftests/ia64/.gitignore1
-rw-r--r--tools/testing/selftests/ia64/Makefile8
-rw-r--r--tools/testing/selftests/ia64/aliasing-test.c263
-rwxr-xr-x[-rw-r--r--]tools/testing/selftests/lib/printf.sh0
-rw-r--r--tools/testing/selftests/media_tests/.gitignore2
-rw-r--r--tools/testing/selftests/media_tests/Makefile4
-rwxr-xr-xtools/testing/selftests/media_tests/bind_unbind_sample.sh12
-rw-r--r--tools/testing/selftests/media_tests/media_device_open.c81
-rw-r--r--tools/testing/selftests/media_tests/media_device_test.c19
-rwxr-xr-xtools/testing/selftests/media_tests/open_loop_test.sh10
-rw-r--r--tools/testing/selftests/media_tests/regression_test.txt43
-rw-r--r--tools/testing/selftests/media_tests/video_device_test.c100
-rw-r--r--tools/testing/selftests/net/reuseport_bpf.c10
-rw-r--r--tools/testing/selftests/networking/timestamping/.gitignore3
-rw-r--r--tools/testing/selftests/networking/timestamping/Makefile8
-rw-r--r--tools/testing/selftests/networking/timestamping/hwtstamp_config.c134
-rw-r--r--tools/testing/selftests/networking/timestamping/timestamping.c528
-rw-r--r--tools/testing/selftests/networking/timestamping/txtimestamp.c549
-rw-r--r--tools/testing/selftests/nsfs/Makefile12
-rw-r--r--tools/testing/selftests/nsfs/owner.c91
-rw-r--r--tools/testing/selftests/nsfs/pidns.c78
-rwxr-xr-xtools/testing/selftests/ntb/ntb_test.sh422
-rw-r--r--tools/testing/selftests/powerpc/Makefile6
-rw-r--r--tools/testing/selftests/powerpc/alignment/.gitignore5
-rw-r--r--tools/testing/selftests/powerpc/alignment/Makefile10
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c41
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c53
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h26
-rw-r--r--tools/testing/selftests/powerpc/alignment/copy_unaligned.c41
-rw-r--r--tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c43
-rw-r--r--tools/testing/selftests/powerpc/alignment/paste_unaligned.c43
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/.gitignore2
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/Makefile3
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/context_switch.c17
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/futex_bench.c42
-rw-r--r--tools/testing/selftests/powerpc/benchmarks/mmap_bench.c41
-rw-r--r--tools/testing/selftests/powerpc/copyloops/asm/export.h1
-rw-r--r--tools/testing/selftests/powerpc/fpu_asm.h80
-rw-r--r--tools/testing/selftests/powerpc/gpr_asm.h96
-rw-r--r--tools/testing/selftests/powerpc/harness.c9
-rw-r--r--tools/testing/selftests/powerpc/instructions.h68
-rw-r--r--tools/testing/selftests/powerpc/math/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/math/Makefile5
-rw-r--r--tools/testing/selftests/powerpc/math/fpu_asm.S73
-rw-r--r--tools/testing/selftests/powerpc/math/vmx_asm.S85
-rw-r--r--tools/testing/selftests/powerpc/math/vsx_asm.S61
-rw-r--r--tools/testing/selftests/powerpc/math/vsx_preempt.c147
-rw-r--r--tools/testing/selftests/powerpc/mm/.gitignore1
-rw-r--r--tools/testing/selftests/powerpc/mm/Makefile4
-rw-r--r--tools/testing/selftests/powerpc/mm/prot_sao.c42
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/.gitignore2
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/Makefile2
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c143
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h39
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c37
-rw-r--r--tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c2
-rw-r--r--tools/testing/selftests/powerpc/pmu/lib.c6
-rw-r--r--tools/testing/selftests/powerpc/reg.h5
-rw-r--r--tools/testing/selftests/powerpc/signal/.gitignore2
-rw-r--r--tools/testing/selftests/powerpc/signal/Makefile13
-rw-r--r--tools/testing/selftests/powerpc/signal/signal.S50
-rw-r--r--tools/testing/selftests/powerpc/signal/signal.c111
-rw-r--r--tools/testing/selftests/powerpc/signal/signal_tm.c110
-rw-r--r--tools/testing/selftests/powerpc/stringloops/asm/export.h1
-rw-r--r--tools/testing/selftests/powerpc/tm/.gitignore5
-rw-r--r--tools/testing/selftests/powerpc/tm/Makefile13
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-exec.c70
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c92
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c90
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c110
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c125
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-signal.S114
-rw-r--r--tools/testing/selftests/powerpc/tm/tm-syscall.c15
-rw-r--r--tools/testing/selftests/powerpc/tm/tm.h50
-rw-r--r--tools/testing/selftests/powerpc/utils.h14
-rw-r--r--tools/testing/selftests/powerpc/vmx_asm.h96
-rw-r--r--tools/testing/selftests/powerpc/vsx_asm.h71
-rw-r--r--tools/testing/selftests/prctl/.gitignore3
-rw-r--r--tools/testing/selftests/prctl/Makefile15
-rw-r--r--tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c97
-rw-r--r--tools/testing/selftests/prctl/disable-tsc-on-off-stress-test.c96
-rw-r--r--tools/testing/selftests/prctl/disable-tsc-test.c95
-rw-r--r--tools/testing/selftests/ptp/.gitignore1
-rw-r--r--tools/testing/selftests/ptp/Makefile8
-rw-r--r--tools/testing/selftests/ptp/testptp.c523
-rw-r--r--tools/testing/selftests/ptp/testptp.mk33
-rw-r--r--tools/testing/selftests/rcutorture/bin/functions.sh12
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh34
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/kvm.sh2
-rwxr-xr-xtools/testing/selftests/rcutorture/bin/parse-console.sh7
-rw-r--r--tools/testing/selftests/rcutorture/doc/initrd.txt22
-rw-r--r--tools/testing/selftests/seccomp/seccomp_bpf.c176
-rw-r--r--tools/testing/selftests/timers/Makefile3
-rw-r--r--tools/testing/selftests/timers/posix_timers.c4
-rw-r--r--tools/testing/selftests/timers/rtctest.c13
-rw-r--r--tools/testing/selftests/timers/set-tz.c119
-rw-r--r--tools/testing/selftests/vDSO/.gitignore2
-rw-r--r--tools/testing/selftests/vDSO/Makefile20
-rw-r--r--tools/testing/selftests/vDSO/parse_vdso.c269
-rw-r--r--tools/testing/selftests/vDSO/vdso_standalone_test_x86.c128
-rw-r--r--tools/testing/selftests/vDSO/vdso_test.c52
-rw-r--r--tools/testing/selftests/vm/.gitignore1
-rw-r--r--tools/testing/selftests/vm/Makefile4
-rw-r--r--tools/testing/selftests/vm/compaction_test.c10
-rw-r--r--tools/testing/selftests/vm/mlock-random-test.c293
-rw-r--r--tools/testing/selftests/vm/mlock2-tests.c63
-rw-r--r--tools/testing/selftests/vm/mlock2.h62
-rw-r--r--tools/testing/selftests/vm/on-fault-limit.c2
-rw-r--r--tools/testing/selftests/watchdog/.gitignore1
-rw-r--r--tools/testing/selftests/watchdog/Makefile8
-rw-r--r--tools/testing/selftests/watchdog/watchdog-test.c105
-rw-r--r--tools/testing/selftests/x86/Makefile5
-rw-r--r--tools/testing/selftests/x86/mpx-debug.h14
-rw-r--r--tools/testing/selftests/x86/mpx-dig.c498
-rw-r--r--tools/testing/selftests/x86/mpx-hw.h123
-rw-r--r--tools/testing/selftests/x86/mpx-mini-test.c1585
-rw-r--r--tools/testing/selftests/x86/mpx-mm.h9
-rw-r--r--tools/testing/selftests/x86/pkey-helpers.h219
-rw-r--r--tools/testing/selftests/x86/protection_keys.c1410
-rw-r--r--tools/testing/selftests/x86/ptrace_syscall.c4
-rw-r--r--tools/testing/selftests/x86/sigreturn.c16
-rw-r--r--tools/testing/selftests/x86/test_mremap_vdso.c111
-rw-r--r--tools/testing/selftests/zram/README2
-rw-r--r--tools/virtio/linux/dma-mapping.h16
-rw-r--r--tools/virtio/linux/kernel.h14
-rw-r--r--tools/virtio/linux/slab.h4
-rw-r--r--tools/virtio/linux/virtio.h6
-rw-r--r--tools/virtio/linux/virtio_config.h13
-rw-r--r--tools/virtio/ringtest/Makefile7
-rw-r--r--tools/virtio/ringtest/README4
-rw-r--r--tools/virtio/ringtest/noring.c69
-rw-r--r--tools/virtio/ringtest/ptr_ring.c198
-rwxr-xr-xtools/virtio/ringtest/run-on-all.sh4
-rw-r--r--tools/vm/page_owner_sort.c9
-rw-r--r--tools/vm/slabinfo.c5
632 files changed, 38827 insertions, 4504 deletions
diff --git a/tools/Makefile b/tools/Makefile
index f10b64d8c674..daa8fb3e4363 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -85,7 +85,7 @@ tmon: FORCE
85freefall: FORCE 85freefall: FORCE
86 $(call descend,laptop/$@) 86 $(call descend,laptop/$@)
87 87
88all: acpi cgroup cpupower hv firewire lguest \ 88all: acpi cgroup cpupower gpio hv firewire lguest \
89 perf selftests turbostat usb \ 89 perf selftests turbostat usb \
90 virtio vm net x86_energy_perf_policy \ 90 virtio vm net x86_energy_perf_policy \
91 tmon freefall objtool 91 tmon freefall objtool
@@ -96,7 +96,7 @@ acpi_install:
96cpupower_install: 96cpupower_install:
97 $(call descend,power/$(@:_install=),install) 97 $(call descend,power/$(@:_install=),install)
98 98
99cgroup_install firewire_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install: 99cgroup_install firewire_install gpio_install hv_install lguest_install perf_install usb_install virtio_install vm_install net_install objtool_install:
100 $(call descend,$(@:_install=),install) 100 $(call descend,$(@:_install=),install)
101 101
102selftests_install: 102selftests_install:
@@ -114,7 +114,8 @@ freefall_install:
114kvm_stat_install: 114kvm_stat_install:
115 $(call descend,kvm/$(@:_install=),install) 115 $(call descend,kvm/$(@:_install=),install)
116 116
117install: acpi_install cgroup_install cpupower_install hv_install firewire_install lguest_install \ 117install: acpi_install cgroup_install cpupower_install gpio_install \
118 hv_install firewire_install lguest_install \
118 perf_install selftests_install turbostat_install usb_install \ 119 perf_install selftests_install turbostat_install usb_install \
119 virtio_install vm_install net_install x86_energy_perf_policy_install \ 120 virtio_install vm_install net_install x86_energy_perf_policy_install \
120 tmon_install freefall_install objtool_install kvm_stat_install 121 tmon_install freefall_install objtool_install kvm_stat_install
diff --git a/tools/accounting/.gitignore b/tools/accounting/.gitignore
new file mode 100644
index 000000000000..86485203c4ae
--- /dev/null
+++ b/tools/accounting/.gitignore
@@ -0,0 +1 @@
getdelays
diff --git a/tools/accounting/Makefile b/tools/accounting/Makefile
new file mode 100644
index 000000000000..647c94a219bf
--- /dev/null
+++ b/tools/accounting/Makefile
@@ -0,0 +1,9 @@
1CC := $(CROSS_COMPILE)gcc
2CFLAGS := -I../../usr/include
3
4PROGS := getdelays
5
6all: $(PROGS)
7
8clean:
9 rm -fr $(PROGS)
diff --git a/tools/accounting/getdelays.c b/tools/accounting/getdelays.c
new file mode 100644
index 000000000000..b5ca536e56a8
--- /dev/null
+++ b/tools/accounting/getdelays.c
@@ -0,0 +1,550 @@
1/* getdelays.c
2 *
3 * Utility to get per-pid and per-tgid delay accounting statistics
4 * Also illustrates usage of the taskstats interface
5 *
6 * Copyright (C) Shailabh Nagar, IBM Corp. 2005
7 * Copyright (C) Balbir Singh, IBM Corp. 2006
8 * Copyright (c) Jay Lan, SGI. 2006
9 *
10 * Compile with
11 * gcc -I/usr/src/linux/include getdelays.c -o getdelays
12 */
13
14#include <stdio.h>
15#include <stdlib.h>
16#include <errno.h>
17#include <unistd.h>
18#include <poll.h>
19#include <string.h>
20#include <fcntl.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <sys/socket.h>
24#include <sys/wait.h>
25#include <signal.h>
26
27#include <linux/genetlink.h>
28#include <linux/taskstats.h>
29#include <linux/cgroupstats.h>
30
31/*
32 * Generic macros for dealing with netlink sockets. Might be duplicated
33 * elsewhere. It is recommended that commercial grade applications use
34 * libnl or libnetlink and use the interfaces provided by the library
35 */
36#define GENLMSG_DATA(glh) ((void *)(NLMSG_DATA(glh) + GENL_HDRLEN))
37#define GENLMSG_PAYLOAD(glh) (NLMSG_PAYLOAD(glh, 0) - GENL_HDRLEN)
38#define NLA_DATA(na) ((void *)((char*)(na) + NLA_HDRLEN))
39#define NLA_PAYLOAD(len) (len - NLA_HDRLEN)
40
41#define err(code, fmt, arg...) \
42 do { \
43 fprintf(stderr, fmt, ##arg); \
44 exit(code); \
45 } while (0)
46
47int done;
48int rcvbufsz;
49char name[100];
50int dbg;
51int print_delays;
52int print_io_accounting;
53int print_task_context_switch_counts;
54
55#define PRINTF(fmt, arg...) { \
56 if (dbg) { \
57 printf(fmt, ##arg); \
58 } \
59 }
60
61/* Maximum size of response requested or message sent */
62#define MAX_MSG_SIZE 1024
63/* Maximum number of cpus expected to be specified in a cpumask */
64#define MAX_CPUS 32
65
66struct msgtemplate {
67 struct nlmsghdr n;
68 struct genlmsghdr g;
69 char buf[MAX_MSG_SIZE];
70};
71
72char cpumask[100+6*MAX_CPUS];
73
74static void usage(void)
75{
76 fprintf(stderr, "getdelays [-dilv] [-w logfile] [-r bufsize] "
77 "[-m cpumask] [-t tgid] [-p pid]\n");
78 fprintf(stderr, " -d: print delayacct stats\n");
79 fprintf(stderr, " -i: print IO accounting (works only with -p)\n");
80 fprintf(stderr, " -l: listen forever\n");
81 fprintf(stderr, " -v: debug on\n");
82 fprintf(stderr, " -C: container path\n");
83}
84
85/*
86 * Create a raw netlink socket and bind
87 */
88static int create_nl_socket(int protocol)
89{
90 int fd;
91 struct sockaddr_nl local;
92
93 fd = socket(AF_NETLINK, SOCK_RAW, protocol);
94 if (fd < 0)
95 return -1;
96
97 if (rcvbufsz)
98 if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
99 &rcvbufsz, sizeof(rcvbufsz)) < 0) {
100 fprintf(stderr, "Unable to set socket rcv buf size to %d\n",
101 rcvbufsz);
102 goto error;
103 }
104
105 memset(&local, 0, sizeof(local));
106 local.nl_family = AF_NETLINK;
107
108 if (bind(fd, (struct sockaddr *) &local, sizeof(local)) < 0)
109 goto error;
110
111 return fd;
112error:
113 close(fd);
114 return -1;
115}
116
117
118static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid,
119 __u8 genl_cmd, __u16 nla_type,
120 void *nla_data, int nla_len)
121{
122 struct nlattr *na;
123 struct sockaddr_nl nladdr;
124 int r, buflen;
125 char *buf;
126
127 struct msgtemplate msg;
128
129 msg.n.nlmsg_len = NLMSG_LENGTH(GENL_HDRLEN);
130 msg.n.nlmsg_type = nlmsg_type;
131 msg.n.nlmsg_flags = NLM_F_REQUEST;
132 msg.n.nlmsg_seq = 0;
133 msg.n.nlmsg_pid = nlmsg_pid;
134 msg.g.cmd = genl_cmd;
135 msg.g.version = 0x1;
136 na = (struct nlattr *) GENLMSG_DATA(&msg);
137 na->nla_type = nla_type;
138 na->nla_len = nla_len + 1 + NLA_HDRLEN;
139 memcpy(NLA_DATA(na), nla_data, nla_len);
140 msg.n.nlmsg_len += NLMSG_ALIGN(na->nla_len);
141
142 buf = (char *) &msg;
143 buflen = msg.n.nlmsg_len ;
144 memset(&nladdr, 0, sizeof(nladdr));
145 nladdr.nl_family = AF_NETLINK;
146 while ((r = sendto(sd, buf, buflen, 0, (struct sockaddr *) &nladdr,
147 sizeof(nladdr))) < buflen) {
148 if (r > 0) {
149 buf += r;
150 buflen -= r;
151 } else if (errno != EAGAIN)
152 return -1;
153 }
154 return 0;
155}
156
157
158/*
159 * Probe the controller in genetlink to find the family id
160 * for the TASKSTATS family
161 */
162static int get_family_id(int sd)
163{
164 struct {
165 struct nlmsghdr n;
166 struct genlmsghdr g;
167 char buf[256];
168 } ans;
169
170 int id = 0, rc;
171 struct nlattr *na;
172 int rep_len;
173
174 strcpy(name, TASKSTATS_GENL_NAME);
175 rc = send_cmd(sd, GENL_ID_CTRL, getpid(), CTRL_CMD_GETFAMILY,
176 CTRL_ATTR_FAMILY_NAME, (void *)name,
177 strlen(TASKSTATS_GENL_NAME)+1);
178 if (rc < 0)
179 return 0; /* sendto() failure? */
180
181 rep_len = recv(sd, &ans, sizeof(ans), 0);
182 if (ans.n.nlmsg_type == NLMSG_ERROR ||
183 (rep_len < 0) || !NLMSG_OK((&ans.n), rep_len))
184 return 0;
185
186 na = (struct nlattr *) GENLMSG_DATA(&ans);
187 na = (struct nlattr *) ((char *) na + NLA_ALIGN(na->nla_len));
188 if (na->nla_type == CTRL_ATTR_FAMILY_ID) {
189 id = *(__u16 *) NLA_DATA(na);
190 }
191 return id;
192}
193
194#define average_ms(t, c) (t / 1000000ULL / (c ? c : 1))
195
196static void print_delayacct(struct taskstats *t)
197{
198 printf("\n\nCPU %15s%15s%15s%15s%15s\n"
199 " %15llu%15llu%15llu%15llu%15.3fms\n"
200 "IO %15s%15s%15s\n"
201 " %15llu%15llu%15llums\n"
202 "SWAP %15s%15s%15s\n"
203 " %15llu%15llu%15llums\n"
204 "RECLAIM %12s%15s%15s\n"
205 " %15llu%15llu%15llums\n",
206 "count", "real total", "virtual total",
207 "delay total", "delay average",
208 (unsigned long long)t->cpu_count,
209 (unsigned long long)t->cpu_run_real_total,
210 (unsigned long long)t->cpu_run_virtual_total,
211 (unsigned long long)t->cpu_delay_total,
212 average_ms((double)t->cpu_delay_total, t->cpu_count),
213 "count", "delay total", "delay average",
214 (unsigned long long)t->blkio_count,
215 (unsigned long long)t->blkio_delay_total,
216 average_ms(t->blkio_delay_total, t->blkio_count),
217 "count", "delay total", "delay average",
218 (unsigned long long)t->swapin_count,
219 (unsigned long long)t->swapin_delay_total,
220 average_ms(t->swapin_delay_total, t->swapin_count),
221 "count", "delay total", "delay average",
222 (unsigned long long)t->freepages_count,
223 (unsigned long long)t->freepages_delay_total,
224 average_ms(t->freepages_delay_total, t->freepages_count));
225}
226
227static void task_context_switch_counts(struct taskstats *t)
228{
229 printf("\n\nTask %15s%15s\n"
230 " %15llu%15llu\n",
231 "voluntary", "nonvoluntary",
232 (unsigned long long)t->nvcsw, (unsigned long long)t->nivcsw);
233}
234
235static void print_cgroupstats(struct cgroupstats *c)
236{
237 printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, "
238 "uninterruptible %llu\n", (unsigned long long)c->nr_sleeping,
239 (unsigned long long)c->nr_io_wait,
240 (unsigned long long)c->nr_running,
241 (unsigned long long)c->nr_stopped,
242 (unsigned long long)c->nr_uninterruptible);
243}
244
245
246static void print_ioacct(struct taskstats *t)
247{
248 printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n",
249 t->ac_comm,
250 (unsigned long long)t->read_bytes,
251 (unsigned long long)t->write_bytes,
252 (unsigned long long)t->cancelled_write_bytes);
253}
254
255int main(int argc, char *argv[])
256{
257 int c, rc, rep_len, aggr_len, len2;
258 int cmd_type = TASKSTATS_CMD_ATTR_UNSPEC;
259 __u16 id;
260 __u32 mypid;
261
262 struct nlattr *na;
263 int nl_sd = -1;
264 int len = 0;
265 pid_t tid = 0;
266 pid_t rtid = 0;
267
268 int fd = 0;
269 int count = 0;
270 int write_file = 0;
271 int maskset = 0;
272 char *logfile = NULL;
273 int loop = 0;
274 int containerset = 0;
275 char *containerpath = NULL;
276 int cfd = 0;
277 int forking = 0;
278 sigset_t sigset;
279
280 struct msgtemplate msg;
281
282 while (!forking) {
283 c = getopt(argc, argv, "qdiw:r:m:t:p:vlC:c:");
284 if (c < 0)
285 break;
286
287 switch (c) {
288 case 'd':
289 printf("print delayacct stats ON\n");
290 print_delays = 1;
291 break;
292 case 'i':
293 printf("printing IO accounting\n");
294 print_io_accounting = 1;
295 break;
296 case 'q':
297 printf("printing task/process context switch rates\n");
298 print_task_context_switch_counts = 1;
299 break;
300 case 'C':
301 containerset = 1;
302 containerpath = optarg;
303 break;
304 case 'w':
305 logfile = strdup(optarg);
306 printf("write to file %s\n", logfile);
307 write_file = 1;
308 break;
309 case 'r':
310 rcvbufsz = atoi(optarg);
311 printf("receive buf size %d\n", rcvbufsz);
312 if (rcvbufsz < 0)
313 err(1, "Invalid rcv buf size\n");
314 break;
315 case 'm':
316 strncpy(cpumask, optarg, sizeof(cpumask));
317 cpumask[sizeof(cpumask) - 1] = '\0';
318 maskset = 1;
319 printf("cpumask %s maskset %d\n", cpumask, maskset);
320 break;
321 case 't':
322 tid = atoi(optarg);
323 if (!tid)
324 err(1, "Invalid tgid\n");
325 cmd_type = TASKSTATS_CMD_ATTR_TGID;
326 break;
327 case 'p':
328 tid = atoi(optarg);
329 if (!tid)
330 err(1, "Invalid pid\n");
331 cmd_type = TASKSTATS_CMD_ATTR_PID;
332 break;
333 case 'c':
334
335 /* Block SIGCHLD for sigwait() later */
336 if (sigemptyset(&sigset) == -1)
337 err(1, "Failed to empty sigset");
338 if (sigaddset(&sigset, SIGCHLD))
339 err(1, "Failed to set sigchld in sigset");
340 sigprocmask(SIG_BLOCK, &sigset, NULL);
341
342 /* fork/exec a child */
343 tid = fork();
344 if (tid < 0)
345 err(1, "Fork failed\n");
346 if (tid == 0)
347 if (execvp(argv[optind - 1],
348 &argv[optind - 1]) < 0)
349 exit(-1);
350
351 /* Set the command type and avoid further processing */
352 cmd_type = TASKSTATS_CMD_ATTR_PID;
353 forking = 1;
354 break;
355 case 'v':
356 printf("debug on\n");
357 dbg = 1;
358 break;
359 case 'l':
360 printf("listen forever\n");
361 loop = 1;
362 break;
363 default:
364 usage();
365 exit(-1);
366 }
367 }
368
369 if (write_file) {
370 fd = open(logfile, O_WRONLY | O_CREAT | O_TRUNC,
371 S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
372 if (fd == -1) {
373 perror("Cannot open output file\n");
374 exit(1);
375 }
376 }
377
378 nl_sd = create_nl_socket(NETLINK_GENERIC);
379 if (nl_sd < 0)
380 err(1, "error creating Netlink socket\n");
381
382
383 mypid = getpid();
384 id = get_family_id(nl_sd);
385 if (!id) {
386 fprintf(stderr, "Error getting family id, errno %d\n", errno);
387 goto err;
388 }
389 PRINTF("family id %d\n", id);
390
391 if (maskset) {
392 rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
393 TASKSTATS_CMD_ATTR_REGISTER_CPUMASK,
394 &cpumask, strlen(cpumask) + 1);
395 PRINTF("Sent register cpumask, retval %d\n", rc);
396 if (rc < 0) {
397 fprintf(stderr, "error sending register cpumask\n");
398 goto err;
399 }
400 }
401
402 if (tid && containerset) {
403 fprintf(stderr, "Select either -t or -C, not both\n");
404 goto err;
405 }
406
407 /*
408 * If we forked a child, wait for it to exit. Cannot use waitpid()
409 * as all the delicious data would be reaped as part of the wait
410 */
411 if (tid && forking) {
412 int sig_received;
413 sigwait(&sigset, &sig_received);
414 }
415
416 if (tid) {
417 rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
418 cmd_type, &tid, sizeof(__u32));
419 PRINTF("Sent pid/tgid, retval %d\n", rc);
420 if (rc < 0) {
421 fprintf(stderr, "error sending tid/tgid cmd\n");
422 goto done;
423 }
424 }
425
426 if (containerset) {
427 cfd = open(containerpath, O_RDONLY);
428 if (cfd < 0) {
429 perror("error opening container file");
430 goto err;
431 }
432 rc = send_cmd(nl_sd, id, mypid, CGROUPSTATS_CMD_GET,
433 CGROUPSTATS_CMD_ATTR_FD, &cfd, sizeof(__u32));
434 if (rc < 0) {
435 perror("error sending cgroupstats command");
436 goto err;
437 }
438 }
439 if (!maskset && !tid && !containerset) {
440 usage();
441 goto err;
442 }
443
444 do {
445 rep_len = recv(nl_sd, &msg, sizeof(msg), 0);
446 PRINTF("received %d bytes\n", rep_len);
447
448 if (rep_len < 0) {
449 fprintf(stderr, "nonfatal reply error: errno %d\n",
450 errno);
451 continue;
452 }
453 if (msg.n.nlmsg_type == NLMSG_ERROR ||
454 !NLMSG_OK((&msg.n), rep_len)) {
455 struct nlmsgerr *err = NLMSG_DATA(&msg);
456 fprintf(stderr, "fatal reply error, errno %d\n",
457 err->error);
458 goto done;
459 }
460
461 PRINTF("nlmsghdr size=%zu, nlmsg_len=%d, rep_len=%d\n",
462 sizeof(struct nlmsghdr), msg.n.nlmsg_len, rep_len);
463
464
465 rep_len = GENLMSG_PAYLOAD(&msg.n);
466
467 na = (struct nlattr *) GENLMSG_DATA(&msg);
468 len = 0;
469 while (len < rep_len) {
470 len += NLA_ALIGN(na->nla_len);
471 switch (na->nla_type) {
472 case TASKSTATS_TYPE_AGGR_TGID:
473 /* Fall through */
474 case TASKSTATS_TYPE_AGGR_PID:
475 aggr_len = NLA_PAYLOAD(na->nla_len);
476 len2 = 0;
477 /* For nested attributes, na follows */
478 na = (struct nlattr *) NLA_DATA(na);
479 done = 0;
480 while (len2 < aggr_len) {
481 switch (na->nla_type) {
482 case TASKSTATS_TYPE_PID:
483 rtid = *(int *) NLA_DATA(na);
484 if (print_delays)
485 printf("PID\t%d\n", rtid);
486 break;
487 case TASKSTATS_TYPE_TGID:
488 rtid = *(int *) NLA_DATA(na);
489 if (print_delays)
490 printf("TGID\t%d\n", rtid);
491 break;
492 case TASKSTATS_TYPE_STATS:
493 count++;
494 if (print_delays)
495 print_delayacct((struct taskstats *) NLA_DATA(na));
496 if (print_io_accounting)
497 print_ioacct((struct taskstats *) NLA_DATA(na));
498 if (print_task_context_switch_counts)
499 task_context_switch_counts((struct taskstats *) NLA_DATA(na));
500 if (fd) {
501 if (write(fd, NLA_DATA(na), na->nla_len) < 0) {
502 err(1,"write error\n");
503 }
504 }
505 if (!loop)
506 goto done;
507 break;
508 case TASKSTATS_TYPE_NULL:
509 break;
510 default:
511 fprintf(stderr, "Unknown nested"
512 " nla_type %d\n",
513 na->nla_type);
514 break;
515 }
516 len2 += NLA_ALIGN(na->nla_len);
517 na = (struct nlattr *)((char *)na +
518 NLA_ALIGN(na->nla_len));
519 }
520 break;
521
522 case CGROUPSTATS_TYPE_CGROUP_STATS:
523 print_cgroupstats(NLA_DATA(na));
524 break;
525 default:
526 fprintf(stderr, "Unknown nla_type %d\n",
527 na->nla_type);
528 case TASKSTATS_TYPE_NULL:
529 break;
530 }
531 na = (struct nlattr *) (GENLMSG_DATA(&msg) + len);
532 }
533 } while (loop);
534done:
535 if (maskset) {
536 rc = send_cmd(nl_sd, id, mypid, TASKSTATS_CMD_GET,
537 TASKSTATS_CMD_ATTR_DEREGISTER_CPUMASK,
538 &cpumask, strlen(cpumask) + 1);
539 printf("Sent deregister mask, retval %d\n", rc);
540 if (rc < 0)
541 err(rc, "error sending deregister cpumask\n");
542 }
543err:
544 close(nl_sd);
545 if (fd)
546 close(fd);
547 if (cfd)
548 close(cfd);
549 return 0;
550}
diff --git a/tools/arch/alpha/include/uapi/asm/bitsperlong.h b/tools/arch/alpha/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..ad57f7868203
--- /dev/null
+++ b/tools/arch/alpha/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,8 @@
1#ifndef __ASM_ALPHA_BITSPERLONG_H
2#define __ASM_ALPHA_BITSPERLONG_H
3
4#define __BITS_PER_LONG 64
5
6#include <asm-generic/bitsperlong.h>
7
8#endif /* __ASM_ALPHA_BITSPERLONG_H */
diff --git a/tools/arch/alpha/include/uapi/asm/mman.h b/tools/arch/alpha/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..e38b64c82b97
--- /dev/null
+++ b/tools/arch/alpha/include/uapi/asm/mman.h
@@ -0,0 +1,47 @@
1#ifndef TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ALPHA_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 16
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 6
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 14
10#define MADV_MERGEABLE 12
11#define MADV_NOHUGEPAGE 15
12#define MADV_NORMAL 0
13#define MADV_RANDOM 1
14#define MADV_REMOVE 9
15#define MADV_SEQUENTIAL 2
16#define MADV_UNMERGEABLE 13
17#define MADV_WILLNEED 3
18#define MAP_ANONYMOUS 0x10
19#define MAP_DENYWRITE 0x02000
20#define MAP_EXECUTABLE 0x04000
21#define MAP_FILE 0
22#define MAP_FIXED 0x100
23#define MAP_GROWSDOWN 0x01000
24#define MAP_HUGETLB 0x100000
25#define MAP_LOCKED 0x08000
26#define MAP_NONBLOCK 0x40000
27#define MAP_NORESERVE 0x10000
28#define MAP_POPULATE 0x20000
29#define MAP_PRIVATE 0x02
30#define MAP_SHARED 0x01
31#define MAP_STACK 0x80000
32#define PROT_EXEC 0x4
33#define PROT_GROWSDOWN 0x01000000
34#define PROT_GROWSUP 0x02000000
35#define PROT_NONE 0x0
36#define PROT_READ 0x1
37#define PROT_SEM 0x8
38#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on alpha, fix it for perf */
40#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on alpha, fix it for perf */
42#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on alpha, fix it for perf */
44#define MAP_32BIT 0
45/* MAP_UNINITIALIZED is undefined on alpha, fix it for perf */
46#define MAP_UNINITIALIZED 0
47#endif
diff --git a/tools/arch/arc/include/uapi/asm/mman.h b/tools/arch/arc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..aa3acd2aa9af
--- /dev/null
+++ b/tools/arch/arc/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARC_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on arc, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/arm/include/uapi/asm/kvm.h b/tools/arch/arm/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..a2b3eb313a25
--- /dev/null
+++ b/tools/arch/arm/include/uapi/asm/kvm.h
@@ -0,0 +1,224 @@
1/*
2 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
3 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License, version 2, as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17 */
18
19#ifndef __ARM_KVM_H__
20#define __ARM_KVM_H__
21
22#include <linux/types.h>
23#include <linux/psci.h>
24#include <asm/ptrace.h>
25
26#define __KVM_HAVE_GUEST_DEBUG
27#define __KVM_HAVE_IRQ_LINE
28#define __KVM_HAVE_READONLY_MEM
29
30#define KVM_REG_SIZE(id) \
31 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
32
33/* Valid for svc_regs, abt_regs, und_regs, irq_regs in struct kvm_regs */
34#define KVM_ARM_SVC_sp svc_regs[0]
35#define KVM_ARM_SVC_lr svc_regs[1]
36#define KVM_ARM_SVC_spsr svc_regs[2]
37#define KVM_ARM_ABT_sp abt_regs[0]
38#define KVM_ARM_ABT_lr abt_regs[1]
39#define KVM_ARM_ABT_spsr abt_regs[2]
40#define KVM_ARM_UND_sp und_regs[0]
41#define KVM_ARM_UND_lr und_regs[1]
42#define KVM_ARM_UND_spsr und_regs[2]
43#define KVM_ARM_IRQ_sp irq_regs[0]
44#define KVM_ARM_IRQ_lr irq_regs[1]
45#define KVM_ARM_IRQ_spsr irq_regs[2]
46
47/* Valid only for fiq_regs in struct kvm_regs */
48#define KVM_ARM_FIQ_r8 fiq_regs[0]
49#define KVM_ARM_FIQ_r9 fiq_regs[1]
50#define KVM_ARM_FIQ_r10 fiq_regs[2]
51#define KVM_ARM_FIQ_fp fiq_regs[3]
52#define KVM_ARM_FIQ_ip fiq_regs[4]
53#define KVM_ARM_FIQ_sp fiq_regs[5]
54#define KVM_ARM_FIQ_lr fiq_regs[6]
55#define KVM_ARM_FIQ_spsr fiq_regs[7]
56
57struct kvm_regs {
58 struct pt_regs usr_regs; /* R0_usr - R14_usr, PC, CPSR */
59 unsigned long svc_regs[3]; /* SP_svc, LR_svc, SPSR_svc */
60 unsigned long abt_regs[3]; /* SP_abt, LR_abt, SPSR_abt */
61 unsigned long und_regs[3]; /* SP_und, LR_und, SPSR_und */
62 unsigned long irq_regs[3]; /* SP_irq, LR_irq, SPSR_irq */
63 unsigned long fiq_regs[8]; /* R8_fiq - R14_fiq, SPSR_fiq */
64};
65
66/* Supported Processor Types */
67#define KVM_ARM_TARGET_CORTEX_A15 0
68#define KVM_ARM_TARGET_CORTEX_A7 1
69#define KVM_ARM_NUM_TARGETS 2
70
71/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
72#define KVM_ARM_DEVICE_TYPE_SHIFT 0
73#define KVM_ARM_DEVICE_TYPE_MASK (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
74#define KVM_ARM_DEVICE_ID_SHIFT 16
75#define KVM_ARM_DEVICE_ID_MASK (0xffff << KVM_ARM_DEVICE_ID_SHIFT)
76
77/* Supported device IDs */
78#define KVM_ARM_DEVICE_VGIC_V2 0
79
80/* Supported VGIC address types */
81#define KVM_VGIC_V2_ADDR_TYPE_DIST 0
82#define KVM_VGIC_V2_ADDR_TYPE_CPU 1
83
84#define KVM_VGIC_V2_DIST_SIZE 0x1000
85#define KVM_VGIC_V2_CPU_SIZE 0x2000
86
87#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
88#define KVM_ARM_VCPU_PSCI_0_2 1 /* CPU uses PSCI v0.2 */
89
90struct kvm_vcpu_init {
91 __u32 target;
92 __u32 features[7];
93};
94
95struct kvm_sregs {
96};
97
98struct kvm_fpu {
99};
100
101struct kvm_guest_debug_arch {
102};
103
104struct kvm_debug_exit_arch {
105};
106
107struct kvm_sync_regs {
108};
109
110struct kvm_arch_memory_slot {
111};
112
113/* If you need to interpret the index values, here is the key: */
114#define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
115#define KVM_REG_ARM_COPROC_SHIFT 16
116#define KVM_REG_ARM_32_OPC2_MASK 0x0000000000000007
117#define KVM_REG_ARM_32_OPC2_SHIFT 0
118#define KVM_REG_ARM_OPC1_MASK 0x0000000000000078
119#define KVM_REG_ARM_OPC1_SHIFT 3
120#define KVM_REG_ARM_CRM_MASK 0x0000000000000780
121#define KVM_REG_ARM_CRM_SHIFT 7
122#define KVM_REG_ARM_32_CRN_MASK 0x0000000000007800
123#define KVM_REG_ARM_32_CRN_SHIFT 11
124
125#define ARM_CP15_REG_SHIFT_MASK(x,n) \
126 (((x) << KVM_REG_ARM_ ## n ## _SHIFT) & KVM_REG_ARM_ ## n ## _MASK)
127
128#define __ARM_CP15_REG(op1,crn,crm,op2) \
129 (KVM_REG_ARM | (15 << KVM_REG_ARM_COPROC_SHIFT) | \
130 ARM_CP15_REG_SHIFT_MASK(op1, OPC1) | \
131 ARM_CP15_REG_SHIFT_MASK(crn, 32_CRN) | \
132 ARM_CP15_REG_SHIFT_MASK(crm, CRM) | \
133 ARM_CP15_REG_SHIFT_MASK(op2, 32_OPC2))
134
135#define ARM_CP15_REG32(...) (__ARM_CP15_REG(__VA_ARGS__) | KVM_REG_SIZE_U32)
136
137#define __ARM_CP15_REG64(op1,crm) \
138 (__ARM_CP15_REG(op1, 0, crm, 0) | KVM_REG_SIZE_U64)
139#define ARM_CP15_REG64(...) __ARM_CP15_REG64(__VA_ARGS__)
140
141#define KVM_REG_ARM_TIMER_CTL ARM_CP15_REG32(0, 14, 3, 1)
142#define KVM_REG_ARM_TIMER_CNT ARM_CP15_REG64(1, 14)
143#define KVM_REG_ARM_TIMER_CVAL ARM_CP15_REG64(3, 14)
144
145/* Normal registers are mapped as coprocessor 16. */
146#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
147#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / 4)
148
149/* Some registers need more space to represent values. */
150#define KVM_REG_ARM_DEMUX (0x0011 << KVM_REG_ARM_COPROC_SHIFT)
151#define KVM_REG_ARM_DEMUX_ID_MASK 0x000000000000FF00
152#define KVM_REG_ARM_DEMUX_ID_SHIFT 8
153#define KVM_REG_ARM_DEMUX_ID_CCSIDR (0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
154#define KVM_REG_ARM_DEMUX_VAL_MASK 0x00000000000000FF
155#define KVM_REG_ARM_DEMUX_VAL_SHIFT 0
156
157/* VFP registers: we could overload CP10 like ARM does, but that's ugly. */
158#define KVM_REG_ARM_VFP (0x0012 << KVM_REG_ARM_COPROC_SHIFT)
159#define KVM_REG_ARM_VFP_MASK 0x000000000000FFFF
160#define KVM_REG_ARM_VFP_BASE_REG 0x0
161#define KVM_REG_ARM_VFP_FPSID 0x1000
162#define KVM_REG_ARM_VFP_FPSCR 0x1001
163#define KVM_REG_ARM_VFP_MVFR1 0x1006
164#define KVM_REG_ARM_VFP_MVFR0 0x1007
165#define KVM_REG_ARM_VFP_FPEXC 0x1008
166#define KVM_REG_ARM_VFP_FPINST 0x1009
167#define KVM_REG_ARM_VFP_FPINST2 0x100A
168
169/* Device Control API: ARM VGIC */
170#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
171#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
172#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
173#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
174#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
175#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
176#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
177#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
178#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
179#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
180
181/* KVM_IRQ_LINE irq field index values */
182#define KVM_ARM_IRQ_TYPE_SHIFT 24
183#define KVM_ARM_IRQ_TYPE_MASK 0xff
184#define KVM_ARM_IRQ_VCPU_SHIFT 16
185#define KVM_ARM_IRQ_VCPU_MASK 0xff
186#define KVM_ARM_IRQ_NUM_SHIFT 0
187#define KVM_ARM_IRQ_NUM_MASK 0xffff
188
189/* irq_type field */
190#define KVM_ARM_IRQ_TYPE_CPU 0
191#define KVM_ARM_IRQ_TYPE_SPI 1
192#define KVM_ARM_IRQ_TYPE_PPI 2
193
194/* out-of-kernel GIC cpu interrupt injection irq_number field */
195#define KVM_ARM_IRQ_CPU_IRQ 0
196#define KVM_ARM_IRQ_CPU_FIQ 1
197
198/*
199 * This used to hold the highest supported SPI, but it is now obsolete
200 * and only here to provide source code level compatibility with older
201 * userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS.
202 */
203#ifndef __KERNEL__
204#define KVM_ARM_IRQ_GIC_MAX 127
205#endif
206
207/* One single KVM irqchip, ie. the VGIC */
208#define KVM_NR_IRQCHIPS 1
209
210/* PSCI interface */
211#define KVM_PSCI_FN_BASE 0x95c1ba5e
212#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
213
214#define KVM_PSCI_FN_CPU_SUSPEND KVM_PSCI_FN(0)
215#define KVM_PSCI_FN_CPU_OFF KVM_PSCI_FN(1)
216#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
217#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
218
219#define KVM_PSCI_RET_SUCCESS PSCI_RET_SUCCESS
220#define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
221#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
222#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
223
224#endif /* __ARM_KVM_H__ */
diff --git a/tools/arch/arm/include/uapi/asm/mman.h b/tools/arch/arm/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..478f699f56fd
--- /dev/null
+++ b/tools/arch/arm/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARM_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on arm, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/arm/include/uapi/asm/perf_regs.h b/tools/arch/arm/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..ce59448458b2
--- /dev/null
+++ b/tools/arch/arm/include/uapi/asm/perf_regs.h
@@ -0,0 +1,23 @@
1#ifndef _ASM_ARM_PERF_REGS_H
2#define _ASM_ARM_PERF_REGS_H
3
4enum perf_event_arm_regs {
5 PERF_REG_ARM_R0,
6 PERF_REG_ARM_R1,
7 PERF_REG_ARM_R2,
8 PERF_REG_ARM_R3,
9 PERF_REG_ARM_R4,
10 PERF_REG_ARM_R5,
11 PERF_REG_ARM_R6,
12 PERF_REG_ARM_R7,
13 PERF_REG_ARM_R8,
14 PERF_REG_ARM_R9,
15 PERF_REG_ARM_R10,
16 PERF_REG_ARM_FP,
17 PERF_REG_ARM_IP,
18 PERF_REG_ARM_SP,
19 PERF_REG_ARM_LR,
20 PERF_REG_ARM_PC,
21 PERF_REG_ARM_MAX,
22};
23#endif /* _ASM_ARM_PERF_REGS_H */
diff --git a/tools/arch/arm64/include/uapi/asm/bitsperlong.h b/tools/arch/arm64/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..fce9c2924fa3
--- /dev/null
+++ b/tools/arch/arm64/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,23 @@
1/*
2 * Copyright (C) 2012 ARM Ltd.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16#ifndef __ASM_BITSPERLONG_H
17#define __ASM_BITSPERLONG_H
18
19#define __BITS_PER_LONG 64
20
21#include <asm-generic/bitsperlong.h>
22
23#endif /* __ASM_BITSPERLONG_H */
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..3051f86a9b5f
--- /dev/null
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -0,0 +1,260 @@
1/*
2 * Copyright (C) 2012,2013 - ARM Ltd
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 * Derived from arch/arm/include/uapi/asm/kvm.h:
6 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
7 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22#ifndef __ARM_KVM_H__
23#define __ARM_KVM_H__
24
25#define KVM_SPSR_EL1 0
26#define KVM_SPSR_SVC KVM_SPSR_EL1
27#define KVM_SPSR_ABT 1
28#define KVM_SPSR_UND 2
29#define KVM_SPSR_IRQ 3
30#define KVM_SPSR_FIQ 4
31#define KVM_NR_SPSR 5
32
33#ifndef __ASSEMBLY__
34#include <linux/psci.h>
35#include <linux/types.h>
36#include <asm/ptrace.h>
37
38#define __KVM_HAVE_GUEST_DEBUG
39#define __KVM_HAVE_IRQ_LINE
40#define __KVM_HAVE_READONLY_MEM
41
42#define KVM_REG_SIZE(id) \
43 (1U << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
44
45struct kvm_regs {
46 struct user_pt_regs regs; /* sp = sp_el0 */
47
48 __u64 sp_el1;
49 __u64 elr_el1;
50
51 __u64 spsr[KVM_NR_SPSR];
52
53 struct user_fpsimd_state fp_regs;
54};
55
56/*
57 * Supported CPU Targets - Adding a new target type is not recommended,
58 * unless there are some special registers not supported by the
59 * genericv8 syreg table.
60 */
61#define KVM_ARM_TARGET_AEM_V8 0
62#define KVM_ARM_TARGET_FOUNDATION_V8 1
63#define KVM_ARM_TARGET_CORTEX_A57 2
64#define KVM_ARM_TARGET_XGENE_POTENZA 3
65#define KVM_ARM_TARGET_CORTEX_A53 4
66/* Generic ARM v8 target */
67#define KVM_ARM_TARGET_GENERIC_V8 5
68
69#define KVM_ARM_NUM_TARGETS 6
70
71/* KVM_ARM_SET_DEVICE_ADDR ioctl id encoding */
72#define KVM_ARM_DEVICE_TYPE_SHIFT 0
73#define KVM_ARM_DEVICE_TYPE_MASK (0xffff << KVM_ARM_DEVICE_TYPE_SHIFT)
74#define KVM_ARM_DEVICE_ID_SHIFT 16
75#define KVM_ARM_DEVICE_ID_MASK (0xffff << KVM_ARM_DEVICE_ID_SHIFT)
76
77/* Supported device IDs */
78#define KVM_ARM_DEVICE_VGIC_V2 0
79
80/* Supported VGIC address types */
81#define KVM_VGIC_V2_ADDR_TYPE_DIST 0
82#define KVM_VGIC_V2_ADDR_TYPE_CPU 1
83
84#define KVM_VGIC_V2_DIST_SIZE 0x1000
85#define KVM_VGIC_V2_CPU_SIZE 0x2000
86
87/* Supported VGICv3 address types */
88#define KVM_VGIC_V3_ADDR_TYPE_DIST 2
89#define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
90#define KVM_VGIC_ITS_ADDR_TYPE 4
91
92#define KVM_VGIC_V3_DIST_SIZE SZ_64K
93#define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
94#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
95
96#define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
97#define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
98#define KVM_ARM_VCPU_PSCI_0_2 2 /* CPU uses PSCI v0.2 */
99#define KVM_ARM_VCPU_PMU_V3 3 /* Support guest PMUv3 */
100
101struct kvm_vcpu_init {
102 __u32 target;
103 __u32 features[7];
104};
105
106struct kvm_sregs {
107};
108
109struct kvm_fpu {
110};
111
112/*
113 * See v8 ARM ARM D7.3: Debug Registers
114 *
115 * The architectural limit is 16 debug registers of each type although
116 * in practice there are usually less (see ID_AA64DFR0_EL1).
117 *
118 * Although the control registers are architecturally defined as 32
119 * bits wide we use a 64 bit structure here to keep parity with
120 * KVM_GET/SET_ONE_REG behaviour which treats all system registers as
121 * 64 bit values. It also allows for the possibility of the
122 * architecture expanding the control registers without having to
123 * change the userspace ABI.
124 */
125#define KVM_ARM_MAX_DBG_REGS 16
126struct kvm_guest_debug_arch {
127 __u64 dbg_bcr[KVM_ARM_MAX_DBG_REGS];
128 __u64 dbg_bvr[KVM_ARM_MAX_DBG_REGS];
129 __u64 dbg_wcr[KVM_ARM_MAX_DBG_REGS];
130 __u64 dbg_wvr[KVM_ARM_MAX_DBG_REGS];
131};
132
133struct kvm_debug_exit_arch {
134 __u32 hsr;
135 __u64 far; /* used for watchpoints */
136};
137
138/*
139 * Architecture specific defines for kvm_guest_debug->control
140 */
141
142#define KVM_GUESTDBG_USE_SW_BP (1 << 16)
143#define KVM_GUESTDBG_USE_HW (1 << 17)
144
145struct kvm_sync_regs {
146};
147
148struct kvm_arch_memory_slot {
149};
150
151/* If you need to interpret the index values, here is the key: */
152#define KVM_REG_ARM_COPROC_MASK 0x000000000FFF0000
153#define KVM_REG_ARM_COPROC_SHIFT 16
154
155/* Normal registers are mapped as coprocessor 16. */
156#define KVM_REG_ARM_CORE (0x0010 << KVM_REG_ARM_COPROC_SHIFT)
157#define KVM_REG_ARM_CORE_REG(name) (offsetof(struct kvm_regs, name) / sizeof(__u32))
158
159/* Some registers need more space to represent values. */
160#define KVM_REG_ARM_DEMUX (0x0011 << KVM_REG_ARM_COPROC_SHIFT)
161#define KVM_REG_ARM_DEMUX_ID_MASK 0x000000000000FF00
162#define KVM_REG_ARM_DEMUX_ID_SHIFT 8
163#define KVM_REG_ARM_DEMUX_ID_CCSIDR (0x00 << KVM_REG_ARM_DEMUX_ID_SHIFT)
164#define KVM_REG_ARM_DEMUX_VAL_MASK 0x00000000000000FF
165#define KVM_REG_ARM_DEMUX_VAL_SHIFT 0
166
167/* AArch64 system registers */
168#define KVM_REG_ARM64_SYSREG (0x0013 << KVM_REG_ARM_COPROC_SHIFT)
169#define KVM_REG_ARM64_SYSREG_OP0_MASK 0x000000000000c000
170#define KVM_REG_ARM64_SYSREG_OP0_SHIFT 14
171#define KVM_REG_ARM64_SYSREG_OP1_MASK 0x0000000000003800
172#define KVM_REG_ARM64_SYSREG_OP1_SHIFT 11
173#define KVM_REG_ARM64_SYSREG_CRN_MASK 0x0000000000000780
174#define KVM_REG_ARM64_SYSREG_CRN_SHIFT 7
175#define KVM_REG_ARM64_SYSREG_CRM_MASK 0x0000000000000078
176#define KVM_REG_ARM64_SYSREG_CRM_SHIFT 3
177#define KVM_REG_ARM64_SYSREG_OP2_MASK 0x0000000000000007
178#define KVM_REG_ARM64_SYSREG_OP2_SHIFT 0
179
180#define ARM64_SYS_REG_SHIFT_MASK(x,n) \
181 (((x) << KVM_REG_ARM64_SYSREG_ ## n ## _SHIFT) & \
182 KVM_REG_ARM64_SYSREG_ ## n ## _MASK)
183
184#define __ARM64_SYS_REG(op0,op1,crn,crm,op2) \
185 (KVM_REG_ARM64 | KVM_REG_ARM64_SYSREG | \
186 ARM64_SYS_REG_SHIFT_MASK(op0, OP0) | \
187 ARM64_SYS_REG_SHIFT_MASK(op1, OP1) | \
188 ARM64_SYS_REG_SHIFT_MASK(crn, CRN) | \
189 ARM64_SYS_REG_SHIFT_MASK(crm, CRM) | \
190 ARM64_SYS_REG_SHIFT_MASK(op2, OP2))
191
192#define ARM64_SYS_REG(...) (__ARM64_SYS_REG(__VA_ARGS__) | KVM_REG_SIZE_U64)
193
194#define KVM_REG_ARM_TIMER_CTL ARM64_SYS_REG(3, 3, 14, 3, 1)
195#define KVM_REG_ARM_TIMER_CNT ARM64_SYS_REG(3, 3, 14, 3, 2)
196#define KVM_REG_ARM_TIMER_CVAL ARM64_SYS_REG(3, 3, 14, 0, 2)
197
198/* Device Control API: ARM VGIC */
199#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
200#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
201#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
202#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
203#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
204#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
205#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
206#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
207#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
208#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
209
210/* Device Control API on vcpu fd */
211#define KVM_ARM_VCPU_PMU_V3_CTRL 0
212#define KVM_ARM_VCPU_PMU_V3_IRQ 0
213#define KVM_ARM_VCPU_PMU_V3_INIT 1
214
215/* KVM_IRQ_LINE irq field index values */
216#define KVM_ARM_IRQ_TYPE_SHIFT 24
217#define KVM_ARM_IRQ_TYPE_MASK 0xff
218#define KVM_ARM_IRQ_VCPU_SHIFT 16
219#define KVM_ARM_IRQ_VCPU_MASK 0xff
220#define KVM_ARM_IRQ_NUM_SHIFT 0
221#define KVM_ARM_IRQ_NUM_MASK 0xffff
222
223/* irq_type field */
224#define KVM_ARM_IRQ_TYPE_CPU 0
225#define KVM_ARM_IRQ_TYPE_SPI 1
226#define KVM_ARM_IRQ_TYPE_PPI 2
227
228/* out-of-kernel GIC cpu interrupt injection irq_number field */
229#define KVM_ARM_IRQ_CPU_IRQ 0
230#define KVM_ARM_IRQ_CPU_FIQ 1
231
232/*
233 * This used to hold the highest supported SPI, but it is now obsolete
234 * and only here to provide source code level compatibility with older
235 * userland. The highest SPI number can be set via KVM_DEV_ARM_VGIC_GRP_NR_IRQS.
236 */
237#ifndef __KERNEL__
238#define KVM_ARM_IRQ_GIC_MAX 127
239#endif
240
241/* One single KVM irqchip, ie. the VGIC */
242#define KVM_NR_IRQCHIPS 1
243
244/* PSCI interface */
245#define KVM_PSCI_FN_BASE 0x95c1ba5e
246#define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n))
247
248#define KVM_PSCI_FN_CPU_SUSPEND KVM_PSCI_FN(0)
249#define KVM_PSCI_FN_CPU_OFF KVM_PSCI_FN(1)
250#define KVM_PSCI_FN_CPU_ON KVM_PSCI_FN(2)
251#define KVM_PSCI_FN_MIGRATE KVM_PSCI_FN(3)
252
253#define KVM_PSCI_RET_SUCCESS PSCI_RET_SUCCESS
254#define KVM_PSCI_RET_NI PSCI_RET_NOT_SUPPORTED
255#define KVM_PSCI_RET_INVAL PSCI_RET_INVALID_PARAMS
256#define KVM_PSCI_RET_DENIED PSCI_RET_DENIED
257
258#endif
259
260#endif /* __ARM_KVM_H__ */
diff --git a/tools/arch/arm64/include/uapi/asm/mman.h b/tools/arch/arm64/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..70fd3113710a
--- /dev/null
+++ b/tools/arch/arm64/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_ARM64_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on arm64, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/arm64/include/uapi/asm/perf_regs.h b/tools/arch/arm64/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..172b8317ee49
--- /dev/null
+++ b/tools/arch/arm64/include/uapi/asm/perf_regs.h
@@ -0,0 +1,40 @@
1#ifndef _ASM_ARM64_PERF_REGS_H
2#define _ASM_ARM64_PERF_REGS_H
3
4enum perf_event_arm_regs {
5 PERF_REG_ARM64_X0,
6 PERF_REG_ARM64_X1,
7 PERF_REG_ARM64_X2,
8 PERF_REG_ARM64_X3,
9 PERF_REG_ARM64_X4,
10 PERF_REG_ARM64_X5,
11 PERF_REG_ARM64_X6,
12 PERF_REG_ARM64_X7,
13 PERF_REG_ARM64_X8,
14 PERF_REG_ARM64_X9,
15 PERF_REG_ARM64_X10,
16 PERF_REG_ARM64_X11,
17 PERF_REG_ARM64_X12,
18 PERF_REG_ARM64_X13,
19 PERF_REG_ARM64_X14,
20 PERF_REG_ARM64_X15,
21 PERF_REG_ARM64_X16,
22 PERF_REG_ARM64_X17,
23 PERF_REG_ARM64_X18,
24 PERF_REG_ARM64_X19,
25 PERF_REG_ARM64_X20,
26 PERF_REG_ARM64_X21,
27 PERF_REG_ARM64_X22,
28 PERF_REG_ARM64_X23,
29 PERF_REG_ARM64_X24,
30 PERF_REG_ARM64_X25,
31 PERF_REG_ARM64_X26,
32 PERF_REG_ARM64_X27,
33 PERF_REG_ARM64_X28,
34 PERF_REG_ARM64_X29,
35 PERF_REG_ARM64_LR,
36 PERF_REG_ARM64_SP,
37 PERF_REG_ARM64_PC,
38 PERF_REG_ARM64_MAX,
39};
40#endif /* _ASM_ARM64_PERF_REGS_H */
diff --git a/tools/arch/frv/include/uapi/asm/bitsperlong.h b/tools/arch/frv/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..6dc0bb0c13b2
--- /dev/null
+++ b/tools/arch/frv/include/uapi/asm/bitsperlong.h
@@ -0,0 +1 @@
#include <asm-generic/bitsperlong.h>
diff --git a/tools/arch/frv/include/uapi/asm/mman.h b/tools/arch/frv/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..5be78ac12464
--- /dev/null
+++ b/tools/arch/frv/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_FRV_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on frv, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/h8300/include/asm/bitsperlong.h b/tools/arch/h8300/include/asm/bitsperlong.h
new file mode 100644
index 000000000000..e140e46729ac
--- /dev/null
+++ b/tools/arch/h8300/include/asm/bitsperlong.h
@@ -0,0 +1,14 @@
1#ifndef __ASM_H8300_BITS_PER_LONG
2#define __ASM_H8300_BITS_PER_LONG
3
4#include <asm-generic/bitsperlong.h>
5
6#if !defined(__ASSEMBLY__)
7/* h8300-unknown-linux required long */
8#define __kernel_size_t __kernel_size_t
9typedef unsigned long __kernel_size_t;
10typedef long __kernel_ssize_t;
11typedef long __kernel_ptrdiff_t;
12#endif
13
14#endif /* __ASM_H8300_BITS_PER_LONG */
diff --git a/tools/arch/h8300/include/uapi/asm/mman.h b/tools/arch/h8300/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..9d9ac54d3c5a
--- /dev/null
+++ b/tools/arch/h8300/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_H8300_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on h8300, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/hexagon/include/uapi/asm/bitsperlong.h b/tools/arch/hexagon/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..4a658151383d
--- /dev/null
+++ b/tools/arch/hexagon/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright (c) 2010-2011, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 * 02110-1301, USA.
17 */
18
19#ifndef __ASM_HEXAGON_BITSPERLONG_H
20#define __ASM_HEXAGON_BITSPERLONG_H
21
22#define __BITS_PER_LONG 32
23
24#include <asm-generic/bitsperlong.h>
25
26#endif
diff --git a/tools/arch/hexagon/include/uapi/asm/mman.h b/tools/arch/hexagon/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..102f3fae6085
--- /dev/null
+++ b/tools/arch/hexagon/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_HEXAGON_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on hexagon, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/ia64/include/uapi/asm/bitsperlong.h b/tools/arch/ia64/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..ec4db3c970b7
--- /dev/null
+++ b/tools/arch/ia64/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,8 @@
1#ifndef __ASM_IA64_BITSPERLONG_H
2#define __ASM_IA64_BITSPERLONG_H
3
4#define __BITS_PER_LONG 64
5
6#include <asm-generic/bitsperlong.h>
7
8#endif /* __ASM_IA64_BITSPERLONG_H */
diff --git a/tools/arch/ia64/include/uapi/asm/mman.h b/tools/arch/ia64/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..1d6e5ac6442d
--- /dev/null
+++ b/tools/arch/ia64/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_IA64_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on ia64, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/m32r/include/uapi/asm/bitsperlong.h b/tools/arch/m32r/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..6dc0bb0c13b2
--- /dev/null
+++ b/tools/arch/m32r/include/uapi/asm/bitsperlong.h
@@ -0,0 +1 @@
#include <asm-generic/bitsperlong.h>
diff --git a/tools/arch/m32r/include/uapi/asm/mman.h b/tools/arch/m32r/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..1c29635bb73b
--- /dev/null
+++ b/tools/arch/m32r/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_M32R_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on m32r, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/microblaze/include/uapi/asm/bitsperlong.h b/tools/arch/microblaze/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..6dc0bb0c13b2
--- /dev/null
+++ b/tools/arch/microblaze/include/uapi/asm/bitsperlong.h
@@ -0,0 +1 @@
#include <asm-generic/bitsperlong.h>
diff --git a/tools/arch/microblaze/include/uapi/asm/mman.h b/tools/arch/microblaze/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..005cd50b50e1
--- /dev/null
+++ b/tools/arch/microblaze/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MICROBLAZE_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on microblaze, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/mips/include/uapi/asm/bitsperlong.h b/tools/arch/mips/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..3e4c10a8e787
--- /dev/null
+++ b/tools/arch/mips/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,8 @@
1#ifndef __ASM_MIPS_BITSPERLONG_H
2#define __ASM_MIPS_BITSPERLONG_H
3
4#define __BITS_PER_LONG _MIPS_SZLONG
5
6#include <asm-generic/bitsperlong.h>
7
8#endif /* __ASM_MIPS_BITSPERLONG_H */
diff --git a/tools/arch/mips/include/uapi/asm/kvm.h b/tools/arch/mips/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..6985eb59b085
--- /dev/null
+++ b/tools/arch/mips/include/uapi/asm/kvm.h
@@ -0,0 +1,208 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2012 MIPS Technologies, Inc. All rights reserved.
7 * Copyright (C) 2013 Cavium, Inc.
8 * Authors: Sanjay Lal <sanjayl@kymasys.com>
9 */
10
11#ifndef __LINUX_KVM_MIPS_H
12#define __LINUX_KVM_MIPS_H
13
14#include <linux/types.h>
15
16/*
17 * KVM MIPS specific structures and definitions.
18 *
19 * Some parts derived from the x86 version of this file.
20 */
21
22/*
23 * for KVM_GET_REGS and KVM_SET_REGS
24 *
25 * If Config[AT] is zero (32-bit CPU), the register contents are
26 * stored in the lower 32-bits of the struct kvm_regs fields and sign
27 * extended to 64-bits.
28 */
29struct kvm_regs {
30 /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
31 __u64 gpr[32];
32 __u64 hi;
33 __u64 lo;
34 __u64 pc;
35};
36
37/*
38 * for KVM_GET_FPU and KVM_SET_FPU
39 */
40struct kvm_fpu {
41};
42
43
44/*
45 * For MIPS, we use KVM_SET_ONE_REG and KVM_GET_ONE_REG to access various
46 * registers. The id field is broken down as follows:
47 *
48 * bits[63..52] - As per linux/kvm.h
49 * bits[51..32] - Must be zero.
50 * bits[31..16] - Register set.
51 *
52 * Register set = 0: GP registers from kvm_regs (see definitions below).
53 *
54 * Register set = 1: CP0 registers.
55 * bits[15..8] - Must be zero.
56 * bits[7..3] - Register 'rd' index.
57 * bits[2..0] - Register 'sel' index.
58 *
59 * Register set = 2: KVM specific registers (see definitions below).
60 *
61 * Register set = 3: FPU / MSA registers (see definitions below).
62 *
63 * Other sets registers may be added in the future. Each set would
64 * have its own identifier in bits[31..16].
65 */
66
67#define KVM_REG_MIPS_GP (KVM_REG_MIPS | 0x0000000000000000ULL)
68#define KVM_REG_MIPS_CP0 (KVM_REG_MIPS | 0x0000000000010000ULL)
69#define KVM_REG_MIPS_KVM (KVM_REG_MIPS | 0x0000000000020000ULL)
70#define KVM_REG_MIPS_FPU (KVM_REG_MIPS | 0x0000000000030000ULL)
71
72
73/*
74 * KVM_REG_MIPS_GP - General purpose registers from kvm_regs.
75 */
76
77#define KVM_REG_MIPS_R0 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 0)
78#define KVM_REG_MIPS_R1 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 1)
79#define KVM_REG_MIPS_R2 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 2)
80#define KVM_REG_MIPS_R3 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 3)
81#define KVM_REG_MIPS_R4 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 4)
82#define KVM_REG_MIPS_R5 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 5)
83#define KVM_REG_MIPS_R6 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 6)
84#define KVM_REG_MIPS_R7 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 7)
85#define KVM_REG_MIPS_R8 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 8)
86#define KVM_REG_MIPS_R9 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 9)
87#define KVM_REG_MIPS_R10 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 10)
88#define KVM_REG_MIPS_R11 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 11)
89#define KVM_REG_MIPS_R12 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 12)
90#define KVM_REG_MIPS_R13 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 13)
91#define KVM_REG_MIPS_R14 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 14)
92#define KVM_REG_MIPS_R15 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 15)
93#define KVM_REG_MIPS_R16 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 16)
94#define KVM_REG_MIPS_R17 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 17)
95#define KVM_REG_MIPS_R18 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 18)
96#define KVM_REG_MIPS_R19 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 19)
97#define KVM_REG_MIPS_R20 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 20)
98#define KVM_REG_MIPS_R21 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 21)
99#define KVM_REG_MIPS_R22 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 22)
100#define KVM_REG_MIPS_R23 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 23)
101#define KVM_REG_MIPS_R24 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 24)
102#define KVM_REG_MIPS_R25 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 25)
103#define KVM_REG_MIPS_R26 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 26)
104#define KVM_REG_MIPS_R27 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 27)
105#define KVM_REG_MIPS_R28 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 28)
106#define KVM_REG_MIPS_R29 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 29)
107#define KVM_REG_MIPS_R30 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 30)
108#define KVM_REG_MIPS_R31 (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 31)
109
110#define KVM_REG_MIPS_HI (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 32)
111#define KVM_REG_MIPS_LO (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 33)
112#define KVM_REG_MIPS_PC (KVM_REG_MIPS_GP | KVM_REG_SIZE_U64 | 34)
113
114
115/*
116 * KVM_REG_MIPS_KVM - KVM specific control registers.
117 */
118
119/*
120 * CP0_Count control
121 * DC: Set 0: Master disable CP0_Count and set COUNT_RESUME to now
122 * Set 1: Master re-enable CP0_Count with unchanged bias, handling timer
123 * interrupts since COUNT_RESUME
124 * This can be used to freeze the timer to get a consistent snapshot of
125 * the CP0_Count and timer interrupt pending state, while also resuming
126 * safely without losing time or guest timer interrupts.
127 * Other: Reserved, do not change.
128 */
129#define KVM_REG_MIPS_COUNT_CTL (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 0)
130#define KVM_REG_MIPS_COUNT_CTL_DC 0x00000001
131
132/*
133 * CP0_Count resume monotonic nanoseconds
134 * The monotonic nanosecond time of the last set of COUNT_CTL.DC (master
135 * disable). Any reads and writes of Count related registers while
136 * COUNT_CTL.DC=1 will appear to occur at this time. When COUNT_CTL.DC is
137 * cleared again (master enable) any timer interrupts since this time will be
138 * emulated.
139 * Modifications to times in the future are rejected.
140 */
141#define KVM_REG_MIPS_COUNT_RESUME (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 1)
142/*
143 * CP0_Count rate in Hz
144 * Specifies the rate of the CP0_Count timer in Hz. Modifications occur without
145 * discontinuities in CP0_Count.
146 */
147#define KVM_REG_MIPS_COUNT_HZ (KVM_REG_MIPS_KVM | KVM_REG_SIZE_U64 | 2)
148
149
150/*
151 * KVM_REG_MIPS_FPU - Floating Point and MIPS SIMD Architecture (MSA) registers.
152 *
153 * bits[15..8] - Register subset (see definitions below).
154 * bits[7..5] - Must be zero.
155 * bits[4..0] - Register number within register subset.
156 */
157
158#define KVM_REG_MIPS_FPR (KVM_REG_MIPS_FPU | 0x0000000000000000ULL)
159#define KVM_REG_MIPS_FCR (KVM_REG_MIPS_FPU | 0x0000000000000100ULL)
160#define KVM_REG_MIPS_MSACR (KVM_REG_MIPS_FPU | 0x0000000000000200ULL)
161
162/*
163 * KVM_REG_MIPS_FPR - Floating point / Vector registers.
164 */
165#define KVM_REG_MIPS_FPR_32(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U32 | (n))
166#define KVM_REG_MIPS_FPR_64(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U64 | (n))
167#define KVM_REG_MIPS_VEC_128(n) (KVM_REG_MIPS_FPR | KVM_REG_SIZE_U128 | (n))
168
169/*
170 * KVM_REG_MIPS_FCR - Floating point control registers.
171 */
172#define KVM_REG_MIPS_FCR_IR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 0)
173#define KVM_REG_MIPS_FCR_CSR (KVM_REG_MIPS_FCR | KVM_REG_SIZE_U32 | 31)
174
175/*
176 * KVM_REG_MIPS_MSACR - MIPS SIMD Architecture (MSA) control registers.
177 */
178#define KVM_REG_MIPS_MSA_IR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 0)
179#define KVM_REG_MIPS_MSA_CSR (KVM_REG_MIPS_MSACR | KVM_REG_SIZE_U32 | 1)
180
181
182/*
183 * KVM MIPS specific structures and definitions
184 *
185 */
186struct kvm_debug_exit_arch {
187 __u64 epc;
188};
189
190/* for KVM_SET_GUEST_DEBUG */
191struct kvm_guest_debug_arch {
192};
193
194/* definition of registers in kvm_run */
195struct kvm_sync_regs {
196};
197
198/* dummy definition */
199struct kvm_sregs {
200};
201
202struct kvm_mips_interrupt {
203 /* in */
204 __u32 cpu;
205 __u32 irq;
206};
207
208#endif /* __LINUX_KVM_MIPS_H */
diff --git a/tools/arch/mips/include/uapi/asm/mman.h b/tools/arch/mips/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..c02052965d50
--- /dev/null
+++ b/tools/arch/mips/include/uapi/asm/mman.h
@@ -0,0 +1,46 @@
1#ifndef TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MIPS_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 16
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 4
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 14
10#define MADV_HWPOISON 100
11#define MADV_MERGEABLE 12
12#define MADV_NOHUGEPAGE 15
13#define MADV_NORMAL 0
14#define MADV_RANDOM 1
15#define MADV_REMOVE 9
16#define MADV_SEQUENTIAL 2
17#define MADV_UNMERGEABLE 13
18#define MADV_WILLNEED 3
19#define MAP_ANONYMOUS 0x0800
20#define MAP_DENYWRITE 0x2000
21#define MAP_EXECUTABLE 0x4000
22#define MAP_FILE 0
23#define MAP_FIXED 0x010
24#define MAP_GROWSDOWN 0x1000
25#define MAP_HUGETLB 0x80000
26#define MAP_LOCKED 0x8000
27#define MAP_NONBLOCK 0x20000
28#define MAP_NORESERVE 0x0400
29#define MAP_POPULATE 0x10000
30#define MAP_PRIVATE 0x002
31#define MAP_SHARED 0x001
32#define MAP_STACK 0x40000
33#define PROT_EXEC 0x04
34#define PROT_GROWSDOWN 0x01000000
35#define PROT_GROWSUP 0x02000000
36#define PROT_NONE 0x00
37#define PROT_READ 0x01
38#define PROT_SEM 0x10
39#define PROT_WRITE 0x02
40/* MADV_SOFT_OFFLINE is undefined on mips, fix it for perf */
41#define MADV_SOFT_OFFLINE 101
42/* MAP_32BIT is undefined on mips, fix it for perf */
43#define MAP_32BIT 0
44/* MAP_UNINITIALIZED is undefined on mips, fix it for perf */
45#define MAP_UNINITIALIZED 0
46#endif
diff --git a/tools/arch/mn10300/include/uapi/asm/bitsperlong.h b/tools/arch/mn10300/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..6dc0bb0c13b2
--- /dev/null
+++ b/tools/arch/mn10300/include/uapi/asm/bitsperlong.h
@@ -0,0 +1 @@
#include <asm-generic/bitsperlong.h>
diff --git a/tools/arch/mn10300/include/uapi/asm/mman.h b/tools/arch/mn10300/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..c1ea36d83acc
--- /dev/null
+++ b/tools/arch/mn10300/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_MN10300_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on mn10300, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/parisc/include/uapi/asm/bitsperlong.h b/tools/arch/parisc/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..e0a23c7bdd43
--- /dev/null
+++ b/tools/arch/parisc/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,14 @@
1#ifndef __ASM_PARISC_BITSPERLONG_H
2#define __ASM_PARISC_BITSPERLONG_H
3
4#if defined(__LP64__)
5#define __BITS_PER_LONG 64
6#define SHIFT_PER_LONG 6
7#else
8#define __BITS_PER_LONG 32
9#define SHIFT_PER_LONG 5
10#endif
11
12#include <asm-generic/bitsperlong.h>
13
14#endif /* __ASM_PARISC_BITSPERLONG_H */
diff --git a/tools/arch/parisc/include/uapi/asm/mman.h b/tools/arch/parisc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..03d8d5b7ae7f
--- /dev/null
+++ b/tools/arch/parisc/include/uapi/asm/mman.h
@@ -0,0 +1,47 @@
1#ifndef TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_PARISC_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 70
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 69
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 4
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 67
10#define MADV_MERGEABLE 65
11#define MADV_NOHUGEPAGE 68
12#define MADV_NORMAL 0
13#define MADV_RANDOM 1
14#define MADV_REMOVE 9
15#define MADV_SEQUENTIAL 2
16#define MADV_UNMERGEABLE 66
17#define MADV_WILLNEED 3
18#define MAP_ANONYMOUS 0x10
19#define MAP_DENYWRITE 0x0800
20#define MAP_EXECUTABLE 0x1000
21#define MAP_FILE 0
22#define MAP_FIXED 0x04
23#define MAP_GROWSDOWN 0x8000
24#define MAP_HUGETLB 0x80000
25#define MAP_LOCKED 0x2000
26#define MAP_NONBLOCK 0x20000
27#define MAP_NORESERVE 0x4000
28#define MAP_POPULATE 0x10000
29#define MAP_PRIVATE 0x02
30#define MAP_SHARED 0x01
31#define MAP_STACK 0x40000
32#define PROT_EXEC 0x4
33#define PROT_GROWSDOWN 0x01000000
34#define PROT_GROWSUP 0x02000000
35#define PROT_NONE 0x0
36#define PROT_READ 0x1
37#define PROT_SEM 0x8
38#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on parisc, fix it for perf */
40#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on parisc, fix it for perf */
42#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on parisc, fix it for perf */
44#define MAP_32BIT 0
45/* MAP_UNINITIALIZED is undefined on parisc, fix it for perf */
46#define MAP_UNINITIALIZED 0
47#endif
diff --git a/tools/arch/powerpc/include/uapi/asm/bitsperlong.h b/tools/arch/powerpc/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..5f1659032c40
--- /dev/null
+++ b/tools/arch/powerpc/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,12 @@
1#ifndef __ASM_POWERPC_BITSPERLONG_H
2#define __ASM_POWERPC_BITSPERLONG_H
3
4#if defined(__powerpc64__)
5# define __BITS_PER_LONG 64
6#else
7# define __BITS_PER_LONG 32
8#endif
9
10#include <asm-generic/bitsperlong.h>
11
12#endif /* __ASM_POWERPC_BITSPERLONG_H */
diff --git a/tools/arch/powerpc/include/uapi/asm/kvm.h b/tools/arch/powerpc/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..c93cf35ce379
--- /dev/null
+++ b/tools/arch/powerpc/include/uapi/asm/kvm.h
@@ -0,0 +1,612 @@
1/*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License, version 2, as
4 * published by the Free Software Foundation.
5 *
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU General Public License for more details.
10 *
11 * You should have received a copy of the GNU General Public License
12 * along with this program; if not, write to the Free Software
13 * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
14 *
15 * Copyright IBM Corp. 2007
16 *
17 * Authors: Hollis Blanchard <hollisb@us.ibm.com>
18 */
19
20#ifndef __LINUX_KVM_POWERPC_H
21#define __LINUX_KVM_POWERPC_H
22
23#include <linux/types.h>
24
25/* Select powerpc specific features in <linux/kvm.h> */
26#define __KVM_HAVE_SPAPR_TCE
27#define __KVM_HAVE_PPC_SMT
28#define __KVM_HAVE_IRQCHIP
29#define __KVM_HAVE_IRQ_LINE
30#define __KVM_HAVE_GUEST_DEBUG
31
32struct kvm_regs {
33 __u64 pc;
34 __u64 cr;
35 __u64 ctr;
36 __u64 lr;
37 __u64 xer;
38 __u64 msr;
39 __u64 srr0;
40 __u64 srr1;
41 __u64 pid;
42
43 __u64 sprg0;
44 __u64 sprg1;
45 __u64 sprg2;
46 __u64 sprg3;
47 __u64 sprg4;
48 __u64 sprg5;
49 __u64 sprg6;
50 __u64 sprg7;
51
52 __u64 gpr[32];
53};
54
55#define KVM_SREGS_E_IMPL_NONE 0
56#define KVM_SREGS_E_IMPL_FSL 1
57
58#define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */
59
60/*
61 * Feature bits indicate which sections of the sregs struct are valid,
62 * both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers
63 * corresponding to unset feature bits will not be modified. This allows
64 * restoring a checkpoint made without that feature, while keeping the
65 * default values of the new registers.
66 *
67 * KVM_SREGS_E_BASE contains:
68 * CSRR0/1 (refers to SRR2/3 on 40x)
69 * ESR
70 * DEAR
71 * MCSR
72 * TSR
73 * TCR
74 * DEC
75 * TB
76 * VRSAVE (USPRG0)
77 */
78#define KVM_SREGS_E_BASE (1 << 0)
79
80/*
81 * KVM_SREGS_E_ARCH206 contains:
82 *
83 * PIR
84 * MCSRR0/1
85 * DECAR
86 * IVPR
87 */
88#define KVM_SREGS_E_ARCH206 (1 << 1)
89
90/*
91 * Contains EPCR, plus the upper half of 64-bit registers
92 * that are 32-bit on 32-bit implementations.
93 */
94#define KVM_SREGS_E_64 (1 << 2)
95
96#define KVM_SREGS_E_SPRG8 (1 << 3)
97#define KVM_SREGS_E_MCIVPR (1 << 4)
98
99/*
100 * IVORs are used -- contains IVOR0-15, plus additional IVORs
101 * in combination with an appropriate feature bit.
102 */
103#define KVM_SREGS_E_IVOR (1 << 5)
104
105/*
106 * Contains MAS0-4, MAS6-7, TLBnCFG, MMUCFG.
107 * Also TLBnPS if MMUCFG[MAVN] = 1.
108 */
109#define KVM_SREGS_E_ARCH206_MMU (1 << 6)
110
111/* DBSR, DBCR, IAC, DAC, DVC */
112#define KVM_SREGS_E_DEBUG (1 << 7)
113
114/* Enhanced debug -- DSRR0/1, SPRG9 */
115#define KVM_SREGS_E_ED (1 << 8)
116
117/* Embedded Floating Point (SPE) -- IVOR32-34 if KVM_SREGS_E_IVOR */
118#define KVM_SREGS_E_SPE (1 << 9)
119
120/*
121 * DEPRECATED! USE ONE_REG FOR THIS ONE!
122 * External Proxy (EXP) -- EPR
123 */
124#define KVM_SREGS_EXP (1 << 10)
125
126/* External PID (E.PD) -- EPSC/EPLC */
127#define KVM_SREGS_E_PD (1 << 11)
128
129/* Processor Control (E.PC) -- IVOR36-37 if KVM_SREGS_E_IVOR */
130#define KVM_SREGS_E_PC (1 << 12)
131
132/* Page table (E.PT) -- EPTCFG */
133#define KVM_SREGS_E_PT (1 << 13)
134
135/* Embedded Performance Monitor (E.PM) -- IVOR35 if KVM_SREGS_E_IVOR */
136#define KVM_SREGS_E_PM (1 << 14)
137
138/*
139 * Special updates:
140 *
141 * Some registers may change even while a vcpu is not running.
142 * To avoid losing these changes, by default these registers are
143 * not updated by KVM_SET_SREGS. To force an update, set the bit
144 * in u.e.update_special corresponding to the register to be updated.
145 *
146 * The update_special field is zero on return from KVM_GET_SREGS.
147 *
148 * When restoring a checkpoint, the caller can set update_special
149 * to 0xffffffff to ensure that everything is restored, even new features
150 * that the caller doesn't know about.
151 */
152#define KVM_SREGS_E_UPDATE_MCSR (1 << 0)
153#define KVM_SREGS_E_UPDATE_TSR (1 << 1)
154#define KVM_SREGS_E_UPDATE_DEC (1 << 2)
155#define KVM_SREGS_E_UPDATE_DBSR (1 << 3)
156
157/*
158 * In KVM_SET_SREGS, reserved/pad fields must be left untouched from a
159 * previous KVM_GET_REGS.
160 *
161 * Unless otherwise indicated, setting any register with KVM_SET_SREGS
162 * directly sets its value. It does not trigger any special semantics such
163 * as write-one-to-clear. Calling KVM_SET_SREGS on an unmodified struct
164 * just received from KVM_GET_SREGS is always a no-op.
165 */
166struct kvm_sregs {
167 __u32 pvr;
168 union {
169 struct {
170 __u64 sdr1;
171 struct {
172 struct {
173 __u64 slbe;
174 __u64 slbv;
175 } slb[64];
176 } ppc64;
177 struct {
178 __u32 sr[16];
179 __u64 ibat[8];
180 __u64 dbat[8];
181 } ppc32;
182 } s;
183 struct {
184 union {
185 struct { /* KVM_SREGS_E_IMPL_FSL */
186 __u32 features; /* KVM_SREGS_E_FSL_ */
187 __u32 svr;
188 __u64 mcar;
189 __u32 hid0;
190
191 /* KVM_SREGS_E_FSL_PIDn */
192 __u32 pid1, pid2;
193 } fsl;
194 __u8 pad[256];
195 } impl;
196
197 __u32 features; /* KVM_SREGS_E_ */
198 __u32 impl_id; /* KVM_SREGS_E_IMPL_ */
199 __u32 update_special; /* KVM_SREGS_E_UPDATE_ */
200 __u32 pir; /* read-only */
201 __u64 sprg8;
202 __u64 sprg9; /* E.ED */
203 __u64 csrr0;
204 __u64 dsrr0; /* E.ED */
205 __u64 mcsrr0;
206 __u32 csrr1;
207 __u32 dsrr1; /* E.ED */
208 __u32 mcsrr1;
209 __u32 esr;
210 __u64 dear;
211 __u64 ivpr;
212 __u64 mcivpr;
213 __u64 mcsr; /* KVM_SREGS_E_UPDATE_MCSR */
214
215 __u32 tsr; /* KVM_SREGS_E_UPDATE_TSR */
216 __u32 tcr;
217 __u32 decar;
218 __u32 dec; /* KVM_SREGS_E_UPDATE_DEC */
219
220 /*
221 * Userspace can read TB directly, but the
222 * value reported here is consistent with "dec".
223 *
224 * Read-only.
225 */
226 __u64 tb;
227
228 __u32 dbsr; /* KVM_SREGS_E_UPDATE_DBSR */
229 __u32 dbcr[3];
230 /*
231 * iac/dac registers are 64bit wide, while this API
232 * interface provides only lower 32 bits on 64 bit
233 * processors. ONE_REG interface is added for 64bit
234 * iac/dac registers.
235 */
236 __u32 iac[4];
237 __u32 dac[2];
238 __u32 dvc[2];
239 __u8 num_iac; /* read-only */
240 __u8 num_dac; /* read-only */
241 __u8 num_dvc; /* read-only */
242 __u8 pad;
243
244 __u32 epr; /* EXP */
245 __u32 vrsave; /* a.k.a. USPRG0 */
246 __u32 epcr; /* KVM_SREGS_E_64 */
247
248 __u32 mas0;
249 __u32 mas1;
250 __u64 mas2;
251 __u64 mas7_3;
252 __u32 mas4;
253 __u32 mas6;
254
255 __u32 ivor_low[16]; /* IVOR0-15 */
256 __u32 ivor_high[18]; /* IVOR32+, plus room to expand */
257
258 __u32 mmucfg; /* read-only */
259 __u32 eptcfg; /* E.PT, read-only */
260 __u32 tlbcfg[4];/* read-only */
261 __u32 tlbps[4]; /* read-only */
262
263 __u32 eplc, epsc; /* E.PD */
264 } e;
265 __u8 pad[1020];
266 } u;
267};
268
269struct kvm_fpu {
270 __u64 fpr[32];
271};
272
273/*
274 * Defines for h/w breakpoint, watchpoint (read, write or both) and
275 * software breakpoint.
276 * These are used as "type" in KVM_SET_GUEST_DEBUG ioctl and "status"
277 * for KVM_DEBUG_EXIT.
278 */
279#define KVMPPC_DEBUG_NONE 0x0
280#define KVMPPC_DEBUG_BREAKPOINT (1UL << 1)
281#define KVMPPC_DEBUG_WATCH_WRITE (1UL << 2)
282#define KVMPPC_DEBUG_WATCH_READ (1UL << 3)
283struct kvm_debug_exit_arch {
284 __u64 address;
285 /*
286 * exiting to userspace because of h/w breakpoint, watchpoint
287 * (read, write or both) and software breakpoint.
288 */
289 __u32 status;
290 __u32 reserved;
291};
292
293/* for KVM_SET_GUEST_DEBUG */
294struct kvm_guest_debug_arch {
295 struct {
296 /* H/W breakpoint/watchpoint address */
297 __u64 addr;
298 /*
299 * Type denotes h/w breakpoint, read watchpoint, write
300 * watchpoint or watchpoint (both read and write).
301 */
302 __u32 type;
303 __u32 reserved;
304 } bp[16];
305};
306
307/* Debug related defines */
308/*
309 * kvm_guest_debug->control is a 32 bit field. The lower 16 bits are generic
310 * and upper 16 bits are architecture specific. Architecture specific defines
311 * that ioctl is for setting hardware breakpoint or software breakpoint.
312 */
313#define KVM_GUESTDBG_USE_SW_BP 0x00010000
314#define KVM_GUESTDBG_USE_HW_BP 0x00020000
315
316/* definition of registers in kvm_run */
317struct kvm_sync_regs {
318};
319
320#define KVM_INTERRUPT_SET -1U
321#define KVM_INTERRUPT_UNSET -2U
322#define KVM_INTERRUPT_SET_LEVEL -3U
323
324#define KVM_CPU_440 1
325#define KVM_CPU_E500V2 2
326#define KVM_CPU_3S_32 3
327#define KVM_CPU_3S_64 4
328#define KVM_CPU_E500MC 5
329
330/* for KVM_CAP_SPAPR_TCE */
331struct kvm_create_spapr_tce {
332 __u64 liobn;
333 __u32 window_size;
334};
335
336/* for KVM_CAP_SPAPR_TCE_64 */
337struct kvm_create_spapr_tce_64 {
338 __u64 liobn;
339 __u32 page_shift;
340 __u32 flags;
341 __u64 offset; /* in pages */
342 __u64 size; /* in pages */
343};
344
345/* for KVM_ALLOCATE_RMA */
346struct kvm_allocate_rma {
347 __u64 rma_size;
348};
349
350/* for KVM_CAP_PPC_RTAS */
351struct kvm_rtas_token_args {
352 char name[120];
353 __u64 token; /* Use a token of 0 to undefine a mapping */
354};
355
356struct kvm_book3e_206_tlb_entry {
357 __u32 mas8;
358 __u32 mas1;
359 __u64 mas2;
360 __u64 mas7_3;
361};
362
363struct kvm_book3e_206_tlb_params {
364 /*
365 * For mmu types KVM_MMU_FSL_BOOKE_NOHV and KVM_MMU_FSL_BOOKE_HV:
366 *
367 * - The number of ways of TLB0 must be a power of two between 2 and
368 * 16.
369 * - TLB1 must be fully associative.
370 * - The size of TLB0 must be a multiple of the number of ways, and
371 * the number of sets must be a power of two.
372 * - The size of TLB1 may not exceed 64 entries.
373 * - TLB0 supports 4 KiB pages.
374 * - The page sizes supported by TLB1 are as indicated by
375 * TLB1CFG (if MMUCFG[MAVN] = 0) or TLB1PS (if MMUCFG[MAVN] = 1)
376 * as returned by KVM_GET_SREGS.
377 * - TLB2 and TLB3 are reserved, and their entries in tlb_sizes[]
378 * and tlb_ways[] must be zero.
379 *
380 * tlb_ways[n] = tlb_sizes[n] means the array is fully associative.
381 *
382 * KVM will adjust TLBnCFG based on the sizes configured here,
383 * though arrays greater than 2048 entries will have TLBnCFG[NENTRY]
384 * set to zero.
385 */
386 __u32 tlb_sizes[4];
387 __u32 tlb_ways[4];
388 __u32 reserved[8];
389};
390
391/* For KVM_PPC_GET_HTAB_FD */
392struct kvm_get_htab_fd {
393 __u64 flags;
394 __u64 start_index;
395 __u64 reserved[2];
396};
397
398/* Values for kvm_get_htab_fd.flags */
399#define KVM_GET_HTAB_BOLTED_ONLY ((__u64)0x1)
400#define KVM_GET_HTAB_WRITE ((__u64)0x2)
401
402/*
403 * Data read on the file descriptor is formatted as a series of
404 * records, each consisting of a header followed by a series of
405 * `n_valid' HPTEs (16 bytes each), which are all valid. Following
406 * those valid HPTEs there are `n_invalid' invalid HPTEs, which
407 * are not represented explicitly in the stream. The same format
408 * is used for writing.
409 */
410struct kvm_get_htab_header {
411 __u32 index;
412 __u16 n_valid;
413 __u16 n_invalid;
414};
415
416/* Per-vcpu XICS interrupt controller state */
417#define KVM_REG_PPC_ICP_STATE (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8c)
418
419#define KVM_REG_PPC_ICP_CPPR_SHIFT 56 /* current proc priority */
420#define KVM_REG_PPC_ICP_CPPR_MASK 0xff
421#define KVM_REG_PPC_ICP_XISR_SHIFT 32 /* interrupt status field */
422#define KVM_REG_PPC_ICP_XISR_MASK 0xffffff
423#define KVM_REG_PPC_ICP_MFRR_SHIFT 24 /* pending IPI priority */
424#define KVM_REG_PPC_ICP_MFRR_MASK 0xff
425#define KVM_REG_PPC_ICP_PPRI_SHIFT 16 /* pending irq priority */
426#define KVM_REG_PPC_ICP_PPRI_MASK 0xff
427
428/* Device control API: PPC-specific devices */
429#define KVM_DEV_MPIC_GRP_MISC 1
430#define KVM_DEV_MPIC_BASE_ADDR 0 /* 64-bit */
431
432#define KVM_DEV_MPIC_GRP_REGISTER 2 /* 32-bit */
433#define KVM_DEV_MPIC_GRP_IRQ_ACTIVE 3 /* 32-bit */
434
435/* One-Reg API: PPC-specific registers */
436#define KVM_REG_PPC_HIOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x1)
437#define KVM_REG_PPC_IAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x2)
438#define KVM_REG_PPC_IAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3)
439#define KVM_REG_PPC_IAC3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x4)
440#define KVM_REG_PPC_IAC4 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x5)
441#define KVM_REG_PPC_DAC1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x6)
442#define KVM_REG_PPC_DAC2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x7)
443#define KVM_REG_PPC_DABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8)
444#define KVM_REG_PPC_DSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9)
445#define KVM_REG_PPC_PURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa)
446#define KVM_REG_PPC_SPURR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb)
447#define KVM_REG_PPC_DAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xc)
448#define KVM_REG_PPC_DSISR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xd)
449#define KVM_REG_PPC_AMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xe)
450#define KVM_REG_PPC_UAMOR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xf)
451
452#define KVM_REG_PPC_MMCR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x10)
453#define KVM_REG_PPC_MMCR1 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x11)
454#define KVM_REG_PPC_MMCRA (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x12)
455#define KVM_REG_PPC_MMCR2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x13)
456#define KVM_REG_PPC_MMCRS (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x14)
457#define KVM_REG_PPC_SIAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x15)
458#define KVM_REG_PPC_SDAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x16)
459#define KVM_REG_PPC_SIER (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x17)
460
461#define KVM_REG_PPC_PMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x18)
462#define KVM_REG_PPC_PMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x19)
463#define KVM_REG_PPC_PMC3 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1a)
464#define KVM_REG_PPC_PMC4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1b)
465#define KVM_REG_PPC_PMC5 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1c)
466#define KVM_REG_PPC_PMC6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1d)
467#define KVM_REG_PPC_PMC7 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1e)
468#define KVM_REG_PPC_PMC8 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x1f)
469
470/* 32 floating-point registers */
471#define KVM_REG_PPC_FPR0 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x20)
472#define KVM_REG_PPC_FPR(n) (KVM_REG_PPC_FPR0 + (n))
473#define KVM_REG_PPC_FPR31 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x3f)
474
475/* 32 VMX/Altivec vector registers */
476#define KVM_REG_PPC_VR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x40)
477#define KVM_REG_PPC_VR(n) (KVM_REG_PPC_VR0 + (n))
478#define KVM_REG_PPC_VR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x5f)
479
480/* 32 double-width FP registers for VSX */
481/* High-order halves overlap with FP regs */
482#define KVM_REG_PPC_VSR0 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x60)
483#define KVM_REG_PPC_VSR(n) (KVM_REG_PPC_VSR0 + (n))
484#define KVM_REG_PPC_VSR31 (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x7f)
485
486/* FP and vector status/control registers */
487#define KVM_REG_PPC_FPSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x80)
488/*
489 * VSCR register is documented as a 32-bit register in the ISA, but it can
490 * only be accesses via a vector register. Expose VSCR as a 32-bit register
491 * even though the kernel represents it as a 128-bit vector.
492 */
493#define KVM_REG_PPC_VSCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x81)
494
495/* Virtual processor areas */
496/* For SLB & DTL, address in high (first) half, length in low half */
497#define KVM_REG_PPC_VPA_ADDR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x82)
498#define KVM_REG_PPC_VPA_SLB (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x83)
499#define KVM_REG_PPC_VPA_DTL (KVM_REG_PPC | KVM_REG_SIZE_U128 | 0x84)
500
501#define KVM_REG_PPC_EPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x85)
502#define KVM_REG_PPC_EPR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x86)
503
504/* Timer Status Register OR/CLEAR interface */
505#define KVM_REG_PPC_OR_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x87)
506#define KVM_REG_PPC_CLEAR_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x88)
507#define KVM_REG_PPC_TCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x89)
508#define KVM_REG_PPC_TSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8a)
509
510/* Debugging: Special instruction for software breakpoint */
511#define KVM_REG_PPC_DEBUG_INST (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8b)
512
513/* MMU registers */
514#define KVM_REG_PPC_MAS0 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8c)
515#define KVM_REG_PPC_MAS1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x8d)
516#define KVM_REG_PPC_MAS2 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8e)
517#define KVM_REG_PPC_MAS7_3 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x8f)
518#define KVM_REG_PPC_MAS4 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x90)
519#define KVM_REG_PPC_MAS6 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x91)
520#define KVM_REG_PPC_MMUCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x92)
521/*
522 * TLBnCFG fields TLBnCFG_N_ENTRY and TLBnCFG_ASSOC can be changed only using
523 * KVM_CAP_SW_TLB ioctl
524 */
525#define KVM_REG_PPC_TLB0CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x93)
526#define KVM_REG_PPC_TLB1CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x94)
527#define KVM_REG_PPC_TLB2CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x95)
528#define KVM_REG_PPC_TLB3CFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x96)
529#define KVM_REG_PPC_TLB0PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x97)
530#define KVM_REG_PPC_TLB1PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x98)
531#define KVM_REG_PPC_TLB2PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x99)
532#define KVM_REG_PPC_TLB3PS (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9a)
533#define KVM_REG_PPC_EPTCFG (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9b)
534
535/* Timebase offset */
536#define KVM_REG_PPC_TB_OFFSET (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9c)
537
538/* POWER8 registers */
539#define KVM_REG_PPC_SPMC1 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9d)
540#define KVM_REG_PPC_SPMC2 (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0x9e)
541#define KVM_REG_PPC_IAMR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0x9f)
542#define KVM_REG_PPC_TFHAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa0)
543#define KVM_REG_PPC_TFIAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa1)
544#define KVM_REG_PPC_TEXASR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa2)
545#define KVM_REG_PPC_FSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa3)
546#define KVM_REG_PPC_PSPB (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xa4)
547#define KVM_REG_PPC_EBBHR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa5)
548#define KVM_REG_PPC_EBBRR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa6)
549#define KVM_REG_PPC_BESCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa7)
550#define KVM_REG_PPC_TAR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa8)
551#define KVM_REG_PPC_DPDES (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xa9)
552#define KVM_REG_PPC_DAWR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xaa)
553#define KVM_REG_PPC_DAWRX (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xab)
554#define KVM_REG_PPC_CIABR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xac)
555#define KVM_REG_PPC_IC (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xad)
556#define KVM_REG_PPC_VTB (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xae)
557#define KVM_REG_PPC_CSIGR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xaf)
558#define KVM_REG_PPC_TACR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb0)
559#define KVM_REG_PPC_TCSCR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb1)
560#define KVM_REG_PPC_PID (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb2)
561#define KVM_REG_PPC_ACOP (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb3)
562
563#define KVM_REG_PPC_VRSAVE (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb4)
564#define KVM_REG_PPC_LPCR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb5)
565#define KVM_REG_PPC_LPCR_64 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb5)
566#define KVM_REG_PPC_PPR (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb6)
567
568/* Architecture compatibility level */
569#define KVM_REG_PPC_ARCH_COMPAT (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb7)
570
571#define KVM_REG_PPC_DABRX (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xb8)
572#define KVM_REG_PPC_WORT (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xb9)
573#define KVM_REG_PPC_SPRG9 (KVM_REG_PPC | KVM_REG_SIZE_U64 | 0xba)
574#define KVM_REG_PPC_DBSR (KVM_REG_PPC | KVM_REG_SIZE_U32 | 0xbb)
575
576/* Transactional Memory checkpointed state:
577 * This is all GPRs, all VSX regs and a subset of SPRs
578 */
579#define KVM_REG_PPC_TM (KVM_REG_PPC | 0x80000000)
580/* TM GPRs */
581#define KVM_REG_PPC_TM_GPR0 (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0)
582#define KVM_REG_PPC_TM_GPR(n) (KVM_REG_PPC_TM_GPR0 + (n))
583#define KVM_REG_PPC_TM_GPR31 (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x1f)
584/* TM VSX */
585#define KVM_REG_PPC_TM_VSR0 (KVM_REG_PPC_TM | KVM_REG_SIZE_U128 | 0x20)
586#define KVM_REG_PPC_TM_VSR(n) (KVM_REG_PPC_TM_VSR0 + (n))
587#define KVM_REG_PPC_TM_VSR63 (KVM_REG_PPC_TM | KVM_REG_SIZE_U128 | 0x5f)
588/* TM SPRS */
589#define KVM_REG_PPC_TM_CR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x60)
590#define KVM_REG_PPC_TM_LR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x61)
591#define KVM_REG_PPC_TM_CTR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x62)
592#define KVM_REG_PPC_TM_FPSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x63)
593#define KVM_REG_PPC_TM_AMR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x64)
594#define KVM_REG_PPC_TM_PPR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x65)
595#define KVM_REG_PPC_TM_VRSAVE (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x66)
596#define KVM_REG_PPC_TM_VSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U32 | 0x67)
597#define KVM_REG_PPC_TM_DSCR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x68)
598#define KVM_REG_PPC_TM_TAR (KVM_REG_PPC_TM | KVM_REG_SIZE_U64 | 0x69)
599
600/* PPC64 eXternal Interrupt Controller Specification */
601#define KVM_DEV_XICS_GRP_SOURCES 1 /* 64-bit source attributes */
602
603/* Layout of 64-bit source attribute values */
604#define KVM_XICS_DESTINATION_SHIFT 0
605#define KVM_XICS_DESTINATION_MASK 0xffffffffULL
606#define KVM_XICS_PRIORITY_SHIFT 32
607#define KVM_XICS_PRIORITY_MASK 0xff
608#define KVM_XICS_LEVEL_SENSITIVE (1ULL << 40)
609#define KVM_XICS_MASKED (1ULL << 41)
610#define KVM_XICS_PENDING (1ULL << 42)
611
612#endif /* __LINUX_KVM_POWERPC_H */
diff --git a/tools/arch/powerpc/include/uapi/asm/mman.h b/tools/arch/powerpc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..761db43172fe
--- /dev/null
+++ b/tools/arch/powerpc/include/uapi/asm/mman.h
@@ -0,0 +1,15 @@
1#ifndef TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_POWERPC_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800
4#define MAP_EXECUTABLE 0x1000
5#define MAP_GROWSDOWN 0x0100
6#define MAP_HUGETLB 0x40000
7#define MAP_LOCKED 0x80
8#define MAP_NONBLOCK 0x10000
9#define MAP_NORESERVE 0x40
10#define MAP_POPULATE 0x8000
11#define MAP_STACK 0x20000
12#include <uapi/asm-generic/mman-common.h>
13/* MAP_32BIT is undefined on powerpc, fix it for perf */
14#define MAP_32BIT 0
15#endif
diff --git a/tools/arch/powerpc/include/uapi/asm/perf_regs.h b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..6a93209748a1
--- /dev/null
+++ b/tools/arch/powerpc/include/uapi/asm/perf_regs.h
@@ -0,0 +1,50 @@
1#ifndef _UAPI_ASM_POWERPC_PERF_REGS_H
2#define _UAPI_ASM_POWERPC_PERF_REGS_H
3
4enum perf_event_powerpc_regs {
5 PERF_REG_POWERPC_R0,
6 PERF_REG_POWERPC_R1,
7 PERF_REG_POWERPC_R2,
8 PERF_REG_POWERPC_R3,
9 PERF_REG_POWERPC_R4,
10 PERF_REG_POWERPC_R5,
11 PERF_REG_POWERPC_R6,
12 PERF_REG_POWERPC_R7,
13 PERF_REG_POWERPC_R8,
14 PERF_REG_POWERPC_R9,
15 PERF_REG_POWERPC_R10,
16 PERF_REG_POWERPC_R11,
17 PERF_REG_POWERPC_R12,
18 PERF_REG_POWERPC_R13,
19 PERF_REG_POWERPC_R14,
20 PERF_REG_POWERPC_R15,
21 PERF_REG_POWERPC_R16,
22 PERF_REG_POWERPC_R17,
23 PERF_REG_POWERPC_R18,
24 PERF_REG_POWERPC_R19,
25 PERF_REG_POWERPC_R20,
26 PERF_REG_POWERPC_R21,
27 PERF_REG_POWERPC_R22,
28 PERF_REG_POWERPC_R23,
29 PERF_REG_POWERPC_R24,
30 PERF_REG_POWERPC_R25,
31 PERF_REG_POWERPC_R26,
32 PERF_REG_POWERPC_R27,
33 PERF_REG_POWERPC_R28,
34 PERF_REG_POWERPC_R29,
35 PERF_REG_POWERPC_R30,
36 PERF_REG_POWERPC_R31,
37 PERF_REG_POWERPC_NIP,
38 PERF_REG_POWERPC_MSR,
39 PERF_REG_POWERPC_ORIG_R3,
40 PERF_REG_POWERPC_CTR,
41 PERF_REG_POWERPC_LINK,
42 PERF_REG_POWERPC_XER,
43 PERF_REG_POWERPC_CCR,
44 PERF_REG_POWERPC_SOFTE,
45 PERF_REG_POWERPC_TRAP,
46 PERF_REG_POWERPC_DAR,
47 PERF_REG_POWERPC_DSISR,
48 PERF_REG_POWERPC_MAX,
49};
50#endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
diff --git a/tools/arch/s390/include/uapi/asm/bitsperlong.h b/tools/arch/s390/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..e351ea2ad43e
--- /dev/null
+++ b/tools/arch/s390/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,12 @@
1#ifndef __ASM_S390_BITSPERLONG_H
2#define __ASM_S390_BITSPERLONG_H
3
4#ifndef __s390x__
5#define __BITS_PER_LONG 32
6#else
7#define __BITS_PER_LONG 64
8#endif
9
10#include <asm-generic/bitsperlong.h>
11
12#endif /* __ASM_S390_BITSPERLONG_H */
diff --git a/tools/arch/s390/include/uapi/asm/kvm.h b/tools/arch/s390/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..a2ffec4139ad
--- /dev/null
+++ b/tools/arch/s390/include/uapi/asm/kvm.h
@@ -0,0 +1,233 @@
1#ifndef __LINUX_KVM_S390_H
2#define __LINUX_KVM_S390_H
3/*
4 * KVM s390 specific structures and definitions
5 *
6 * Copyright IBM Corp. 2008
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License (version 2 only)
10 * as published by the Free Software Foundation.
11 *
12 * Author(s): Carsten Otte <cotte@de.ibm.com>
13 * Christian Borntraeger <borntraeger@de.ibm.com>
14 */
15#include <linux/types.h>
16
17#define __KVM_S390
18#define __KVM_HAVE_GUEST_DEBUG
19
20/* Device control API: s390-specific devices */
21#define KVM_DEV_FLIC_GET_ALL_IRQS 1
22#define KVM_DEV_FLIC_ENQUEUE 2
23#define KVM_DEV_FLIC_CLEAR_IRQS 3
24#define KVM_DEV_FLIC_APF_ENABLE 4
25#define KVM_DEV_FLIC_APF_DISABLE_WAIT 5
26#define KVM_DEV_FLIC_ADAPTER_REGISTER 6
27#define KVM_DEV_FLIC_ADAPTER_MODIFY 7
28#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
29/*
30 * We can have up to 4*64k pending subchannels + 8 adapter interrupts,
31 * as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
32 * There are also sclp and machine checks. This gives us
33 * sizeof(kvm_s390_irq)*(4*65536+8+64*64+1+1) = 72 * 266250 = 19170000
34 * Lets round up to 8192 pages.
35 */
36#define KVM_S390_MAX_FLOAT_IRQS 266250
37#define KVM_S390_FLIC_MAX_BUFFER 0x2000000
38
39struct kvm_s390_io_adapter {
40 __u32 id;
41 __u8 isc;
42 __u8 maskable;
43 __u8 swap;
44 __u8 pad;
45};
46
47#define KVM_S390_IO_ADAPTER_MASK 1
48#define KVM_S390_IO_ADAPTER_MAP 2
49#define KVM_S390_IO_ADAPTER_UNMAP 3
50
51struct kvm_s390_io_adapter_req {
52 __u32 id;
53 __u8 type;
54 __u8 mask;
55 __u16 pad0;
56 __u64 addr;
57};
58
59/* kvm attr_group on vm fd */
60#define KVM_S390_VM_MEM_CTRL 0
61#define KVM_S390_VM_TOD 1
62#define KVM_S390_VM_CRYPTO 2
63#define KVM_S390_VM_CPU_MODEL 3
64
65/* kvm attributes for mem_ctrl */
66#define KVM_S390_VM_MEM_ENABLE_CMMA 0
67#define KVM_S390_VM_MEM_CLR_CMMA 1
68#define KVM_S390_VM_MEM_LIMIT_SIZE 2
69
70#define KVM_S390_NO_MEM_LIMIT U64_MAX
71
72/* kvm attributes for KVM_S390_VM_TOD */
73#define KVM_S390_VM_TOD_LOW 0
74#define KVM_S390_VM_TOD_HIGH 1
75
76/* kvm attributes for KVM_S390_VM_CPU_MODEL */
77/* processor related attributes are r/w */
78#define KVM_S390_VM_CPU_PROCESSOR 0
79struct kvm_s390_vm_cpu_processor {
80 __u64 cpuid;
81 __u16 ibc;
82 __u8 pad[6];
83 __u64 fac_list[256];
84};
85
86/* machine related attributes are r/o */
87#define KVM_S390_VM_CPU_MACHINE 1
88struct kvm_s390_vm_cpu_machine {
89 __u64 cpuid;
90 __u32 ibc;
91 __u8 pad[4];
92 __u64 fac_mask[256];
93 __u64 fac_list[256];
94};
95
96#define KVM_S390_VM_CPU_PROCESSOR_FEAT 2
97#define KVM_S390_VM_CPU_MACHINE_FEAT 3
98
99#define KVM_S390_VM_CPU_FEAT_NR_BITS 1024
100#define KVM_S390_VM_CPU_FEAT_ESOP 0
101#define KVM_S390_VM_CPU_FEAT_SIEF2 1
102#define KVM_S390_VM_CPU_FEAT_64BSCAO 2
103#define KVM_S390_VM_CPU_FEAT_SIIF 3
104#define KVM_S390_VM_CPU_FEAT_GPERE 4
105#define KVM_S390_VM_CPU_FEAT_GSLS 5
106#define KVM_S390_VM_CPU_FEAT_IB 6
107#define KVM_S390_VM_CPU_FEAT_CEI 7
108#define KVM_S390_VM_CPU_FEAT_IBS 8
109#define KVM_S390_VM_CPU_FEAT_SKEY 9
110#define KVM_S390_VM_CPU_FEAT_CMMA 10
111#define KVM_S390_VM_CPU_FEAT_PFMFI 11
112#define KVM_S390_VM_CPU_FEAT_SIGPIF 12
113struct kvm_s390_vm_cpu_feat {
114 __u64 feat[16];
115};
116
117#define KVM_S390_VM_CPU_PROCESSOR_SUBFUNC 4
118#define KVM_S390_VM_CPU_MACHINE_SUBFUNC 5
119/* for "test bit" instructions MSB 0 bit ordering, for "query" raw blocks */
120struct kvm_s390_vm_cpu_subfunc {
121 __u8 plo[32]; /* always */
122 __u8 ptff[16]; /* with TOD-clock steering */
123 __u8 kmac[16]; /* with MSA */
124 __u8 kmc[16]; /* with MSA */
125 __u8 km[16]; /* with MSA */
126 __u8 kimd[16]; /* with MSA */
127 __u8 klmd[16]; /* with MSA */
128 __u8 pckmo[16]; /* with MSA3 */
129 __u8 kmctr[16]; /* with MSA4 */
130 __u8 kmf[16]; /* with MSA4 */
131 __u8 kmo[16]; /* with MSA4 */
132 __u8 pcc[16]; /* with MSA4 */
133 __u8 ppno[16]; /* with MSA5 */
134 __u8 reserved[1824];
135};
136
137/* kvm attributes for crypto */
138#define KVM_S390_VM_CRYPTO_ENABLE_AES_KW 0
139#define KVM_S390_VM_CRYPTO_ENABLE_DEA_KW 1
140#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2
141#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3
142
143/* for KVM_GET_REGS and KVM_SET_REGS */
144struct kvm_regs {
145 /* general purpose regs for s390 */
146 __u64 gprs[16];
147};
148
149/* for KVM_GET_SREGS and KVM_SET_SREGS */
150struct kvm_sregs {
151 __u32 acrs[16];
152 __u64 crs[16];
153};
154
155/* for KVM_GET_FPU and KVM_SET_FPU */
156struct kvm_fpu {
157 __u32 fpc;
158 __u64 fprs[16];
159};
160
161#define KVM_GUESTDBG_USE_HW_BP 0x00010000
162
163#define KVM_HW_BP 1
164#define KVM_HW_WP_WRITE 2
165#define KVM_SINGLESTEP 4
166
167struct kvm_debug_exit_arch {
168 __u64 addr;
169 __u8 type;
170 __u8 pad[7]; /* Should be set to 0 */
171};
172
173struct kvm_hw_breakpoint {
174 __u64 addr;
175 __u64 phys_addr;
176 __u64 len;
177 __u8 type;
178 __u8 pad[7]; /* Should be set to 0 */
179};
180
181/* for KVM_SET_GUEST_DEBUG */
182struct kvm_guest_debug_arch {
183 __u32 nr_hw_bp;
184 __u32 pad; /* Should be set to 0 */
185 struct kvm_hw_breakpoint __user *hw_bp;
186};
187
188/* for KVM_SYNC_PFAULT and KVM_REG_S390_PFTOKEN */
189#define KVM_S390_PFAULT_TOKEN_INVALID 0xffffffffffffffffULL
190
191#define KVM_SYNC_PREFIX (1UL << 0)
192#define KVM_SYNC_GPRS (1UL << 1)
193#define KVM_SYNC_ACRS (1UL << 2)
194#define KVM_SYNC_CRS (1UL << 3)
195#define KVM_SYNC_ARCH0 (1UL << 4)
196#define KVM_SYNC_PFAULT (1UL << 5)
197#define KVM_SYNC_VRS (1UL << 6)
198#define KVM_SYNC_RICCB (1UL << 7)
199#define KVM_SYNC_FPRS (1UL << 8)
200/* definition of registers in kvm_run */
201struct kvm_sync_regs {
202 __u64 prefix; /* prefix register */
203 __u64 gprs[16]; /* general purpose registers */
204 __u32 acrs[16]; /* access registers */
205 __u64 crs[16]; /* control registers */
206 __u64 todpr; /* tod programmable register [ARCH0] */
207 __u64 cputm; /* cpu timer [ARCH0] */
208 __u64 ckc; /* clock comparator [ARCH0] */
209 __u64 pp; /* program parameter [ARCH0] */
210 __u64 gbea; /* guest breaking-event address [ARCH0] */
211 __u64 pft; /* pfault token [PFAULT] */
212 __u64 pfs; /* pfault select [PFAULT] */
213 __u64 pfc; /* pfault compare [PFAULT] */
214 union {
215 __u64 vrs[32][2]; /* vector registers (KVM_SYNC_VRS) */
216 __u64 fprs[16]; /* fp registers (KVM_SYNC_FPRS) */
217 };
218 __u8 reserved[512]; /* for future vector expansion */
219 __u32 fpc; /* valid on KVM_SYNC_VRS or KVM_SYNC_FPRS */
220 __u8 padding[52]; /* riccb needs to be 64byte aligned */
221 __u8 riccb[64]; /* runtime instrumentation controls block */
222};
223
224#define KVM_REG_S390_TODPR (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
225#define KVM_REG_S390_EPOCHDIFF (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x2)
226#define KVM_REG_S390_CPU_TIMER (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x3)
227#define KVM_REG_S390_CLOCK_COMP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x4)
228#define KVM_REG_S390_PFTOKEN (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x5)
229#define KVM_REG_S390_PFCOMPARE (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x6)
230#define KVM_REG_S390_PFSELECT (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x7)
231#define KVM_REG_S390_PP (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x8)
232#define KVM_REG_S390_GBEA (KVM_REG_S390 | KVM_REG_SIZE_U64 | 0x9)
233#endif
diff --git a/tools/arch/s390/include/uapi/asm/kvm_perf.h b/tools/arch/s390/include/uapi/asm/kvm_perf.h
new file mode 100644
index 000000000000..397282727e21
--- /dev/null
+++ b/tools/arch/s390/include/uapi/asm/kvm_perf.h
@@ -0,0 +1,25 @@
1/*
2 * Definitions for perf-kvm on s390
3 *
4 * Copyright 2014 IBM Corp.
5 * Author(s): Alexander Yarygin <yarygin@linux.vnet.ibm.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License (version 2 only)
9 * as published by the Free Software Foundation.
10 */
11
12#ifndef __LINUX_KVM_PERF_S390_H
13#define __LINUX_KVM_PERF_S390_H
14
15#include <asm/sie.h>
16
17#define DECODE_STR_LEN 40
18
19#define VCPU_ID "id"
20
21#define KVM_ENTRY_TRACE "kvm:kvm_s390_sie_enter"
22#define KVM_EXIT_TRACE "kvm:kvm_s390_sie_exit"
23#define KVM_EXIT_REASON "icptcode"
24
25#endif
diff --git a/tools/arch/s390/include/uapi/asm/mman.h b/tools/arch/s390/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..b03dea9e1f56
--- /dev/null
+++ b/tools/arch/s390/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_S390_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on s390, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/s390/include/uapi/asm/sie.h b/tools/arch/s390/include/uapi/asm/sie.h
new file mode 100644
index 000000000000..3ac634368939
--- /dev/null
+++ b/tools/arch/s390/include/uapi/asm/sie.h
@@ -0,0 +1,251 @@
1#ifndef _UAPI_ASM_S390_SIE_H
2#define _UAPI_ASM_S390_SIE_H
3
4#define diagnose_codes \
5 { 0x10, "DIAG (0x10) release pages" }, \
6 { 0x44, "DIAG (0x44) time slice end" }, \
7 { 0x9c, "DIAG (0x9c) time slice end directed" }, \
8 { 0x204, "DIAG (0x204) logical-cpu utilization" }, \
9 { 0x258, "DIAG (0x258) page-reference services" }, \
10 { 0x288, "DIAG (0x288) watchdog functions" }, \
11 { 0x308, "DIAG (0x308) ipl functions" }, \
12 { 0x500, "DIAG (0x500) KVM virtio functions" }, \
13 { 0x501, "DIAG (0x501) KVM breakpoint" }
14
15#define sigp_order_codes \
16 { 0x01, "SIGP sense" }, \
17 { 0x02, "SIGP external call" }, \
18 { 0x03, "SIGP emergency signal" }, \
19 { 0x04, "SIGP start" }, \
20 { 0x05, "SIGP stop" }, \
21 { 0x06, "SIGP restart" }, \
22 { 0x09, "SIGP stop and store status" }, \
23 { 0x0b, "SIGP initial cpu reset" }, \
24 { 0x0c, "SIGP cpu reset" }, \
25 { 0x0d, "SIGP set prefix" }, \
26 { 0x0e, "SIGP store status at address" }, \
27 { 0x12, "SIGP set architecture" }, \
28 { 0x13, "SIGP conditional emergency signal" }, \
29 { 0x15, "SIGP sense running" }, \
30 { 0x16, "SIGP set multithreading"}, \
31 { 0x17, "SIGP store additional status ait address"}
32
33#define icpt_prog_codes \
34 { 0x0001, "Prog Operation" }, \
35 { 0x0002, "Prog Privileged Operation" }, \
36 { 0x0003, "Prog Execute" }, \
37 { 0x0004, "Prog Protection" }, \
38 { 0x0005, "Prog Addressing" }, \
39 { 0x0006, "Prog Specification" }, \
40 { 0x0007, "Prog Data" }, \
41 { 0x0008, "Prog Fixedpoint overflow" }, \
42 { 0x0009, "Prog Fixedpoint divide" }, \
43 { 0x000A, "Prog Decimal overflow" }, \
44 { 0x000B, "Prog Decimal divide" }, \
45 { 0x000C, "Prog HFP exponent overflow" }, \
46 { 0x000D, "Prog HFP exponent underflow" }, \
47 { 0x000E, "Prog HFP significance" }, \
48 { 0x000F, "Prog HFP divide" }, \
49 { 0x0010, "Prog Segment translation" }, \
50 { 0x0011, "Prog Page translation" }, \
51 { 0x0012, "Prog Translation specification" }, \
52 { 0x0013, "Prog Special operation" }, \
53 { 0x0015, "Prog Operand" }, \
54 { 0x0016, "Prog Trace table" }, \
55 { 0x0017, "Prog ASNtranslation specification" }, \
56 { 0x001C, "Prog Spaceswitch event" }, \
57 { 0x001D, "Prog HFP square root" }, \
58 { 0x001F, "Prog PCtranslation specification" }, \
59 { 0x0020, "Prog AFX translation" }, \
60 { 0x0021, "Prog ASX translation" }, \
61 { 0x0022, "Prog LX translation" }, \
62 { 0x0023, "Prog EX translation" }, \
63 { 0x0024, "Prog Primary authority" }, \
64 { 0x0025, "Prog Secondary authority" }, \
65 { 0x0026, "Prog LFXtranslation exception" }, \
66 { 0x0027, "Prog LSXtranslation exception" }, \
67 { 0x0028, "Prog ALET specification" }, \
68 { 0x0029, "Prog ALEN translation" }, \
69 { 0x002A, "Prog ALE sequence" }, \
70 { 0x002B, "Prog ASTE validity" }, \
71 { 0x002C, "Prog ASTE sequence" }, \
72 { 0x002D, "Prog Extended authority" }, \
73 { 0x002E, "Prog LSTE sequence" }, \
74 { 0x002F, "Prog ASTE instance" }, \
75 { 0x0030, "Prog Stack full" }, \
76 { 0x0031, "Prog Stack empty" }, \
77 { 0x0032, "Prog Stack specification" }, \
78 { 0x0033, "Prog Stack type" }, \
79 { 0x0034, "Prog Stack operation" }, \
80 { 0x0039, "Prog Region first translation" }, \
81 { 0x003A, "Prog Region second translation" }, \
82 { 0x003B, "Prog Region third translation" }, \
83 { 0x0040, "Prog Monitor event" }, \
84 { 0x0080, "Prog PER event" }, \
85 { 0x0119, "Prog Crypto operation" }
86
87#define exit_code_ipa0(ipa0, opcode, mnemonic) \
88 { (ipa0 << 8 | opcode), #ipa0 " " mnemonic }
89#define exit_code(opcode, mnemonic) \
90 { opcode, mnemonic }
91
92#define icpt_insn_codes \
93 exit_code_ipa0(0x01, 0x01, "PR"), \
94 exit_code_ipa0(0x01, 0x04, "PTFF"), \
95 exit_code_ipa0(0x01, 0x07, "SCKPF"), \
96 exit_code_ipa0(0xAA, 0x00, "RINEXT"), \
97 exit_code_ipa0(0xAA, 0x01, "RION"), \
98 exit_code_ipa0(0xAA, 0x02, "TRIC"), \
99 exit_code_ipa0(0xAA, 0x03, "RIOFF"), \
100 exit_code_ipa0(0xAA, 0x04, "RIEMIT"), \
101 exit_code_ipa0(0xB2, 0x02, "STIDP"), \
102 exit_code_ipa0(0xB2, 0x04, "SCK"), \
103 exit_code_ipa0(0xB2, 0x05, "STCK"), \
104 exit_code_ipa0(0xB2, 0x06, "SCKC"), \
105 exit_code_ipa0(0xB2, 0x07, "STCKC"), \
106 exit_code_ipa0(0xB2, 0x08, "SPT"), \
107 exit_code_ipa0(0xB2, 0x09, "STPT"), \
108 exit_code_ipa0(0xB2, 0x0d, "PTLB"), \
109 exit_code_ipa0(0xB2, 0x10, "SPX"), \
110 exit_code_ipa0(0xB2, 0x11, "STPX"), \
111 exit_code_ipa0(0xB2, 0x12, "STAP"), \
112 exit_code_ipa0(0xB2, 0x14, "SIE"), \
113 exit_code_ipa0(0xB2, 0x16, "SETR"), \
114 exit_code_ipa0(0xB2, 0x17, "STETR"), \
115 exit_code_ipa0(0xB2, 0x18, "PC"), \
116 exit_code_ipa0(0xB2, 0x20, "SERVC"), \
117 exit_code_ipa0(0xB2, 0x21, "IPTE"), \
118 exit_code_ipa0(0xB2, 0x28, "PT"), \
119 exit_code_ipa0(0xB2, 0x29, "ISKE"), \
120 exit_code_ipa0(0xB2, 0x2a, "RRBE"), \
121 exit_code_ipa0(0xB2, 0x2b, "SSKE"), \
122 exit_code_ipa0(0xB2, 0x2c, "TB"), \
123 exit_code_ipa0(0xB2, 0x2e, "PGIN"), \
124 exit_code_ipa0(0xB2, 0x2f, "PGOUT"), \
125 exit_code_ipa0(0xB2, 0x30, "CSCH"), \
126 exit_code_ipa0(0xB2, 0x31, "HSCH"), \
127 exit_code_ipa0(0xB2, 0x32, "MSCH"), \
128 exit_code_ipa0(0xB2, 0x33, "SSCH"), \
129 exit_code_ipa0(0xB2, 0x34, "STSCH"), \
130 exit_code_ipa0(0xB2, 0x35, "TSCH"), \
131 exit_code_ipa0(0xB2, 0x36, "TPI"), \
132 exit_code_ipa0(0xB2, 0x37, "SAL"), \
133 exit_code_ipa0(0xB2, 0x38, "RSCH"), \
134 exit_code_ipa0(0xB2, 0x39, "STCRW"), \
135 exit_code_ipa0(0xB2, 0x3a, "STCPS"), \
136 exit_code_ipa0(0xB2, 0x3b, "RCHP"), \
137 exit_code_ipa0(0xB2, 0x3c, "SCHM"), \
138 exit_code_ipa0(0xB2, 0x40, "BAKR"), \
139 exit_code_ipa0(0xB2, 0x48, "PALB"), \
140 exit_code_ipa0(0xB2, 0x4c, "TAR"), \
141 exit_code_ipa0(0xB2, 0x50, "CSP"), \
142 exit_code_ipa0(0xB2, 0x54, "MVPG"), \
143 exit_code_ipa0(0xB2, 0x56, "STHYI"), \
144 exit_code_ipa0(0xB2, 0x58, "BSG"), \
145 exit_code_ipa0(0xB2, 0x5a, "BSA"), \
146 exit_code_ipa0(0xB2, 0x5f, "CHSC"), \
147 exit_code_ipa0(0xB2, 0x74, "SIGA"), \
148 exit_code_ipa0(0xB2, 0x76, "XSCH"), \
149 exit_code_ipa0(0xB2, 0x78, "STCKE"), \
150 exit_code_ipa0(0xB2, 0x7c, "STCKF"), \
151 exit_code_ipa0(0xB2, 0x7d, "STSI"), \
152 exit_code_ipa0(0xB2, 0xb0, "STFLE"), \
153 exit_code_ipa0(0xB2, 0xb1, "STFL"), \
154 exit_code_ipa0(0xB2, 0xb2, "LPSWE"), \
155 exit_code_ipa0(0xB2, 0xf8, "TEND"), \
156 exit_code_ipa0(0xB2, 0xfc, "TABORT"), \
157 exit_code_ipa0(0xB9, 0x1e, "KMAC"), \
158 exit_code_ipa0(0xB9, 0x28, "PCKMO"), \
159 exit_code_ipa0(0xB9, 0x2a, "KMF"), \
160 exit_code_ipa0(0xB9, 0x2b, "KMO"), \
161 exit_code_ipa0(0xB9, 0x2d, "KMCTR"), \
162 exit_code_ipa0(0xB9, 0x2e, "KM"), \
163 exit_code_ipa0(0xB9, 0x2f, "KMC"), \
164 exit_code_ipa0(0xB9, 0x3e, "KIMD"), \
165 exit_code_ipa0(0xB9, 0x3f, "KLMD"), \
166 exit_code_ipa0(0xB9, 0x8a, "CSPG"), \
167 exit_code_ipa0(0xB9, 0x8d, "EPSW"), \
168 exit_code_ipa0(0xB9, 0x8e, "IDTE"), \
169 exit_code_ipa0(0xB9, 0x8f, "CRDTE"), \
170 exit_code_ipa0(0xB9, 0x9c, "EQBS"), \
171 exit_code_ipa0(0xB9, 0xa2, "PTF"), \
172 exit_code_ipa0(0xB9, 0xab, "ESSA"), \
173 exit_code_ipa0(0xB9, 0xae, "RRBM"), \
174 exit_code_ipa0(0xB9, 0xaf, "PFMF"), \
175 exit_code_ipa0(0xE3, 0x03, "LRAG"), \
176 exit_code_ipa0(0xE3, 0x13, "LRAY"), \
177 exit_code_ipa0(0xE3, 0x25, "NTSTG"), \
178 exit_code_ipa0(0xE5, 0x00, "LASP"), \
179 exit_code_ipa0(0xE5, 0x01, "TPROT"), \
180 exit_code_ipa0(0xE5, 0x60, "TBEGIN"), \
181 exit_code_ipa0(0xE5, 0x61, "TBEGINC"), \
182 exit_code_ipa0(0xEB, 0x25, "STCTG"), \
183 exit_code_ipa0(0xEB, 0x2f, "LCTLG"), \
184 exit_code_ipa0(0xEB, 0x60, "LRIC"), \
185 exit_code_ipa0(0xEB, 0x61, "STRIC"), \
186 exit_code_ipa0(0xEB, 0x62, "MRIC"), \
187 exit_code_ipa0(0xEB, 0x8a, "SQBS"), \
188 exit_code_ipa0(0xC8, 0x01, "ECTG"), \
189 exit_code(0x0a, "SVC"), \
190 exit_code(0x80, "SSM"), \
191 exit_code(0x82, "LPSW"), \
192 exit_code(0x83, "DIAG"), \
193 exit_code(0xae, "SIGP"), \
194 exit_code(0xac, "STNSM"), \
195 exit_code(0xad, "STOSM"), \
196 exit_code(0xb1, "LRA"), \
197 exit_code(0xb6, "STCTL"), \
198 exit_code(0xb7, "LCTL"), \
199 exit_code(0xee, "PLO")
200
201#define sie_intercept_code \
202 { 0x00, "Host interruption" }, \
203 { 0x04, "Instruction" }, \
204 { 0x08, "Program interruption" }, \
205 { 0x0c, "Instruction and program interruption" }, \
206 { 0x10, "External request" }, \
207 { 0x14, "External interruption" }, \
208 { 0x18, "I/O request" }, \
209 { 0x1c, "Wait state" }, \
210 { 0x20, "Validity" }, \
211 { 0x28, "Stop request" }, \
212 { 0x2c, "Operation exception" }, \
213 { 0x38, "Partial-execution" }, \
214 { 0x3c, "I/O interruption" }, \
215 { 0x40, "I/O instruction" }, \
216 { 0x48, "Timing subset" }
217
218/*
219 * This is the simple interceptable instructions decoder.
220 *
221 * It will be used as userspace interface and it can be used in places
222 * that does not allow to use general decoder functions,
223 * such as trace events declarations.
224 *
225 * Some userspace tools may want to parse this code
226 * and would be confused by switch(), if() and other statements,
227 * but they can understand conditional operator.
228 */
229#define INSN_DECODE_IPA0(ipa0, insn, rshift, mask) \
230 (insn >> 56) == (ipa0) ? \
231 ((ipa0 << 8) | ((insn >> rshift) & mask)) :
232
233#define INSN_DECODE(insn) (insn >> 56)
234
235/*
236 * The macro icpt_insn_decoder() takes an intercepted instruction
237 * and returns a key, which can be used to find a mnemonic name
238 * of the instruction in the icpt_insn_codes table.
239 */
240#define icpt_insn_decoder(insn) ( \
241 INSN_DECODE_IPA0(0x01, insn, 48, 0xff) \
242 INSN_DECODE_IPA0(0xaa, insn, 48, 0x0f) \
243 INSN_DECODE_IPA0(0xb2, insn, 48, 0xff) \
244 INSN_DECODE_IPA0(0xb9, insn, 48, 0xff) \
245 INSN_DECODE_IPA0(0xe3, insn, 48, 0xff) \
246 INSN_DECODE_IPA0(0xe5, insn, 48, 0xff) \
247 INSN_DECODE_IPA0(0xeb, insn, 16, 0xff) \
248 INSN_DECODE_IPA0(0xc8, insn, 48, 0x0f) \
249 INSN_DECODE(insn))
250
251#endif /* _UAPI_ASM_S390_SIE_H */
diff --git a/tools/arch/score/include/uapi/asm/bitsperlong.h b/tools/arch/score/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..86ff337aa459
--- /dev/null
+++ b/tools/arch/score/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,6 @@
1#ifndef _ASM_SCORE_BITSPERLONG_H
2#define _ASM_SCORE_BITSPERLONG_H
3
4#include <asm-generic/bitsperlong.h>
5
6#endif /* _ASM_SCORE_BITSPERLONG_H */
diff --git a/tools/arch/score/include/uapi/asm/mman.h b/tools/arch/score/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..2f8fb89944fd
--- /dev/null
+++ b/tools/arch/score/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SCORE_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on score, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/sh/include/uapi/asm/mman.h b/tools/arch/sh/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..26504f6f060e
--- /dev/null
+++ b/tools/arch/sh/include/uapi/asm/mman.h
@@ -0,0 +1,6 @@
1#ifndef TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SH_UAPI_ASM_MMAN_FIX_H
3#include <uapi/asm-generic/mman.h>
4/* MAP_32BIT is undefined on sh, fix it for perf */
5#define MAP_32BIT 0
6#endif
diff --git a/tools/arch/sparc/include/uapi/asm/bitsperlong.h b/tools/arch/sparc/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..b62dd907d7c3
--- /dev/null
+++ b/tools/arch/sparc/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,12 @@
1#ifndef __ASM_ALPHA_BITSPERLONG_H
2#define __ASM_ALPHA_BITSPERLONG_H
3
4#if defined(__sparc__) && defined(__arch64__)
5#define __BITS_PER_LONG 64
6#else
7#define __BITS_PER_LONG 32
8#endif
9
10#include <asm-generic/bitsperlong.h>
11
12#endif /* __ASM_ALPHA_BITSPERLONG_H */
diff --git a/tools/arch/sparc/include/uapi/asm/mman.h b/tools/arch/sparc/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..8640525de991
--- /dev/null
+++ b/tools/arch/sparc/include/uapi/asm/mman.h
@@ -0,0 +1,15 @@
1#ifndef TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_SPARC_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800
4#define MAP_EXECUTABLE 0x1000
5#define MAP_GROWSDOWN 0x0200
6#define MAP_HUGETLB 0x40000
7#define MAP_LOCKED 0x100
8#define MAP_NONBLOCK 0x10000
9#define MAP_NORESERVE 0x40
10#define MAP_POPULATE 0x8000
11#define MAP_STACK 0x20000
12#include <uapi/asm-generic/mman-common.h>
13/* MAP_32BIT is undefined on sparc, fix it for perf */
14#define MAP_32BIT 0
15#endif
diff --git a/tools/arch/tile/include/uapi/asm/bitsperlong.h b/tools/arch/tile/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..58c771f2af2f
--- /dev/null
+++ b/tools/arch/tile/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15#ifndef _ASM_TILE_BITSPERLONG_H
16#define _ASM_TILE_BITSPERLONG_H
17
18#ifdef __LP64__
19# define __BITS_PER_LONG 64
20#else
21# define __BITS_PER_LONG 32
22#endif
23
24#include <asm-generic/bitsperlong.h>
25
26#endif /* _ASM_TILE_BITSPERLONG_H */
diff --git a/tools/arch/tile/include/uapi/asm/mman.h b/tools/arch/tile/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..7116c4b928b3
--- /dev/null
+++ b/tools/arch/tile/include/uapi/asm/mman.h
@@ -0,0 +1,15 @@
1#ifndef TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_TILE_UAPI_ASM_MMAN_FIX_H
3#define MAP_DENYWRITE 0x0800
4#define MAP_EXECUTABLE 0x1000
5#define MAP_GROWSDOWN 0x0100
6#define MAP_HUGETLB 0x4000
7#define MAP_LOCKED 0x0200
8#define MAP_NONBLOCK 0x0080
9#define MAP_NORESERVE 0x0400
10#define MAP_POPULATE 0x0040
11#define MAP_STACK MAP_GROWSDOWN
12#include <uapi/asm-generic/mman-common.h>
13/* MAP_32BIT is undefined on tile, fix it for perf */
14#define MAP_32BIT 0
15#endif
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
new file mode 100644
index 000000000000..1188bc849ee3
--- /dev/null
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -0,0 +1,312 @@
1#ifndef _ASM_X86_CPUFEATURES_H
2#define _ASM_X86_CPUFEATURES_H
3
4#ifndef _ASM_X86_REQUIRED_FEATURES_H
5#include <asm/required-features.h>
6#endif
7
8#ifndef _ASM_X86_DISABLED_FEATURES_H
9#include <asm/disabled-features.h>
10#endif
11
12/*
13 * Defines x86 CPU feature bits
14 */
15#define NCAPINTS 18 /* N 32-bit words worth of info */
16#define NBUGINTS 1 /* N 32-bit bug flags */
17
18/*
19 * Note: If the comment begins with a quoted string, that string is used
20 * in /proc/cpuinfo instead of the macro name. If the string is "",
21 * this feature bit is not displayed in /proc/cpuinfo at all.
22 */
23
24/* Intel-defined CPU features, CPUID level 0x00000001 (edx), word 0 */
25#define X86_FEATURE_FPU ( 0*32+ 0) /* Onboard FPU */
26#define X86_FEATURE_VME ( 0*32+ 1) /* Virtual Mode Extensions */
27#define X86_FEATURE_DE ( 0*32+ 2) /* Debugging Extensions */
28#define X86_FEATURE_PSE ( 0*32+ 3) /* Page Size Extensions */
29#define X86_FEATURE_TSC ( 0*32+ 4) /* Time Stamp Counter */
30#define X86_FEATURE_MSR ( 0*32+ 5) /* Model-Specific Registers */
31#define X86_FEATURE_PAE ( 0*32+ 6) /* Physical Address Extensions */
32#define X86_FEATURE_MCE ( 0*32+ 7) /* Machine Check Exception */
33#define X86_FEATURE_CX8 ( 0*32+ 8) /* CMPXCHG8 instruction */
34#define X86_FEATURE_APIC ( 0*32+ 9) /* Onboard APIC */
35#define X86_FEATURE_SEP ( 0*32+11) /* SYSENTER/SYSEXIT */
36#define X86_FEATURE_MTRR ( 0*32+12) /* Memory Type Range Registers */
37#define X86_FEATURE_PGE ( 0*32+13) /* Page Global Enable */
38#define X86_FEATURE_MCA ( 0*32+14) /* Machine Check Architecture */
39#define X86_FEATURE_CMOV ( 0*32+15) /* CMOV instructions */
40 /* (plus FCMOVcc, FCOMI with FPU) */
41#define X86_FEATURE_PAT ( 0*32+16) /* Page Attribute Table */
42#define X86_FEATURE_PSE36 ( 0*32+17) /* 36-bit PSEs */
43#define X86_FEATURE_PN ( 0*32+18) /* Processor serial number */
44#define X86_FEATURE_CLFLUSH ( 0*32+19) /* CLFLUSH instruction */
45#define X86_FEATURE_DS ( 0*32+21) /* "dts" Debug Store */
46#define X86_FEATURE_ACPI ( 0*32+22) /* ACPI via MSR */
47#define X86_FEATURE_MMX ( 0*32+23) /* Multimedia Extensions */
48#define X86_FEATURE_FXSR ( 0*32+24) /* FXSAVE/FXRSTOR, CR4.OSFXSR */
49#define X86_FEATURE_XMM ( 0*32+25) /* "sse" */
50#define X86_FEATURE_XMM2 ( 0*32+26) /* "sse2" */
51#define X86_FEATURE_SELFSNOOP ( 0*32+27) /* "ss" CPU self snoop */
52#define X86_FEATURE_HT ( 0*32+28) /* Hyper-Threading */
53#define X86_FEATURE_ACC ( 0*32+29) /* "tm" Automatic clock control */
54#define X86_FEATURE_IA64 ( 0*32+30) /* IA-64 processor */
55#define X86_FEATURE_PBE ( 0*32+31) /* Pending Break Enable */
56
57/* AMD-defined CPU features, CPUID level 0x80000001, word 1 */
58/* Don't duplicate feature flags which are redundant with Intel! */
59#define X86_FEATURE_SYSCALL ( 1*32+11) /* SYSCALL/SYSRET */
60#define X86_FEATURE_MP ( 1*32+19) /* MP Capable. */
61#define X86_FEATURE_NX ( 1*32+20) /* Execute Disable */
62#define X86_FEATURE_MMXEXT ( 1*32+22) /* AMD MMX extensions */
63#define X86_FEATURE_FXSR_OPT ( 1*32+25) /* FXSAVE/FXRSTOR optimizations */
64#define X86_FEATURE_GBPAGES ( 1*32+26) /* "pdpe1gb" GB pages */
65#define X86_FEATURE_RDTSCP ( 1*32+27) /* RDTSCP */
66#define X86_FEATURE_LM ( 1*32+29) /* Long Mode (x86-64) */
67#define X86_FEATURE_3DNOWEXT ( 1*32+30) /* AMD 3DNow! extensions */
68#define X86_FEATURE_3DNOW ( 1*32+31) /* 3DNow! */
69
70/* Transmeta-defined CPU features, CPUID level 0x80860001, word 2 */
71#define X86_FEATURE_RECOVERY ( 2*32+ 0) /* CPU in recovery mode */
72#define X86_FEATURE_LONGRUN ( 2*32+ 1) /* Longrun power control */
73#define X86_FEATURE_LRTI ( 2*32+ 3) /* LongRun table interface */
74
75/* Other features, Linux-defined mapping, word 3 */
76/* This range is used for feature bits which conflict or are synthesized */
77#define X86_FEATURE_CXMMX ( 3*32+ 0) /* Cyrix MMX extensions */
78#define X86_FEATURE_K6_MTRR ( 3*32+ 1) /* AMD K6 nonstandard MTRRs */
79#define X86_FEATURE_CYRIX_ARR ( 3*32+ 2) /* Cyrix ARRs (= MTRRs) */
80#define X86_FEATURE_CENTAUR_MCR ( 3*32+ 3) /* Centaur MCRs (= MTRRs) */
81/* cpu types for specific tunings: */
82#define X86_FEATURE_K8 ( 3*32+ 4) /* "" Opteron, Athlon64 */
83#define X86_FEATURE_K7 ( 3*32+ 5) /* "" Athlon */
84#define X86_FEATURE_P3 ( 3*32+ 6) /* "" P3 */
85#define X86_FEATURE_P4 ( 3*32+ 7) /* "" P4 */
86#define X86_FEATURE_CONSTANT_TSC ( 3*32+ 8) /* TSC ticks at a constant rate */
87#define X86_FEATURE_UP ( 3*32+ 9) /* smp kernel running on up */
88#define X86_FEATURE_ART ( 3*32+10) /* Platform has always running timer (ART) */
89#define X86_FEATURE_ARCH_PERFMON ( 3*32+11) /* Intel Architectural PerfMon */
90#define X86_FEATURE_PEBS ( 3*32+12) /* Precise-Event Based Sampling */
91#define X86_FEATURE_BTS ( 3*32+13) /* Branch Trace Store */
92#define X86_FEATURE_SYSCALL32 ( 3*32+14) /* "" syscall in ia32 userspace */
93#define X86_FEATURE_SYSENTER32 ( 3*32+15) /* "" sysenter in ia32 userspace */
94#define X86_FEATURE_REP_GOOD ( 3*32+16) /* rep microcode works well */
95#define X86_FEATURE_MFENCE_RDTSC ( 3*32+17) /* "" Mfence synchronizes RDTSC */
96#define X86_FEATURE_LFENCE_RDTSC ( 3*32+18) /* "" Lfence synchronizes RDTSC */
97#define X86_FEATURE_ACC_POWER ( 3*32+19) /* AMD Accumulated Power Mechanism */
98#define X86_FEATURE_NOPL ( 3*32+20) /* The NOPL (0F 1F) instructions */
99#define X86_FEATURE_ALWAYS ( 3*32+21) /* "" Always-present feature */
100#define X86_FEATURE_XTOPOLOGY ( 3*32+22) /* cpu topology enum extensions */
101#define X86_FEATURE_TSC_RELIABLE ( 3*32+23) /* TSC is known to be reliable */
102#define X86_FEATURE_NONSTOP_TSC ( 3*32+24) /* TSC does not stop in C states */
103/* free, was #define X86_FEATURE_CLFLUSH_MONITOR ( 3*32+25) * "" clflush reqd with monitor */
104#define X86_FEATURE_EXTD_APICID ( 3*32+26) /* has extended APICID (8 bits) */
105#define X86_FEATURE_AMD_DCM ( 3*32+27) /* multi-node processor */
106#define X86_FEATURE_APERFMPERF ( 3*32+28) /* APERFMPERF */
107#define X86_FEATURE_EAGER_FPU ( 3*32+29) /* "eagerfpu" Non lazy FPU restore */
108#define X86_FEATURE_NONSTOP_TSC_S3 ( 3*32+30) /* TSC doesn't stop in S3 state */
109
110/* Intel-defined CPU features, CPUID level 0x00000001 (ecx), word 4 */
111#define X86_FEATURE_XMM3 ( 4*32+ 0) /* "pni" SSE-3 */
112#define X86_FEATURE_PCLMULQDQ ( 4*32+ 1) /* PCLMULQDQ instruction */
113#define X86_FEATURE_DTES64 ( 4*32+ 2) /* 64-bit Debug Store */
114#define X86_FEATURE_MWAIT ( 4*32+ 3) /* "monitor" Monitor/Mwait support */
115#define X86_FEATURE_DSCPL ( 4*32+ 4) /* "ds_cpl" CPL Qual. Debug Store */
116#define X86_FEATURE_VMX ( 4*32+ 5) /* Hardware virtualization */
117#define X86_FEATURE_SMX ( 4*32+ 6) /* Safer mode */
118#define X86_FEATURE_EST ( 4*32+ 7) /* Enhanced SpeedStep */
119#define X86_FEATURE_TM2 ( 4*32+ 8) /* Thermal Monitor 2 */
120#define X86_FEATURE_SSSE3 ( 4*32+ 9) /* Supplemental SSE-3 */
121#define X86_FEATURE_CID ( 4*32+10) /* Context ID */
122#define X86_FEATURE_SDBG ( 4*32+11) /* Silicon Debug */
123#define X86_FEATURE_FMA ( 4*32+12) /* Fused multiply-add */
124#define X86_FEATURE_CX16 ( 4*32+13) /* CMPXCHG16B */
125#define X86_FEATURE_XTPR ( 4*32+14) /* Send Task Priority Messages */
126#define X86_FEATURE_PDCM ( 4*32+15) /* Performance Capabilities */
127#define X86_FEATURE_PCID ( 4*32+17) /* Process Context Identifiers */
128#define X86_FEATURE_DCA ( 4*32+18) /* Direct Cache Access */
129#define X86_FEATURE_XMM4_1 ( 4*32+19) /* "sse4_1" SSE-4.1 */
130#define X86_FEATURE_XMM4_2 ( 4*32+20) /* "sse4_2" SSE-4.2 */
131#define X86_FEATURE_X2APIC ( 4*32+21) /* x2APIC */
132#define X86_FEATURE_MOVBE ( 4*32+22) /* MOVBE instruction */
133#define X86_FEATURE_POPCNT ( 4*32+23) /* POPCNT instruction */
134#define X86_FEATURE_TSC_DEADLINE_TIMER ( 4*32+24) /* Tsc deadline timer */
135#define X86_FEATURE_AES ( 4*32+25) /* AES instructions */
136#define X86_FEATURE_XSAVE ( 4*32+26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
137#define X86_FEATURE_OSXSAVE ( 4*32+27) /* "" XSAVE enabled in the OS */
138#define X86_FEATURE_AVX ( 4*32+28) /* Advanced Vector Extensions */
139#define X86_FEATURE_F16C ( 4*32+29) /* 16-bit fp conversions */
140#define X86_FEATURE_RDRAND ( 4*32+30) /* The RDRAND instruction */
141#define X86_FEATURE_HYPERVISOR ( 4*32+31) /* Running on a hypervisor */
142
143/* VIA/Cyrix/Centaur-defined CPU features, CPUID level 0xC0000001, word 5 */
144#define X86_FEATURE_XSTORE ( 5*32+ 2) /* "rng" RNG present (xstore) */
145#define X86_FEATURE_XSTORE_EN ( 5*32+ 3) /* "rng_en" RNG enabled */
146#define X86_FEATURE_XCRYPT ( 5*32+ 6) /* "ace" on-CPU crypto (xcrypt) */
147#define X86_FEATURE_XCRYPT_EN ( 5*32+ 7) /* "ace_en" on-CPU crypto enabled */
148#define X86_FEATURE_ACE2 ( 5*32+ 8) /* Advanced Cryptography Engine v2 */
149#define X86_FEATURE_ACE2_EN ( 5*32+ 9) /* ACE v2 enabled */
150#define X86_FEATURE_PHE ( 5*32+10) /* PadLock Hash Engine */
151#define X86_FEATURE_PHE_EN ( 5*32+11) /* PHE enabled */
152#define X86_FEATURE_PMM ( 5*32+12) /* PadLock Montgomery Multiplier */
153#define X86_FEATURE_PMM_EN ( 5*32+13) /* PMM enabled */
154
155/* More extended AMD flags: CPUID level 0x80000001, ecx, word 6 */
156#define X86_FEATURE_LAHF_LM ( 6*32+ 0) /* LAHF/SAHF in long mode */
157#define X86_FEATURE_CMP_LEGACY ( 6*32+ 1) /* If yes HyperThreading not valid */
158#define X86_FEATURE_SVM ( 6*32+ 2) /* Secure virtual machine */
159#define X86_FEATURE_EXTAPIC ( 6*32+ 3) /* Extended APIC space */
160#define X86_FEATURE_CR8_LEGACY ( 6*32+ 4) /* CR8 in 32-bit mode */
161#define X86_FEATURE_ABM ( 6*32+ 5) /* Advanced bit manipulation */
162#define X86_FEATURE_SSE4A ( 6*32+ 6) /* SSE-4A */
163#define X86_FEATURE_MISALIGNSSE ( 6*32+ 7) /* Misaligned SSE mode */
164#define X86_FEATURE_3DNOWPREFETCH ( 6*32+ 8) /* 3DNow prefetch instructions */
165#define X86_FEATURE_OSVW ( 6*32+ 9) /* OS Visible Workaround */
166#define X86_FEATURE_IBS ( 6*32+10) /* Instruction Based Sampling */
167#define X86_FEATURE_XOP ( 6*32+11) /* extended AVX instructions */
168#define X86_FEATURE_SKINIT ( 6*32+12) /* SKINIT/STGI instructions */
169#define X86_FEATURE_WDT ( 6*32+13) /* Watchdog timer */
170#define X86_FEATURE_LWP ( 6*32+15) /* Light Weight Profiling */
171#define X86_FEATURE_FMA4 ( 6*32+16) /* 4 operands MAC instructions */
172#define X86_FEATURE_TCE ( 6*32+17) /* translation cache extension */
173#define X86_FEATURE_NODEID_MSR ( 6*32+19) /* NodeId MSR */
174#define X86_FEATURE_TBM ( 6*32+21) /* trailing bit manipulations */
175#define X86_FEATURE_TOPOEXT ( 6*32+22) /* topology extensions CPUID leafs */
176#define X86_FEATURE_PERFCTR_CORE ( 6*32+23) /* core performance counter extensions */
177#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
178#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */
179#define X86_FEATURE_PTSC ( 6*32+27) /* performance time-stamp counter */
180#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */
181#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
182
183/*
184 * Auxiliary flags: Linux defined - For features scattered in various
185 * CPUID levels like 0x6, 0xA etc, word 7.
186 *
187 * Reuse free bits when adding new feature flags!
188 */
189
190#define X86_FEATURE_CPB ( 7*32+ 2) /* AMD Core Performance Boost */
191#define X86_FEATURE_EPB ( 7*32+ 3) /* IA32_ENERGY_PERF_BIAS support */
192
193#define X86_FEATURE_HW_PSTATE ( 7*32+ 8) /* AMD HW-PState */
194#define X86_FEATURE_PROC_FEEDBACK ( 7*32+ 9) /* AMD ProcFeedbackInterface */
195
196#define X86_FEATURE_INTEL_PT ( 7*32+15) /* Intel Processor Trace */
197
198/* Virtualization flags: Linux defined, word 8 */
199#define X86_FEATURE_TPR_SHADOW ( 8*32+ 0) /* Intel TPR Shadow */
200#define X86_FEATURE_VNMI ( 8*32+ 1) /* Intel Virtual NMI */
201#define X86_FEATURE_FLEXPRIORITY ( 8*32+ 2) /* Intel FlexPriority */
202#define X86_FEATURE_EPT ( 8*32+ 3) /* Intel Extended Page Table */
203#define X86_FEATURE_VPID ( 8*32+ 4) /* Intel Virtual Processor ID */
204
205#define X86_FEATURE_VMMCALL ( 8*32+15) /* Prefer vmmcall to vmcall */
206#define X86_FEATURE_XENPV ( 8*32+16) /* "" Xen paravirtual guest */
207
208
209/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */
210#define X86_FEATURE_FSGSBASE ( 9*32+ 0) /* {RD/WR}{FS/GS}BASE instructions*/
211#define X86_FEATURE_TSC_ADJUST ( 9*32+ 1) /* TSC adjustment MSR 0x3b */
212#define X86_FEATURE_BMI1 ( 9*32+ 3) /* 1st group bit manipulation extensions */
213#define X86_FEATURE_HLE ( 9*32+ 4) /* Hardware Lock Elision */
214#define X86_FEATURE_AVX2 ( 9*32+ 5) /* AVX2 instructions */
215#define X86_FEATURE_SMEP ( 9*32+ 7) /* Supervisor Mode Execution Protection */
216#define X86_FEATURE_BMI2 ( 9*32+ 8) /* 2nd group bit manipulation extensions */
217#define X86_FEATURE_ERMS ( 9*32+ 9) /* Enhanced REP MOVSB/STOSB */
218#define X86_FEATURE_INVPCID ( 9*32+10) /* Invalidate Processor Context ID */
219#define X86_FEATURE_RTM ( 9*32+11) /* Restricted Transactional Memory */
220#define X86_FEATURE_CQM ( 9*32+12) /* Cache QoS Monitoring */
221#define X86_FEATURE_MPX ( 9*32+14) /* Memory Protection Extension */
222#define X86_FEATURE_AVX512F ( 9*32+16) /* AVX-512 Foundation */
223#define X86_FEATURE_AVX512DQ ( 9*32+17) /* AVX-512 DQ (Double/Quad granular) Instructions */
224#define X86_FEATURE_RDSEED ( 9*32+18) /* The RDSEED instruction */
225#define X86_FEATURE_ADX ( 9*32+19) /* The ADCX and ADOX instructions */
226#define X86_FEATURE_SMAP ( 9*32+20) /* Supervisor Mode Access Prevention */
227#define X86_FEATURE_CLFLUSHOPT ( 9*32+23) /* CLFLUSHOPT instruction */
228#define X86_FEATURE_CLWB ( 9*32+24) /* CLWB instruction */
229#define X86_FEATURE_AVX512PF ( 9*32+26) /* AVX-512 Prefetch */
230#define X86_FEATURE_AVX512ER ( 9*32+27) /* AVX-512 Exponential and Reciprocal */
231#define X86_FEATURE_AVX512CD ( 9*32+28) /* AVX-512 Conflict Detection */
232#define X86_FEATURE_SHA_NI ( 9*32+29) /* SHA1/SHA256 Instruction Extensions */
233#define X86_FEATURE_AVX512BW ( 9*32+30) /* AVX-512 BW (Byte/Word granular) Instructions */
234#define X86_FEATURE_AVX512VL ( 9*32+31) /* AVX-512 VL (128/256 Vector Length) Extensions */
235
236/* Extended state features, CPUID level 0x0000000d:1 (eax), word 10 */
237#define X86_FEATURE_XSAVEOPT (10*32+ 0) /* XSAVEOPT */
238#define X86_FEATURE_XSAVEC (10*32+ 1) /* XSAVEC */
239#define X86_FEATURE_XGETBV1 (10*32+ 2) /* XGETBV with ECX = 1 */
240#define X86_FEATURE_XSAVES (10*32+ 3) /* XSAVES/XRSTORS */
241
242/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:0 (edx), word 11 */
243#define X86_FEATURE_CQM_LLC (11*32+ 1) /* LLC QoS if 1 */
244
245/* Intel-defined CPU QoS Sub-leaf, CPUID level 0x0000000F:1 (edx), word 12 */
246#define X86_FEATURE_CQM_OCCUP_LLC (12*32+ 0) /* LLC occupancy monitoring if 1 */
247#define X86_FEATURE_CQM_MBM_TOTAL (12*32+ 1) /* LLC Total MBM monitoring */
248#define X86_FEATURE_CQM_MBM_LOCAL (12*32+ 2) /* LLC Local MBM monitoring */
249
250/* AMD-defined CPU features, CPUID level 0x80000008 (ebx), word 13 */
251#define X86_FEATURE_CLZERO (13*32+0) /* CLZERO instruction */
252#define X86_FEATURE_IRPERF (13*32+1) /* Instructions Retired Count */
253
254/* Thermal and Power Management Leaf, CPUID level 0x00000006 (eax), word 14 */
255#define X86_FEATURE_DTHERM (14*32+ 0) /* Digital Thermal Sensor */
256#define X86_FEATURE_IDA (14*32+ 1) /* Intel Dynamic Acceleration */
257#define X86_FEATURE_ARAT (14*32+ 2) /* Always Running APIC Timer */
258#define X86_FEATURE_PLN (14*32+ 4) /* Intel Power Limit Notification */
259#define X86_FEATURE_PTS (14*32+ 6) /* Intel Package Thermal Status */
260#define X86_FEATURE_HWP (14*32+ 7) /* Intel Hardware P-states */
261#define X86_FEATURE_HWP_NOTIFY (14*32+ 8) /* HWP Notification */
262#define X86_FEATURE_HWP_ACT_WINDOW (14*32+ 9) /* HWP Activity Window */
263#define X86_FEATURE_HWP_EPP (14*32+10) /* HWP Energy Perf. Preference */
264#define X86_FEATURE_HWP_PKG_REQ (14*32+11) /* HWP Package Level Request */
265
266/* AMD SVM Feature Identification, CPUID level 0x8000000a (edx), word 15 */
267#define X86_FEATURE_NPT (15*32+ 0) /* Nested Page Table support */
268#define X86_FEATURE_LBRV (15*32+ 1) /* LBR Virtualization support */
269#define X86_FEATURE_SVML (15*32+ 2) /* "svm_lock" SVM locking MSR */
270#define X86_FEATURE_NRIPS (15*32+ 3) /* "nrip_save" SVM next_rip save */
271#define X86_FEATURE_TSCRATEMSR (15*32+ 4) /* "tsc_scale" TSC scaling support */
272#define X86_FEATURE_VMCBCLEAN (15*32+ 5) /* "vmcb_clean" VMCB clean bits support */
273#define X86_FEATURE_FLUSHBYASID (15*32+ 6) /* flush-by-ASID support */
274#define X86_FEATURE_DECODEASSISTS (15*32+ 7) /* Decode Assists support */
275#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */
276#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
277#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
278
279/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
280#define X86_FEATURE_PKU (16*32+ 3) /* Protection Keys for Userspace */
281#define X86_FEATURE_OSPKE (16*32+ 4) /* OS Protection Keys Enable */
282
283/* AMD-defined CPU features, CPUID level 0x80000007 (ebx), word 17 */
284#define X86_FEATURE_OVERFLOW_RECOV (17*32+0) /* MCA overflow recovery support */
285#define X86_FEATURE_SUCCOR (17*32+1) /* Uncorrectable error containment and recovery */
286#define X86_FEATURE_SMCA (17*32+3) /* Scalable MCA */
287
288/*
289 * BUG word(s)
290 */
291#define X86_BUG(x) (NCAPINTS*32 + (x))
292
293#define X86_BUG_F00F X86_BUG(0) /* Intel F00F */
294#define X86_BUG_FDIV X86_BUG(1) /* FPU FDIV */
295#define X86_BUG_COMA X86_BUG(2) /* Cyrix 6x86 coma */
296#define X86_BUG_AMD_TLB_MMATCH X86_BUG(3) /* "tlb_mmatch" AMD Erratum 383 */
297#define X86_BUG_AMD_APIC_C1E X86_BUG(4) /* "apic_c1e" AMD Erratum 400 */
298#define X86_BUG_11AP X86_BUG(5) /* Bad local APIC aka 11AP */
299#define X86_BUG_FXSAVE_LEAK X86_BUG(6) /* FXSAVE leaks FOP/FIP/FOP */
300#define X86_BUG_CLFLUSH_MONITOR X86_BUG(7) /* AAI65, CLFLUSH required before MONITOR */
301#define X86_BUG_SYSRET_SS_ATTRS X86_BUG(8) /* SYSRET doesn't fix up SS attrs */
302#ifdef CONFIG_X86_32
303/*
304 * 64-bit kernels don't use X86_BUG_ESPFIX. Make the define conditional
305 * to avoid confusion.
306 */
307#define X86_BUG_ESPFIX X86_BUG(9) /* "" IRET to 16-bit SS corrupts ESP/RSP high bits */
308#endif
309#define X86_BUG_NULL_SEG X86_BUG(10) /* Nulling a selector preserves the base */
310#define X86_BUG_SWAPGS_FENCE X86_BUG(11) /* SWAPGS without input dep on GS */
311#define X86_BUG_MONITOR X86_BUG(12) /* IPI required to wake up remote CPU */
312#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/arch/x86/include/asm/disabled-features.h b/tools/arch/x86/include/asm/disabled-features.h
new file mode 100644
index 000000000000..85599ad4d024
--- /dev/null
+++ b/tools/arch/x86/include/asm/disabled-features.h
@@ -0,0 +1,62 @@
1#ifndef _ASM_X86_DISABLED_FEATURES_H
2#define _ASM_X86_DISABLED_FEATURES_H
3
4/* These features, although they might be available in a CPU
5 * will not be used because the compile options to support
6 * them are not present.
7 *
8 * This code allows them to be checked and disabled at
9 * compile time without an explicit #ifdef. Use
10 * cpu_feature_enabled().
11 */
12
13#ifdef CONFIG_X86_INTEL_MPX
14# define DISABLE_MPX 0
15#else
16# define DISABLE_MPX (1<<(X86_FEATURE_MPX & 31))
17#endif
18
19#ifdef CONFIG_X86_64
20# define DISABLE_VME (1<<(X86_FEATURE_VME & 31))
21# define DISABLE_K6_MTRR (1<<(X86_FEATURE_K6_MTRR & 31))
22# define DISABLE_CYRIX_ARR (1<<(X86_FEATURE_CYRIX_ARR & 31))
23# define DISABLE_CENTAUR_MCR (1<<(X86_FEATURE_CENTAUR_MCR & 31))
24#else
25# define DISABLE_VME 0
26# define DISABLE_K6_MTRR 0
27# define DISABLE_CYRIX_ARR 0
28# define DISABLE_CENTAUR_MCR 0
29#endif /* CONFIG_X86_64 */
30
31#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
32# define DISABLE_PKU 0
33# define DISABLE_OSPKE 0
34#else
35# define DISABLE_PKU (1<<(X86_FEATURE_PKU & 31))
36# define DISABLE_OSPKE (1<<(X86_FEATURE_OSPKE & 31))
37#endif /* CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS */
38
39/*
40 * Make sure to add features to the correct mask
41 */
42#define DISABLED_MASK0 (DISABLE_VME)
43#define DISABLED_MASK1 0
44#define DISABLED_MASK2 0
45#define DISABLED_MASK3 (DISABLE_CYRIX_ARR|DISABLE_CENTAUR_MCR|DISABLE_K6_MTRR)
46#define DISABLED_MASK4 0
47#define DISABLED_MASK5 0
48#define DISABLED_MASK6 0
49#define DISABLED_MASK7 0
50#define DISABLED_MASK8 0
51#define DISABLED_MASK9 (DISABLE_MPX)
52#define DISABLED_MASK10 0
53#define DISABLED_MASK11 0
54#define DISABLED_MASK12 0
55#define DISABLED_MASK13 0
56#define DISABLED_MASK14 0
57#define DISABLED_MASK15 0
58#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE)
59#define DISABLED_MASK17 0
60#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
61
62#endif /* _ASM_X86_DISABLED_FEATURES_H */
diff --git a/tools/arch/x86/include/asm/required-features.h b/tools/arch/x86/include/asm/required-features.h
new file mode 100644
index 000000000000..fac9a5c0abe9
--- /dev/null
+++ b/tools/arch/x86/include/asm/required-features.h
@@ -0,0 +1,105 @@
1#ifndef _ASM_X86_REQUIRED_FEATURES_H
2#define _ASM_X86_REQUIRED_FEATURES_H
3
4/* Define minimum CPUID feature set for kernel These bits are checked
5 really early to actually display a visible error message before the
6 kernel dies. Make sure to assign features to the proper mask!
7
8 Some requirements that are not in CPUID yet are also in the
9 CONFIG_X86_MINIMUM_CPU_FAMILY which is checked too.
10
11 The real information is in arch/x86/Kconfig.cpu, this just converts
12 the CONFIGs into a bitmask */
13
14#ifndef CONFIG_MATH_EMULATION
15# define NEED_FPU (1<<(X86_FEATURE_FPU & 31))
16#else
17# define NEED_FPU 0
18#endif
19
20#if defined(CONFIG_X86_PAE) || defined(CONFIG_X86_64)
21# define NEED_PAE (1<<(X86_FEATURE_PAE & 31))
22#else
23# define NEED_PAE 0
24#endif
25
26#ifdef CONFIG_X86_CMPXCHG64
27# define NEED_CX8 (1<<(X86_FEATURE_CX8 & 31))
28#else
29# define NEED_CX8 0
30#endif
31
32#if defined(CONFIG_X86_CMOV) || defined(CONFIG_X86_64)
33# define NEED_CMOV (1<<(X86_FEATURE_CMOV & 31))
34#else
35# define NEED_CMOV 0
36#endif
37
38#ifdef CONFIG_X86_USE_3DNOW
39# define NEED_3DNOW (1<<(X86_FEATURE_3DNOW & 31))
40#else
41# define NEED_3DNOW 0
42#endif
43
44#if defined(CONFIG_X86_P6_NOP) || defined(CONFIG_X86_64)
45# define NEED_NOPL (1<<(X86_FEATURE_NOPL & 31))
46#else
47# define NEED_NOPL 0
48#endif
49
50#ifdef CONFIG_MATOM
51# define NEED_MOVBE (1<<(X86_FEATURE_MOVBE & 31))
52#else
53# define NEED_MOVBE 0
54#endif
55
56#ifdef CONFIG_X86_64
57#ifdef CONFIG_PARAVIRT
58/* Paravirtualized systems may not have PSE or PGE available */
59#define NEED_PSE 0
60#define NEED_PGE 0
61#else
62#define NEED_PSE (1<<(X86_FEATURE_PSE) & 31)
63#define NEED_PGE (1<<(X86_FEATURE_PGE) & 31)
64#endif
65#define NEED_MSR (1<<(X86_FEATURE_MSR & 31))
66#define NEED_FXSR (1<<(X86_FEATURE_FXSR & 31))
67#define NEED_XMM (1<<(X86_FEATURE_XMM & 31))
68#define NEED_XMM2 (1<<(X86_FEATURE_XMM2 & 31))
69#define NEED_LM (1<<(X86_FEATURE_LM & 31))
70#else
71#define NEED_PSE 0
72#define NEED_MSR 0
73#define NEED_PGE 0
74#define NEED_FXSR 0
75#define NEED_XMM 0
76#define NEED_XMM2 0
77#define NEED_LM 0
78#endif
79
80#define REQUIRED_MASK0 (NEED_FPU|NEED_PSE|NEED_MSR|NEED_PAE|\
81 NEED_CX8|NEED_PGE|NEED_FXSR|NEED_CMOV|\
82 NEED_XMM|NEED_XMM2)
83#define SSE_MASK (NEED_XMM|NEED_XMM2)
84
85#define REQUIRED_MASK1 (NEED_LM|NEED_3DNOW)
86
87#define REQUIRED_MASK2 0
88#define REQUIRED_MASK3 (NEED_NOPL)
89#define REQUIRED_MASK4 (NEED_MOVBE)
90#define REQUIRED_MASK5 0
91#define REQUIRED_MASK6 0
92#define REQUIRED_MASK7 0
93#define REQUIRED_MASK8 0
94#define REQUIRED_MASK9 0
95#define REQUIRED_MASK10 0
96#define REQUIRED_MASK11 0
97#define REQUIRED_MASK12 0
98#define REQUIRED_MASK13 0
99#define REQUIRED_MASK14 0
100#define REQUIRED_MASK15 0
101#define REQUIRED_MASK16 0
102#define REQUIRED_MASK17 0
103#define REQUIRED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 18)
104
105#endif /* _ASM_X86_REQUIRED_FEATURES_H */
diff --git a/tools/arch/x86/include/asm/unistd_32.h b/tools/arch/x86/include/asm/unistd_32.h
new file mode 100644
index 000000000000..88b3f8c8920c
--- /dev/null
+++ b/tools/arch/x86/include/asm/unistd_32.h
@@ -0,0 +1,12 @@
1#ifndef __NR_perf_event_open
2# define __NR_perf_event_open 336
3#endif
4#ifndef __NR_futex
5# define __NR_futex 240
6#endif
7#ifndef __NR_gettid
8# define __NR_gettid 224
9#endif
10#ifndef __NR_getcpu
11# define __NR_getcpu 318
12#endif
diff --git a/tools/arch/x86/include/asm/unistd_64.h b/tools/arch/x86/include/asm/unistd_64.h
new file mode 100644
index 000000000000..fbdb70ee8837
--- /dev/null
+++ b/tools/arch/x86/include/asm/unistd_64.h
@@ -0,0 +1,12 @@
1#ifndef __NR_perf_event_open
2# define __NR_perf_event_open 298
3#endif
4#ifndef __NR_futex
5# define __NR_futex 202
6#endif
7#ifndef __NR_gettid
8# define __NR_gettid 186
9#endif
10#ifndef __NR_getcpu
11# define __NR_getcpu 309
12#endif
diff --git a/tools/arch/x86/include/uapi/asm/bitsperlong.h b/tools/arch/x86/include/uapi/asm/bitsperlong.h
new file mode 100644
index 000000000000..6e23c543cd80
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/bitsperlong.h
@@ -0,0 +1,12 @@
1#ifndef __ASM_X86_BITSPERLONG_H
2#define __ASM_X86_BITSPERLONG_H
3
4#if defined(__x86_64__) && !defined(__ILP32__)
5# define __BITS_PER_LONG 64
6#else
7# define __BITS_PER_LONG 32
8#endif
9
10#include <asm-generic/bitsperlong.h>
11
12#endif /* __ASM_X86_BITSPERLONG_H */
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
new file mode 100644
index 000000000000..739c0c594022
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -0,0 +1,360 @@
1#ifndef _ASM_X86_KVM_H
2#define _ASM_X86_KVM_H
3
4/*
5 * KVM x86 specific structures and definitions
6 *
7 */
8
9#include <linux/types.h>
10#include <linux/ioctl.h>
11
12#define DE_VECTOR 0
13#define DB_VECTOR 1
14#define BP_VECTOR 3
15#define OF_VECTOR 4
16#define BR_VECTOR 5
17#define UD_VECTOR 6
18#define NM_VECTOR 7
19#define DF_VECTOR 8
20#define TS_VECTOR 10
21#define NP_VECTOR 11
22#define SS_VECTOR 12
23#define GP_VECTOR 13
24#define PF_VECTOR 14
25#define MF_VECTOR 16
26#define AC_VECTOR 17
27#define MC_VECTOR 18
28#define XM_VECTOR 19
29#define VE_VECTOR 20
30
31/* Select x86 specific features in <linux/kvm.h> */
32#define __KVM_HAVE_PIT
33#define __KVM_HAVE_IOAPIC
34#define __KVM_HAVE_IRQ_LINE
35#define __KVM_HAVE_MSI
36#define __KVM_HAVE_USER_NMI
37#define __KVM_HAVE_GUEST_DEBUG
38#define __KVM_HAVE_MSIX
39#define __KVM_HAVE_MCE
40#define __KVM_HAVE_PIT_STATE2
41#define __KVM_HAVE_XEN_HVM
42#define __KVM_HAVE_VCPU_EVENTS
43#define __KVM_HAVE_DEBUGREGS
44#define __KVM_HAVE_XSAVE
45#define __KVM_HAVE_XCRS
46#define __KVM_HAVE_READONLY_MEM
47
48/* Architectural interrupt line count. */
49#define KVM_NR_INTERRUPTS 256
50
51struct kvm_memory_alias {
52 __u32 slot; /* this has a different namespace than memory slots */
53 __u32 flags;
54 __u64 guest_phys_addr;
55 __u64 memory_size;
56 __u64 target_phys_addr;
57};
58
59/* for KVM_GET_IRQCHIP and KVM_SET_IRQCHIP */
60struct kvm_pic_state {
61 __u8 last_irr; /* edge detection */
62 __u8 irr; /* interrupt request register */
63 __u8 imr; /* interrupt mask register */
64 __u8 isr; /* interrupt service register */
65 __u8 priority_add; /* highest irq priority */
66 __u8 irq_base;
67 __u8 read_reg_select;
68 __u8 poll;
69 __u8 special_mask;
70 __u8 init_state;
71 __u8 auto_eoi;
72 __u8 rotate_on_auto_eoi;
73 __u8 special_fully_nested_mode;
74 __u8 init4; /* true if 4 byte init */
75 __u8 elcr; /* PIIX edge/trigger selection */
76 __u8 elcr_mask;
77};
78
79#define KVM_IOAPIC_NUM_PINS 24
80struct kvm_ioapic_state {
81 __u64 base_address;
82 __u32 ioregsel;
83 __u32 id;
84 __u32 irr;
85 __u32 pad;
86 union {
87 __u64 bits;
88 struct {
89 __u8 vector;
90 __u8 delivery_mode:3;
91 __u8 dest_mode:1;
92 __u8 delivery_status:1;
93 __u8 polarity:1;
94 __u8 remote_irr:1;
95 __u8 trig_mode:1;
96 __u8 mask:1;
97 __u8 reserve:7;
98 __u8 reserved[4];
99 __u8 dest_id;
100 } fields;
101 } redirtbl[KVM_IOAPIC_NUM_PINS];
102};
103
104#define KVM_IRQCHIP_PIC_MASTER 0
105#define KVM_IRQCHIP_PIC_SLAVE 1
106#define KVM_IRQCHIP_IOAPIC 2
107#define KVM_NR_IRQCHIPS 3
108
109#define KVM_RUN_X86_SMM (1 << 0)
110
111/* for KVM_GET_REGS and KVM_SET_REGS */
112struct kvm_regs {
113 /* out (KVM_GET_REGS) / in (KVM_SET_REGS) */
114 __u64 rax, rbx, rcx, rdx;
115 __u64 rsi, rdi, rsp, rbp;
116 __u64 r8, r9, r10, r11;
117 __u64 r12, r13, r14, r15;
118 __u64 rip, rflags;
119};
120
121/* for KVM_GET_LAPIC and KVM_SET_LAPIC */
122#define KVM_APIC_REG_SIZE 0x400
123struct kvm_lapic_state {
124 char regs[KVM_APIC_REG_SIZE];
125};
126
127struct kvm_segment {
128 __u64 base;
129 __u32 limit;
130 __u16 selector;
131 __u8 type;
132 __u8 present, dpl, db, s, l, g, avl;
133 __u8 unusable;
134 __u8 padding;
135};
136
137struct kvm_dtable {
138 __u64 base;
139 __u16 limit;
140 __u16 padding[3];
141};
142
143
144/* for KVM_GET_SREGS and KVM_SET_SREGS */
145struct kvm_sregs {
146 /* out (KVM_GET_SREGS) / in (KVM_SET_SREGS) */
147 struct kvm_segment cs, ds, es, fs, gs, ss;
148 struct kvm_segment tr, ldt;
149 struct kvm_dtable gdt, idt;
150 __u64 cr0, cr2, cr3, cr4, cr8;
151 __u64 efer;
152 __u64 apic_base;
153 __u64 interrupt_bitmap[(KVM_NR_INTERRUPTS + 63) / 64];
154};
155
156/* for KVM_GET_FPU and KVM_SET_FPU */
157struct kvm_fpu {
158 __u8 fpr[8][16];
159 __u16 fcw;
160 __u16 fsw;
161 __u8 ftwx; /* in fxsave format */
162 __u8 pad1;
163 __u16 last_opcode;
164 __u64 last_ip;
165 __u64 last_dp;
166 __u8 xmm[16][16];
167 __u32 mxcsr;
168 __u32 pad2;
169};
170
171struct kvm_msr_entry {
172 __u32 index;
173 __u32 reserved;
174 __u64 data;
175};
176
177/* for KVM_GET_MSRS and KVM_SET_MSRS */
178struct kvm_msrs {
179 __u32 nmsrs; /* number of msrs in entries */
180 __u32 pad;
181
182 struct kvm_msr_entry entries[0];
183};
184
185/* for KVM_GET_MSR_INDEX_LIST */
186struct kvm_msr_list {
187 __u32 nmsrs; /* number of msrs in entries */
188 __u32 indices[0];
189};
190
191
192struct kvm_cpuid_entry {
193 __u32 function;
194 __u32 eax;
195 __u32 ebx;
196 __u32 ecx;
197 __u32 edx;
198 __u32 padding;
199};
200
201/* for KVM_SET_CPUID */
202struct kvm_cpuid {
203 __u32 nent;
204 __u32 padding;
205 struct kvm_cpuid_entry entries[0];
206};
207
208struct kvm_cpuid_entry2 {
209 __u32 function;
210 __u32 index;
211 __u32 flags;
212 __u32 eax;
213 __u32 ebx;
214 __u32 ecx;
215 __u32 edx;
216 __u32 padding[3];
217};
218
219#define KVM_CPUID_FLAG_SIGNIFCANT_INDEX (1 << 0)
220#define KVM_CPUID_FLAG_STATEFUL_FUNC (1 << 1)
221#define KVM_CPUID_FLAG_STATE_READ_NEXT (1 << 2)
222
223/* for KVM_SET_CPUID2 */
224struct kvm_cpuid2 {
225 __u32 nent;
226 __u32 padding;
227 struct kvm_cpuid_entry2 entries[0];
228};
229
230/* for KVM_GET_PIT and KVM_SET_PIT */
231struct kvm_pit_channel_state {
232 __u32 count; /* can be 65536 */
233 __u16 latched_count;
234 __u8 count_latched;
235 __u8 status_latched;
236 __u8 status;
237 __u8 read_state;
238 __u8 write_state;
239 __u8 write_latch;
240 __u8 rw_mode;
241 __u8 mode;
242 __u8 bcd;
243 __u8 gate;
244 __s64 count_load_time;
245};
246
247struct kvm_debug_exit_arch {
248 __u32 exception;
249 __u32 pad;
250 __u64 pc;
251 __u64 dr6;
252 __u64 dr7;
253};
254
255#define KVM_GUESTDBG_USE_SW_BP 0x00010000
256#define KVM_GUESTDBG_USE_HW_BP 0x00020000
257#define KVM_GUESTDBG_INJECT_DB 0x00040000
258#define KVM_GUESTDBG_INJECT_BP 0x00080000
259
260/* for KVM_SET_GUEST_DEBUG */
261struct kvm_guest_debug_arch {
262 __u64 debugreg[8];
263};
264
265struct kvm_pit_state {
266 struct kvm_pit_channel_state channels[3];
267};
268
269#define KVM_PIT_FLAGS_HPET_LEGACY 0x00000001
270
271struct kvm_pit_state2 {
272 struct kvm_pit_channel_state channels[3];
273 __u32 flags;
274 __u32 reserved[9];
275};
276
277struct kvm_reinject_control {
278 __u8 pit_reinject;
279 __u8 reserved[31];
280};
281
282/* When set in flags, include corresponding fields on KVM_SET_VCPU_EVENTS */
283#define KVM_VCPUEVENT_VALID_NMI_PENDING 0x00000001
284#define KVM_VCPUEVENT_VALID_SIPI_VECTOR 0x00000002
285#define KVM_VCPUEVENT_VALID_SHADOW 0x00000004
286#define KVM_VCPUEVENT_VALID_SMM 0x00000008
287
288/* Interrupt shadow states */
289#define KVM_X86_SHADOW_INT_MOV_SS 0x01
290#define KVM_X86_SHADOW_INT_STI 0x02
291
292/* for KVM_GET/SET_VCPU_EVENTS */
293struct kvm_vcpu_events {
294 struct {
295 __u8 injected;
296 __u8 nr;
297 __u8 has_error_code;
298 __u8 pad;
299 __u32 error_code;
300 } exception;
301 struct {
302 __u8 injected;
303 __u8 nr;
304 __u8 soft;
305 __u8 shadow;
306 } interrupt;
307 struct {
308 __u8 injected;
309 __u8 pending;
310 __u8 masked;
311 __u8 pad;
312 } nmi;
313 __u32 sipi_vector;
314 __u32 flags;
315 struct {
316 __u8 smm;
317 __u8 pending;
318 __u8 smm_inside_nmi;
319 __u8 latched_init;
320 } smi;
321 __u32 reserved[9];
322};
323
324/* for KVM_GET/SET_DEBUGREGS */
325struct kvm_debugregs {
326 __u64 db[4];
327 __u64 dr6;
328 __u64 dr7;
329 __u64 flags;
330 __u64 reserved[9];
331};
332
333/* for KVM_CAP_XSAVE */
334struct kvm_xsave {
335 __u32 region[1024];
336};
337
338#define KVM_MAX_XCRS 16
339
340struct kvm_xcr {
341 __u32 xcr;
342 __u32 reserved;
343 __u64 value;
344};
345
346struct kvm_xcrs {
347 __u32 nr_xcrs;
348 __u32 flags;
349 struct kvm_xcr xcrs[KVM_MAX_XCRS];
350 __u64 padding[16];
351};
352
353/* definition of registers in kvm_run */
354struct kvm_sync_regs {
355};
356
357#define KVM_X86_QUIRK_LINT0_REENABLED (1 << 0)
358#define KVM_X86_QUIRK_CD_NW_CLEARED (1 << 1)
359
360#endif /* _ASM_X86_KVM_H */
diff --git a/tools/arch/x86/include/uapi/asm/kvm_perf.h b/tools/arch/x86/include/uapi/asm/kvm_perf.h
new file mode 100644
index 000000000000..3bb964f88aa1
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/kvm_perf.h
@@ -0,0 +1,16 @@
1#ifndef _ASM_X86_KVM_PERF_H
2#define _ASM_X86_KVM_PERF_H
3
4#include <asm/svm.h>
5#include <asm/vmx.h>
6#include <asm/kvm.h>
7
8#define DECODE_STR_LEN 20
9
10#define VCPU_ID "vcpu_id"
11
12#define KVM_ENTRY_TRACE "kvm:kvm_entry"
13#define KVM_EXIT_TRACE "kvm:kvm_exit"
14#define KVM_EXIT_REASON "exit_reason"
15
16#endif /* _ASM_X86_KVM_PERF_H */
diff --git a/tools/arch/x86/include/uapi/asm/mman.h b/tools/arch/x86/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..b73c1af8b1dd
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/mman.h
@@ -0,0 +1,5 @@
1#ifndef TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_X86_UAPI_ASM_MMAN_FIX_H
3#define MAP_32BIT 0x40
4#include <uapi/asm-generic/mman.h>
5#endif
diff --git a/tools/arch/x86/include/uapi/asm/perf_regs.h b/tools/arch/x86/include/uapi/asm/perf_regs.h
new file mode 100644
index 000000000000..3f2207bfd17b
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/perf_regs.h
@@ -0,0 +1,33 @@
1#ifndef _ASM_X86_PERF_REGS_H
2#define _ASM_X86_PERF_REGS_H
3
4enum perf_event_x86_regs {
5 PERF_REG_X86_AX,
6 PERF_REG_X86_BX,
7 PERF_REG_X86_CX,
8 PERF_REG_X86_DX,
9 PERF_REG_X86_SI,
10 PERF_REG_X86_DI,
11 PERF_REG_X86_BP,
12 PERF_REG_X86_SP,
13 PERF_REG_X86_IP,
14 PERF_REG_X86_FLAGS,
15 PERF_REG_X86_CS,
16 PERF_REG_X86_SS,
17 PERF_REG_X86_DS,
18 PERF_REG_X86_ES,
19 PERF_REG_X86_FS,
20 PERF_REG_X86_GS,
21 PERF_REG_X86_R8,
22 PERF_REG_X86_R9,
23 PERF_REG_X86_R10,
24 PERF_REG_X86_R11,
25 PERF_REG_X86_R12,
26 PERF_REG_X86_R13,
27 PERF_REG_X86_R14,
28 PERF_REG_X86_R15,
29
30 PERF_REG_X86_32_MAX = PERF_REG_X86_GS + 1,
31 PERF_REG_X86_64_MAX = PERF_REG_X86_R15 + 1,
32};
33#endif /* _ASM_X86_PERF_REGS_H */
diff --git a/tools/arch/x86/include/uapi/asm/svm.h b/tools/arch/x86/include/uapi/asm/svm.h
new file mode 100644
index 000000000000..3725e145aa58
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/svm.h
@@ -0,0 +1,178 @@
1#ifndef _UAPI__SVM_H
2#define _UAPI__SVM_H
3
4#define SVM_EXIT_READ_CR0 0x000
5#define SVM_EXIT_READ_CR2 0x002
6#define SVM_EXIT_READ_CR3 0x003
7#define SVM_EXIT_READ_CR4 0x004
8#define SVM_EXIT_READ_CR8 0x008
9#define SVM_EXIT_WRITE_CR0 0x010
10#define SVM_EXIT_WRITE_CR2 0x012
11#define SVM_EXIT_WRITE_CR3 0x013
12#define SVM_EXIT_WRITE_CR4 0x014
13#define SVM_EXIT_WRITE_CR8 0x018
14#define SVM_EXIT_READ_DR0 0x020
15#define SVM_EXIT_READ_DR1 0x021
16#define SVM_EXIT_READ_DR2 0x022
17#define SVM_EXIT_READ_DR3 0x023
18#define SVM_EXIT_READ_DR4 0x024
19#define SVM_EXIT_READ_DR5 0x025
20#define SVM_EXIT_READ_DR6 0x026
21#define SVM_EXIT_READ_DR7 0x027
22#define SVM_EXIT_WRITE_DR0 0x030
23#define SVM_EXIT_WRITE_DR1 0x031
24#define SVM_EXIT_WRITE_DR2 0x032
25#define SVM_EXIT_WRITE_DR3 0x033
26#define SVM_EXIT_WRITE_DR4 0x034
27#define SVM_EXIT_WRITE_DR5 0x035
28#define SVM_EXIT_WRITE_DR6 0x036
29#define SVM_EXIT_WRITE_DR7 0x037
30#define SVM_EXIT_EXCP_BASE 0x040
31#define SVM_EXIT_INTR 0x060
32#define SVM_EXIT_NMI 0x061
33#define SVM_EXIT_SMI 0x062
34#define SVM_EXIT_INIT 0x063
35#define SVM_EXIT_VINTR 0x064
36#define SVM_EXIT_CR0_SEL_WRITE 0x065
37#define SVM_EXIT_IDTR_READ 0x066
38#define SVM_EXIT_GDTR_READ 0x067
39#define SVM_EXIT_LDTR_READ 0x068
40#define SVM_EXIT_TR_READ 0x069
41#define SVM_EXIT_IDTR_WRITE 0x06a
42#define SVM_EXIT_GDTR_WRITE 0x06b
43#define SVM_EXIT_LDTR_WRITE 0x06c
44#define SVM_EXIT_TR_WRITE 0x06d
45#define SVM_EXIT_RDTSC 0x06e
46#define SVM_EXIT_RDPMC 0x06f
47#define SVM_EXIT_PUSHF 0x070
48#define SVM_EXIT_POPF 0x071
49#define SVM_EXIT_CPUID 0x072
50#define SVM_EXIT_RSM 0x073
51#define SVM_EXIT_IRET 0x074
52#define SVM_EXIT_SWINT 0x075
53#define SVM_EXIT_INVD 0x076
54#define SVM_EXIT_PAUSE 0x077
55#define SVM_EXIT_HLT 0x078
56#define SVM_EXIT_INVLPG 0x079
57#define SVM_EXIT_INVLPGA 0x07a
58#define SVM_EXIT_IOIO 0x07b
59#define SVM_EXIT_MSR 0x07c
60#define SVM_EXIT_TASK_SWITCH 0x07d
61#define SVM_EXIT_FERR_FREEZE 0x07e
62#define SVM_EXIT_SHUTDOWN 0x07f
63#define SVM_EXIT_VMRUN 0x080
64#define SVM_EXIT_VMMCALL 0x081
65#define SVM_EXIT_VMLOAD 0x082
66#define SVM_EXIT_VMSAVE 0x083
67#define SVM_EXIT_STGI 0x084
68#define SVM_EXIT_CLGI 0x085
69#define SVM_EXIT_SKINIT 0x086
70#define SVM_EXIT_RDTSCP 0x087
71#define SVM_EXIT_ICEBP 0x088
72#define SVM_EXIT_WBINVD 0x089
73#define SVM_EXIT_MONITOR 0x08a
74#define SVM_EXIT_MWAIT 0x08b
75#define SVM_EXIT_MWAIT_COND 0x08c
76#define SVM_EXIT_XSETBV 0x08d
77#define SVM_EXIT_NPF 0x400
78#define SVM_EXIT_AVIC_INCOMPLETE_IPI 0x401
79#define SVM_EXIT_AVIC_UNACCELERATED_ACCESS 0x402
80
81#define SVM_EXIT_ERR -1
82
83#define SVM_EXIT_REASONS \
84 { SVM_EXIT_READ_CR0, "read_cr0" }, \
85 { SVM_EXIT_READ_CR2, "read_cr2" }, \
86 { SVM_EXIT_READ_CR3, "read_cr3" }, \
87 { SVM_EXIT_READ_CR4, "read_cr4" }, \
88 { SVM_EXIT_READ_CR8, "read_cr8" }, \
89 { SVM_EXIT_WRITE_CR0, "write_cr0" }, \
90 { SVM_EXIT_WRITE_CR2, "write_cr2" }, \
91 { SVM_EXIT_WRITE_CR3, "write_cr3" }, \
92 { SVM_EXIT_WRITE_CR4, "write_cr4" }, \
93 { SVM_EXIT_WRITE_CR8, "write_cr8" }, \
94 { SVM_EXIT_READ_DR0, "read_dr0" }, \
95 { SVM_EXIT_READ_DR1, "read_dr1" }, \
96 { SVM_EXIT_READ_DR2, "read_dr2" }, \
97 { SVM_EXIT_READ_DR3, "read_dr3" }, \
98 { SVM_EXIT_READ_DR4, "read_dr4" }, \
99 { SVM_EXIT_READ_DR5, "read_dr5" }, \
100 { SVM_EXIT_READ_DR6, "read_dr6" }, \
101 { SVM_EXIT_READ_DR7, "read_dr7" }, \
102 { SVM_EXIT_WRITE_DR0, "write_dr0" }, \
103 { SVM_EXIT_WRITE_DR1, "write_dr1" }, \
104 { SVM_EXIT_WRITE_DR2, "write_dr2" }, \
105 { SVM_EXIT_WRITE_DR3, "write_dr3" }, \
106 { SVM_EXIT_WRITE_DR4, "write_dr4" }, \
107 { SVM_EXIT_WRITE_DR5, "write_dr5" }, \
108 { SVM_EXIT_WRITE_DR6, "write_dr6" }, \
109 { SVM_EXIT_WRITE_DR7, "write_dr7" }, \
110 { SVM_EXIT_EXCP_BASE + DE_VECTOR, "DE excp" }, \
111 { SVM_EXIT_EXCP_BASE + DB_VECTOR, "DB excp" }, \
112 { SVM_EXIT_EXCP_BASE + BP_VECTOR, "BP excp" }, \
113 { SVM_EXIT_EXCP_BASE + OF_VECTOR, "OF excp" }, \
114 { SVM_EXIT_EXCP_BASE + BR_VECTOR, "BR excp" }, \
115 { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
116 { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
117 { SVM_EXIT_EXCP_BASE + DF_VECTOR, "DF excp" }, \
118 { SVM_EXIT_EXCP_BASE + TS_VECTOR, "TS excp" }, \
119 { SVM_EXIT_EXCP_BASE + NP_VECTOR, "NP excp" }, \
120 { SVM_EXIT_EXCP_BASE + SS_VECTOR, "SS excp" }, \
121 { SVM_EXIT_EXCP_BASE + GP_VECTOR, "GP excp" }, \
122 { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
123 { SVM_EXIT_EXCP_BASE + MF_VECTOR, "MF excp" }, \
124 { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, \
125 { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
126 { SVM_EXIT_EXCP_BASE + XM_VECTOR, "XF excp" }, \
127 { SVM_EXIT_INTR, "interrupt" }, \
128 { SVM_EXIT_NMI, "nmi" }, \
129 { SVM_EXIT_SMI, "smi" }, \
130 { SVM_EXIT_INIT, "init" }, \
131 { SVM_EXIT_VINTR, "vintr" }, \
132 { SVM_EXIT_CR0_SEL_WRITE, "cr0_sel_write" }, \
133 { SVM_EXIT_IDTR_READ, "read_idtr" }, \
134 { SVM_EXIT_GDTR_READ, "read_gdtr" }, \
135 { SVM_EXIT_LDTR_READ, "read_ldtr" }, \
136 { SVM_EXIT_TR_READ, "read_rt" }, \
137 { SVM_EXIT_IDTR_WRITE, "write_idtr" }, \
138 { SVM_EXIT_GDTR_WRITE, "write_gdtr" }, \
139 { SVM_EXIT_LDTR_WRITE, "write_ldtr" }, \
140 { SVM_EXIT_TR_WRITE, "write_rt" }, \
141 { SVM_EXIT_RDTSC, "rdtsc" }, \
142 { SVM_EXIT_RDPMC, "rdpmc" }, \
143 { SVM_EXIT_PUSHF, "pushf" }, \
144 { SVM_EXIT_POPF, "popf" }, \
145 { SVM_EXIT_CPUID, "cpuid" }, \
146 { SVM_EXIT_RSM, "rsm" }, \
147 { SVM_EXIT_IRET, "iret" }, \
148 { SVM_EXIT_SWINT, "swint" }, \
149 { SVM_EXIT_INVD, "invd" }, \
150 { SVM_EXIT_PAUSE, "pause" }, \
151 { SVM_EXIT_HLT, "hlt" }, \
152 { SVM_EXIT_INVLPG, "invlpg" }, \
153 { SVM_EXIT_INVLPGA, "invlpga" }, \
154 { SVM_EXIT_IOIO, "io" }, \
155 { SVM_EXIT_MSR, "msr" }, \
156 { SVM_EXIT_TASK_SWITCH, "task_switch" }, \
157 { SVM_EXIT_FERR_FREEZE, "ferr_freeze" }, \
158 { SVM_EXIT_SHUTDOWN, "shutdown" }, \
159 { SVM_EXIT_VMRUN, "vmrun" }, \
160 { SVM_EXIT_VMMCALL, "hypercall" }, \
161 { SVM_EXIT_VMLOAD, "vmload" }, \
162 { SVM_EXIT_VMSAVE, "vmsave" }, \
163 { SVM_EXIT_STGI, "stgi" }, \
164 { SVM_EXIT_CLGI, "clgi" }, \
165 { SVM_EXIT_SKINIT, "skinit" }, \
166 { SVM_EXIT_RDTSCP, "rdtscp" }, \
167 { SVM_EXIT_ICEBP, "icebp" }, \
168 { SVM_EXIT_WBINVD, "wbinvd" }, \
169 { SVM_EXIT_MONITOR, "monitor" }, \
170 { SVM_EXIT_MWAIT, "mwait" }, \
171 { SVM_EXIT_XSETBV, "xsetbv" }, \
172 { SVM_EXIT_NPF, "npf" }, \
173 { SVM_EXIT_AVIC_INCOMPLETE_IPI, "avic_incomplete_ipi" }, \
174 { SVM_EXIT_AVIC_UNACCELERATED_ACCESS, "avic_unaccelerated_access" }, \
175 { SVM_EXIT_ERR, "invalid_guest_state" }
176
177
178#endif /* _UAPI__SVM_H */
diff --git a/tools/arch/x86/include/uapi/asm/vmx.h b/tools/arch/x86/include/uapi/asm/vmx.h
new file mode 100644
index 000000000000..37fee272618f
--- /dev/null
+++ b/tools/arch/x86/include/uapi/asm/vmx.h
@@ -0,0 +1,134 @@
1/*
2 * vmx.h: VMX Architecture related definitions
3 * Copyright (c) 2004, Intel Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
16 * Place - Suite 330, Boston, MA 02111-1307 USA.
17 *
18 * A few random additions are:
19 * Copyright (C) 2006 Qumranet
20 * Avi Kivity <avi@qumranet.com>
21 * Yaniv Kamay <yaniv@qumranet.com>
22 *
23 */
24#ifndef _UAPIVMX_H
25#define _UAPIVMX_H
26
27
28#define VMX_EXIT_REASONS_FAILED_VMENTRY 0x80000000
29
30#define EXIT_REASON_EXCEPTION_NMI 0
31#define EXIT_REASON_EXTERNAL_INTERRUPT 1
32#define EXIT_REASON_TRIPLE_FAULT 2
33
34#define EXIT_REASON_PENDING_INTERRUPT 7
35#define EXIT_REASON_NMI_WINDOW 8
36#define EXIT_REASON_TASK_SWITCH 9
37#define EXIT_REASON_CPUID 10
38#define EXIT_REASON_HLT 12
39#define EXIT_REASON_INVD 13
40#define EXIT_REASON_INVLPG 14
41#define EXIT_REASON_RDPMC 15
42#define EXIT_REASON_RDTSC 16
43#define EXIT_REASON_VMCALL 18
44#define EXIT_REASON_VMCLEAR 19
45#define EXIT_REASON_VMLAUNCH 20
46#define EXIT_REASON_VMPTRLD 21
47#define EXIT_REASON_VMPTRST 22
48#define EXIT_REASON_VMREAD 23
49#define EXIT_REASON_VMRESUME 24
50#define EXIT_REASON_VMWRITE 25
51#define EXIT_REASON_VMOFF 26
52#define EXIT_REASON_VMON 27
53#define EXIT_REASON_CR_ACCESS 28
54#define EXIT_REASON_DR_ACCESS 29
55#define EXIT_REASON_IO_INSTRUCTION 30
56#define EXIT_REASON_MSR_READ 31
57#define EXIT_REASON_MSR_WRITE 32
58#define EXIT_REASON_INVALID_STATE 33
59#define EXIT_REASON_MSR_LOAD_FAIL 34
60#define EXIT_REASON_MWAIT_INSTRUCTION 36
61#define EXIT_REASON_MONITOR_TRAP_FLAG 37
62#define EXIT_REASON_MONITOR_INSTRUCTION 39
63#define EXIT_REASON_PAUSE_INSTRUCTION 40
64#define EXIT_REASON_MCE_DURING_VMENTRY 41
65#define EXIT_REASON_TPR_BELOW_THRESHOLD 43
66#define EXIT_REASON_APIC_ACCESS 44
67#define EXIT_REASON_EOI_INDUCED 45
68#define EXIT_REASON_EPT_VIOLATION 48
69#define EXIT_REASON_EPT_MISCONFIG 49
70#define EXIT_REASON_INVEPT 50
71#define EXIT_REASON_RDTSCP 51
72#define EXIT_REASON_PREEMPTION_TIMER 52
73#define EXIT_REASON_INVVPID 53
74#define EXIT_REASON_WBINVD 54
75#define EXIT_REASON_XSETBV 55
76#define EXIT_REASON_APIC_WRITE 56
77#define EXIT_REASON_INVPCID 58
78#define EXIT_REASON_PML_FULL 62
79#define EXIT_REASON_XSAVES 63
80#define EXIT_REASON_XRSTORS 64
81
82#define VMX_EXIT_REASONS \
83 { EXIT_REASON_EXCEPTION_NMI, "EXCEPTION_NMI" }, \
84 { EXIT_REASON_EXTERNAL_INTERRUPT, "EXTERNAL_INTERRUPT" }, \
85 { EXIT_REASON_TRIPLE_FAULT, "TRIPLE_FAULT" }, \
86 { EXIT_REASON_PENDING_INTERRUPT, "PENDING_INTERRUPT" }, \
87 { EXIT_REASON_NMI_WINDOW, "NMI_WINDOW" }, \
88 { EXIT_REASON_TASK_SWITCH, "TASK_SWITCH" }, \
89 { EXIT_REASON_CPUID, "CPUID" }, \
90 { EXIT_REASON_HLT, "HLT" }, \
91 { EXIT_REASON_INVLPG, "INVLPG" }, \
92 { EXIT_REASON_RDPMC, "RDPMC" }, \
93 { EXIT_REASON_RDTSC, "RDTSC" }, \
94 { EXIT_REASON_VMCALL, "VMCALL" }, \
95 { EXIT_REASON_VMCLEAR, "VMCLEAR" }, \
96 { EXIT_REASON_VMLAUNCH, "VMLAUNCH" }, \
97 { EXIT_REASON_VMPTRLD, "VMPTRLD" }, \
98 { EXIT_REASON_VMPTRST, "VMPTRST" }, \
99 { EXIT_REASON_VMREAD, "VMREAD" }, \
100 { EXIT_REASON_VMRESUME, "VMRESUME" }, \
101 { EXIT_REASON_VMWRITE, "VMWRITE" }, \
102 { EXIT_REASON_VMOFF, "VMOFF" }, \
103 { EXIT_REASON_VMON, "VMON" }, \
104 { EXIT_REASON_CR_ACCESS, "CR_ACCESS" }, \
105 { EXIT_REASON_DR_ACCESS, "DR_ACCESS" }, \
106 { EXIT_REASON_IO_INSTRUCTION, "IO_INSTRUCTION" }, \
107 { EXIT_REASON_MSR_READ, "MSR_READ" }, \
108 { EXIT_REASON_MSR_WRITE, "MSR_WRITE" }, \
109 { EXIT_REASON_MWAIT_INSTRUCTION, "MWAIT_INSTRUCTION" }, \
110 { EXIT_REASON_MONITOR_TRAP_FLAG, "MONITOR_TRAP_FLAG" }, \
111 { EXIT_REASON_MONITOR_INSTRUCTION, "MONITOR_INSTRUCTION" }, \
112 { EXIT_REASON_PAUSE_INSTRUCTION, "PAUSE_INSTRUCTION" }, \
113 { EXIT_REASON_MCE_DURING_VMENTRY, "MCE_DURING_VMENTRY" }, \
114 { EXIT_REASON_TPR_BELOW_THRESHOLD, "TPR_BELOW_THRESHOLD" }, \
115 { EXIT_REASON_APIC_ACCESS, "APIC_ACCESS" }, \
116 { EXIT_REASON_EPT_VIOLATION, "EPT_VIOLATION" }, \
117 { EXIT_REASON_EPT_MISCONFIG, "EPT_MISCONFIG" }, \
118 { EXIT_REASON_INVEPT, "INVEPT" }, \
119 { EXIT_REASON_PREEMPTION_TIMER, "PREEMPTION_TIMER" }, \
120 { EXIT_REASON_WBINVD, "WBINVD" }, \
121 { EXIT_REASON_APIC_WRITE, "APIC_WRITE" }, \
122 { EXIT_REASON_EOI_INDUCED, "EOI_INDUCED" }, \
123 { EXIT_REASON_INVALID_STATE, "INVALID_STATE" }, \
124 { EXIT_REASON_MSR_LOAD_FAIL, "MSR_LOAD_FAIL" }, \
125 { EXIT_REASON_INVD, "INVD" }, \
126 { EXIT_REASON_INVVPID, "INVVPID" }, \
127 { EXIT_REASON_INVPCID, "INVPCID" }, \
128 { EXIT_REASON_XSAVES, "XSAVES" }, \
129 { EXIT_REASON_XRSTORS, "XRSTORS" }
130
131#define VMX_ABORT_SAVE_GUEST_MSR_FAIL 1
132#define VMX_ABORT_LOAD_HOST_MSR_FAIL 4
133
134#endif /* _UAPIVMX_H */
diff --git a/tools/arch/x86/lib/memcpy_64.S b/tools/arch/x86/lib/memcpy_64.S
new file mode 100644
index 000000000000..49e6ebac7e73
--- /dev/null
+++ b/tools/arch/x86/lib/memcpy_64.S
@@ -0,0 +1,297 @@
1/* Copyright 2002 Andi Kleen */
2
3#include <linux/linkage.h>
4#include <asm/errno.h>
5#include <asm/cpufeatures.h>
6#include <asm/alternative-asm.h>
7
8/*
9 * We build a jump to memcpy_orig by default which gets NOPped out on
10 * the majority of x86 CPUs which set REP_GOOD. In addition, CPUs which
11 * have the enhanced REP MOVSB/STOSB feature (ERMS), change those NOPs
12 * to a jmp to memcpy_erms which does the REP; MOVSB mem copy.
13 */
14
15.weak memcpy
16
17/*
18 * memcpy - Copy a memory block.
19 *
20 * Input:
21 * rdi destination
22 * rsi source
23 * rdx count
24 *
25 * Output:
26 * rax original destination
27 */
28ENTRY(__memcpy)
29ENTRY(memcpy)
30 ALTERNATIVE_2 "jmp memcpy_orig", "", X86_FEATURE_REP_GOOD, \
31 "jmp memcpy_erms", X86_FEATURE_ERMS
32
33 movq %rdi, %rax
34 movq %rdx, %rcx
35 shrq $3, %rcx
36 andl $7, %edx
37 rep movsq
38 movl %edx, %ecx
39 rep movsb
40 ret
41ENDPROC(memcpy)
42ENDPROC(__memcpy)
43
44/*
45 * memcpy_erms() - enhanced fast string memcpy. This is faster and
46 * simpler than memcpy. Use memcpy_erms when possible.
47 */
48ENTRY(memcpy_erms)
49 movq %rdi, %rax
50 movq %rdx, %rcx
51 rep movsb
52 ret
53ENDPROC(memcpy_erms)
54
55ENTRY(memcpy_orig)
56 movq %rdi, %rax
57
58 cmpq $0x20, %rdx
59 jb .Lhandle_tail
60
61 /*
62 * We check whether memory false dependence could occur,
63 * then jump to corresponding copy mode.
64 */
65 cmp %dil, %sil
66 jl .Lcopy_backward
67 subq $0x20, %rdx
68.Lcopy_forward_loop:
69 subq $0x20, %rdx
70
71 /*
72 * Move in blocks of 4x8 bytes:
73 */
74 movq 0*8(%rsi), %r8
75 movq 1*8(%rsi), %r9
76 movq 2*8(%rsi), %r10
77 movq 3*8(%rsi), %r11
78 leaq 4*8(%rsi), %rsi
79
80 movq %r8, 0*8(%rdi)
81 movq %r9, 1*8(%rdi)
82 movq %r10, 2*8(%rdi)
83 movq %r11, 3*8(%rdi)
84 leaq 4*8(%rdi), %rdi
85 jae .Lcopy_forward_loop
86 addl $0x20, %edx
87 jmp .Lhandle_tail
88
89.Lcopy_backward:
90 /*
91 * Calculate copy position to tail.
92 */
93 addq %rdx, %rsi
94 addq %rdx, %rdi
95 subq $0x20, %rdx
96 /*
97 * At most 3 ALU operations in one cycle,
98 * so append NOPS in the same 16 bytes trunk.
99 */
100 .p2align 4
101.Lcopy_backward_loop:
102 subq $0x20, %rdx
103 movq -1*8(%rsi), %r8
104 movq -2*8(%rsi), %r9
105 movq -3*8(%rsi), %r10
106 movq -4*8(%rsi), %r11
107 leaq -4*8(%rsi), %rsi
108 movq %r8, -1*8(%rdi)
109 movq %r9, -2*8(%rdi)
110 movq %r10, -3*8(%rdi)
111 movq %r11, -4*8(%rdi)
112 leaq -4*8(%rdi), %rdi
113 jae .Lcopy_backward_loop
114
115 /*
116 * Calculate copy position to head.
117 */
118 addl $0x20, %edx
119 subq %rdx, %rsi
120 subq %rdx, %rdi
121.Lhandle_tail:
122 cmpl $16, %edx
123 jb .Lless_16bytes
124
125 /*
126 * Move data from 16 bytes to 31 bytes.
127 */
128 movq 0*8(%rsi), %r8
129 movq 1*8(%rsi), %r9
130 movq -2*8(%rsi, %rdx), %r10
131 movq -1*8(%rsi, %rdx), %r11
132 movq %r8, 0*8(%rdi)
133 movq %r9, 1*8(%rdi)
134 movq %r10, -2*8(%rdi, %rdx)
135 movq %r11, -1*8(%rdi, %rdx)
136 retq
137 .p2align 4
138.Lless_16bytes:
139 cmpl $8, %edx
140 jb .Lless_8bytes
141 /*
142 * Move data from 8 bytes to 15 bytes.
143 */
144 movq 0*8(%rsi), %r8
145 movq -1*8(%rsi, %rdx), %r9
146 movq %r8, 0*8(%rdi)
147 movq %r9, -1*8(%rdi, %rdx)
148 retq
149 .p2align 4
150.Lless_8bytes:
151 cmpl $4, %edx
152 jb .Lless_3bytes
153
154 /*
155 * Move data from 4 bytes to 7 bytes.
156 */
157 movl (%rsi), %ecx
158 movl -4(%rsi, %rdx), %r8d
159 movl %ecx, (%rdi)
160 movl %r8d, -4(%rdi, %rdx)
161 retq
162 .p2align 4
163.Lless_3bytes:
164 subl $1, %edx
165 jb .Lend
166 /*
167 * Move data from 1 bytes to 3 bytes.
168 */
169 movzbl (%rsi), %ecx
170 jz .Lstore_1byte
171 movzbq 1(%rsi), %r8
172 movzbq (%rsi, %rdx), %r9
173 movb %r8b, 1(%rdi)
174 movb %r9b, (%rdi, %rdx)
175.Lstore_1byte:
176 movb %cl, (%rdi)
177
178.Lend:
179 retq
180ENDPROC(memcpy_orig)
181
182#ifndef CONFIG_UML
183/*
184 * memcpy_mcsafe_unrolled - memory copy with machine check exception handling
185 * Note that we only catch machine checks when reading the source addresses.
186 * Writes to target are posted and don't generate machine checks.
187 */
188ENTRY(memcpy_mcsafe_unrolled)
189 cmpl $8, %edx
190 /* Less than 8 bytes? Go to byte copy loop */
191 jb .L_no_whole_words
192
193 /* Check for bad alignment of source */
194 testl $7, %esi
195 /* Already aligned */
196 jz .L_8byte_aligned
197
198 /* Copy one byte at a time until source is 8-byte aligned */
199 movl %esi, %ecx
200 andl $7, %ecx
201 subl $8, %ecx
202 negl %ecx
203 subl %ecx, %edx
204.L_copy_leading_bytes:
205 movb (%rsi), %al
206 movb %al, (%rdi)
207 incq %rsi
208 incq %rdi
209 decl %ecx
210 jnz .L_copy_leading_bytes
211
212.L_8byte_aligned:
213 /* Figure out how many whole cache lines (64-bytes) to copy */
214 movl %edx, %ecx
215 andl $63, %edx
216 shrl $6, %ecx
217 jz .L_no_whole_cache_lines
218
219 /* Loop copying whole cache lines */
220.L_cache_w0: movq (%rsi), %r8
221.L_cache_w1: movq 1*8(%rsi), %r9
222.L_cache_w2: movq 2*8(%rsi), %r10
223.L_cache_w3: movq 3*8(%rsi), %r11
224 movq %r8, (%rdi)
225 movq %r9, 1*8(%rdi)
226 movq %r10, 2*8(%rdi)
227 movq %r11, 3*8(%rdi)
228.L_cache_w4: movq 4*8(%rsi), %r8
229.L_cache_w5: movq 5*8(%rsi), %r9
230.L_cache_w6: movq 6*8(%rsi), %r10
231.L_cache_w7: movq 7*8(%rsi), %r11
232 movq %r8, 4*8(%rdi)
233 movq %r9, 5*8(%rdi)
234 movq %r10, 6*8(%rdi)
235 movq %r11, 7*8(%rdi)
236 leaq 64(%rsi), %rsi
237 leaq 64(%rdi), %rdi
238 decl %ecx
239 jnz .L_cache_w0
240
241 /* Are there any trailing 8-byte words? */
242.L_no_whole_cache_lines:
243 movl %edx, %ecx
244 andl $7, %edx
245 shrl $3, %ecx
246 jz .L_no_whole_words
247
248 /* Copy trailing words */
249.L_copy_trailing_words:
250 movq (%rsi), %r8
251 mov %r8, (%rdi)
252 leaq 8(%rsi), %rsi
253 leaq 8(%rdi), %rdi
254 decl %ecx
255 jnz .L_copy_trailing_words
256
257 /* Any trailing bytes? */
258.L_no_whole_words:
259 andl %edx, %edx
260 jz .L_done_memcpy_trap
261
262 /* Copy trailing bytes */
263 movl %edx, %ecx
264.L_copy_trailing_bytes:
265 movb (%rsi), %al
266 movb %al, (%rdi)
267 incq %rsi
268 incq %rdi
269 decl %ecx
270 jnz .L_copy_trailing_bytes
271
272 /* Copy successful. Return zero */
273.L_done_memcpy_trap:
274 xorq %rax, %rax
275 ret
276ENDPROC(memcpy_mcsafe_unrolled)
277
278 .section .fixup, "ax"
279 /* Return -EFAULT for any failure */
280.L_memcpy_mcsafe_fail:
281 mov $-EFAULT, %rax
282 ret
283
284 .previous
285
286 _ASM_EXTABLE_FAULT(.L_copy_leading_bytes, .L_memcpy_mcsafe_fail)
287 _ASM_EXTABLE_FAULT(.L_cache_w0, .L_memcpy_mcsafe_fail)
288 _ASM_EXTABLE_FAULT(.L_cache_w1, .L_memcpy_mcsafe_fail)
289 _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
290 _ASM_EXTABLE_FAULT(.L_cache_w3, .L_memcpy_mcsafe_fail)
291 _ASM_EXTABLE_FAULT(.L_cache_w4, .L_memcpy_mcsafe_fail)
292 _ASM_EXTABLE_FAULT(.L_cache_w5, .L_memcpy_mcsafe_fail)
293 _ASM_EXTABLE_FAULT(.L_cache_w6, .L_memcpy_mcsafe_fail)
294 _ASM_EXTABLE_FAULT(.L_cache_w7, .L_memcpy_mcsafe_fail)
295 _ASM_EXTABLE_FAULT(.L_copy_trailing_words, .L_memcpy_mcsafe_fail)
296 _ASM_EXTABLE_FAULT(.L_copy_trailing_bytes, .L_memcpy_mcsafe_fail)
297#endif
diff --git a/tools/arch/x86/lib/memset_64.S b/tools/arch/x86/lib/memset_64.S
new file mode 100644
index 000000000000..e1229ecd2a82
--- /dev/null
+++ b/tools/arch/x86/lib/memset_64.S
@@ -0,0 +1,138 @@
1/* Copyright 2002 Andi Kleen, SuSE Labs */
2
3#include <linux/linkage.h>
4#include <asm/cpufeatures.h>
5#include <asm/alternative-asm.h>
6
7.weak memset
8
9/*
10 * ISO C memset - set a memory block to a byte value. This function uses fast
11 * string to get better performance than the original function. The code is
12 * simpler and shorter than the original function as well.
13 *
14 * rdi destination
15 * rsi value (char)
16 * rdx count (bytes)
17 *
18 * rax original destination
19 */
20ENTRY(memset)
21ENTRY(__memset)
22 /*
23 * Some CPUs support enhanced REP MOVSB/STOSB feature. It is recommended
24 * to use it when possible. If not available, use fast string instructions.
25 *
26 * Otherwise, use original memset function.
27 */
28 ALTERNATIVE_2 "jmp memset_orig", "", X86_FEATURE_REP_GOOD, \
29 "jmp memset_erms", X86_FEATURE_ERMS
30
31 movq %rdi,%r9
32 movq %rdx,%rcx
33 andl $7,%edx
34 shrq $3,%rcx
35 /* expand byte value */
36 movzbl %sil,%esi
37 movabs $0x0101010101010101,%rax
38 imulq %rsi,%rax
39 rep stosq
40 movl %edx,%ecx
41 rep stosb
42 movq %r9,%rax
43 ret
44ENDPROC(memset)
45ENDPROC(__memset)
46
47/*
48 * ISO C memset - set a memory block to a byte value. This function uses
49 * enhanced rep stosb to override the fast string function.
50 * The code is simpler and shorter than the fast string function as well.
51 *
52 * rdi destination
53 * rsi value (char)
54 * rdx count (bytes)
55 *
56 * rax original destination
57 */
58ENTRY(memset_erms)
59 movq %rdi,%r9
60 movb %sil,%al
61 movq %rdx,%rcx
62 rep stosb
63 movq %r9,%rax
64 ret
65ENDPROC(memset_erms)
66
67ENTRY(memset_orig)
68 movq %rdi,%r10
69
70 /* expand byte value */
71 movzbl %sil,%ecx
72 movabs $0x0101010101010101,%rax
73 imulq %rcx,%rax
74
75 /* align dst */
76 movl %edi,%r9d
77 andl $7,%r9d
78 jnz .Lbad_alignment
79.Lafter_bad_alignment:
80
81 movq %rdx,%rcx
82 shrq $6,%rcx
83 jz .Lhandle_tail
84
85 .p2align 4
86.Lloop_64:
87 decq %rcx
88 movq %rax,(%rdi)
89 movq %rax,8(%rdi)
90 movq %rax,16(%rdi)
91 movq %rax,24(%rdi)
92 movq %rax,32(%rdi)
93 movq %rax,40(%rdi)
94 movq %rax,48(%rdi)
95 movq %rax,56(%rdi)
96 leaq 64(%rdi),%rdi
97 jnz .Lloop_64
98
99 /* Handle tail in loops. The loops should be faster than hard
100 to predict jump tables. */
101 .p2align 4
102.Lhandle_tail:
103 movl %edx,%ecx
104 andl $63&(~7),%ecx
105 jz .Lhandle_7
106 shrl $3,%ecx
107 .p2align 4
108.Lloop_8:
109 decl %ecx
110 movq %rax,(%rdi)
111 leaq 8(%rdi),%rdi
112 jnz .Lloop_8
113
114.Lhandle_7:
115 andl $7,%edx
116 jz .Lende
117 .p2align 4
118.Lloop_1:
119 decl %edx
120 movb %al,(%rdi)
121 leaq 1(%rdi),%rdi
122 jnz .Lloop_1
123
124.Lende:
125 movq %r10,%rax
126 ret
127
128.Lbad_alignment:
129 cmpq $7,%rdx
130 jbe .Lhandle_7
131 movq %rax,(%rdi) /* unaligned store */
132 movq $8,%r8
133 subq %r9,%r8
134 addq %r8,%rdi
135 subq %r8,%rdx
136 jmp .Lafter_bad_alignment
137.Lfinal:
138ENDPROC(memset_orig)
diff --git a/tools/arch/xtensa/include/uapi/asm/mman.h b/tools/arch/xtensa/include/uapi/asm/mman.h
new file mode 100644
index 000000000000..4453195c450c
--- /dev/null
+++ b/tools/arch/xtensa/include/uapi/asm/mman.h
@@ -0,0 +1,47 @@
1#ifndef TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H
2#define TOOLS_ARCH_XTENSA_UAPI_ASM_MMAN_FIX_H
3#define MADV_DODUMP 17
4#define MADV_DOFORK 11
5#define MADV_DONTDUMP 16
6#define MADV_DONTFORK 10
7#define MADV_DONTNEED 4
8#define MADV_FREE 8
9#define MADV_HUGEPAGE 14
10#define MADV_MERGEABLE 12
11#define MADV_NOHUGEPAGE 15
12#define MADV_NORMAL 0
13#define MADV_RANDOM 1
14#define MADV_REMOVE 9
15#define MADV_SEQUENTIAL 2
16#define MADV_UNMERGEABLE 13
17#define MADV_WILLNEED 3
18#define MAP_ANONYMOUS 0x0800
19#define MAP_DENYWRITE 0x2000
20#define MAP_EXECUTABLE 0x4000
21#define MAP_FILE 0
22#define MAP_FIXED 0x010
23#define MAP_GROWSDOWN 0x1000
24#define MAP_HUGETLB 0x80000
25#define MAP_LOCKED 0x8000
26#define MAP_NONBLOCK 0x20000
27#define MAP_NORESERVE 0x0400
28#define MAP_POPULATE 0x10000
29#define MAP_PRIVATE 0x002
30#define MAP_SHARED 0x001
31#define MAP_STACK 0x40000
32#define PROT_EXEC 0x4
33#define PROT_GROWSDOWN 0x01000000
34#define PROT_GROWSUP 0x02000000
35#define PROT_NONE 0x0
36#define PROT_READ 0x1
37#define PROT_SEM 0x10
38#define PROT_WRITE 0x2
39/* MADV_HWPOISON is undefined on xtensa, fix it for perf */
40#define MADV_HWPOISON 100
41/* MADV_SOFT_OFFLINE is undefined on xtensa, fix it for perf */
42#define MADV_SOFT_OFFLINE 101
43/* MAP_32BIT is undefined on xtensa, fix it for perf */
44#define MAP_32BIT 0
45/* MAP_UNINITIALIZED is undefined on xtensa, fix it for perf */
46#define MAP_UNINITIALIZED 0
47#endif
diff --git a/tools/build/Build b/tools/build/Build
index 63a6c34c0c88..76d1a4960973 100644
--- a/tools/build/Build
+++ b/tools/build/Build
@@ -1 +1,3 @@
1hostprogs := fixdep
2
1fixdep-y := fixdep.o 3fixdep-y := fixdep.o
diff --git a/tools/build/Build.include b/tools/build/Build.include
index 4d000bc959b4..1dcb95e76f70 100644
--- a/tools/build/Build.include
+++ b/tools/build/Build.include
@@ -90,3 +90,9 @@ if_changed = $(if $(strip $(any-prereq) $(arg-check)), \
90# - per object C flags 90# - per object C flags
91# - BUILD_STR macro to allow '-D"$(variable)"' constructs 91# - BUILD_STR macro to allow '-D"$(variable)"' constructs
92c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj)) 92c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CFLAGS) -D"BUILD_STR(s)=\#s" $(CFLAGS_$(basetarget).o) $(CFLAGS_$(obj))
93cxx_flags = -Wp,-MD,$(depfile),-MT,$@ $(CXXFLAGS) -D"BUILD_STR(s)=\#s" $(CXXFLAGS_$(basetarget).o) $(CXXFLAGS_$(obj))
94
95###
96## HOSTCC C flags
97
98host_c_flags = -Wp,-MD,$(depfile),-MT,$@ $(CHOSTFLAGS) -D"BUILD_STR(s)=\#s" $(CHOSTFLAGS_$(basetarget).o) $(CHOSTFLAGS_$(obj))
diff --git a/tools/build/Makefile b/tools/build/Makefile
index 0d5a0e3a8fa9..8332959fbca4 100644
--- a/tools/build/Makefile
+++ b/tools/build/Makefile
@@ -14,6 +14,12 @@ endef
14$(call allow-override,CC,$(CROSS_COMPILE)gcc) 14$(call allow-override,CC,$(CROSS_COMPILE)gcc)
15$(call allow-override,LD,$(CROSS_COMPILE)ld) 15$(call allow-override,LD,$(CROSS_COMPILE)ld)
16 16
17HOSTCC ?= gcc
18HOSTLD ?= ld
19HOSTAR ?= ar
20
21export HOSTCC HOSTLD HOSTAR
22
17ifeq ($(V),1) 23ifeq ($(V),1)
18 Q = 24 Q =
19else 25else
@@ -36,7 +42,7 @@ $(OUTPUT)fixdep-in.o: FORCE
36 $(Q)$(MAKE) $(build)=fixdep 42 $(Q)$(MAKE) $(build)=fixdep
37 43
38$(OUTPUT)fixdep: $(OUTPUT)fixdep-in.o 44$(OUTPUT)fixdep: $(OUTPUT)fixdep-in.o
39 $(QUIET_LINK)$(CC) $(LDFLAGS) -o $@ $< 45 $(QUIET_LINK)$(HOSTCC) $(LDFLAGS) -o $@ $<
40 46
41FORCE: 47FORCE:
42 48
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index 27f3583193e6..99c0ccd2f176 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -58,6 +58,12 @@ quiet_cmd_mkdir = MKDIR $(dir $@)
58quiet_cmd_cc_o_c = CC $@ 58quiet_cmd_cc_o_c = CC $@
59 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< 59 cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
60 60
61quiet_cmd_host_cc_o_c = HOSTCC $@
62 cmd_host_cc_o_c = $(HOSTCC) $(host_c_flags) -c -o $@ $<
63
64quiet_cmd_cxx_o_c = CXX $@
65 cmd_cxx_o_c = $(CXX) $(cxx_flags) -c -o $@ $<
66
61quiet_cmd_cpp_i_c = CPP $@ 67quiet_cmd_cpp_i_c = CPP $@
62 cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $< 68 cmd_cpp_i_c = $(CC) $(c_flags) -E -o $@ $<
63 69
@@ -70,16 +76,28 @@ quiet_cmd_gen = GEN $@
70# If there's nothing to link, create empty $@ object. 76# If there's nothing to link, create empty $@ object.
71quiet_cmd_ld_multi = LD $@ 77quiet_cmd_ld_multi = LD $@
72 cmd_ld_multi = $(if $(strip $(obj-y)),\ 78 cmd_ld_multi = $(if $(strip $(obj-y)),\
73 $(LD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(AR) rcs $@) 79 $(LD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(AR) rcs $@)
80
81quiet_cmd_host_ld_multi = HOSTLD $@
82 cmd_host_ld_multi = $(if $(strip $(obj-y)),\
83 $(HOSTLD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(HOSTAR) rcs $@)
84
85ifneq ($(filter $(obj),$(hostprogs)),)
86 host = host_
87endif
74 88
75# Build rules 89# Build rules
76$(OUTPUT)%.o: %.c FORCE 90$(OUTPUT)%.o: %.c FORCE
77 $(call rule_mkdir) 91 $(call rule_mkdir)
78 $(call if_changed_dep,cc_o_c) 92 $(call if_changed_dep,$(host)cc_o_c)
93
94$(OUTPUT)%.o: %.cpp FORCE
95 $(call rule_mkdir)
96 $(call if_changed_dep,cxx_o_c)
79 97
80$(OUTPUT)%.o: %.S FORCE 98$(OUTPUT)%.o: %.S FORCE
81 $(call rule_mkdir) 99 $(call rule_mkdir)
82 $(call if_changed_dep,cc_o_c) 100 $(call if_changed_dep,$(host)cc_o_c)
83 101
84$(OUTPUT)%.i: %.c FORCE 102$(OUTPUT)%.i: %.c FORCE
85 $(call rule_mkdir) 103 $(call rule_mkdir)
@@ -119,7 +137,7 @@ $(sort $(subdir-obj-y)): $(subdir-y) ;
119 137
120$(in-target): $(obj-y) FORCE 138$(in-target): $(obj-y) FORCE
121 $(call rule_mkdir) 139 $(call rule_mkdir)
122 $(call if_changed,ld_multi) 140 $(call if_changed,$(host)ld_multi)
123 141
124__build: $(in-target) 142__build: $(in-target)
125 @: 143 @:
diff --git a/tools/build/Makefile.feature b/tools/build/Makefile.feature
index 57c8f98874e8..ae52e029dd22 100644
--- a/tools/build/Makefile.feature
+++ b/tools/build/Makefile.feature
@@ -7,7 +7,7 @@ endif
7 7
8feature_check = $(eval $(feature_check_code)) 8feature_check = $(eval $(feature_check_code))
9define feature_check_code 9define feature_check_code
10 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0) 10 feature-$(1) := $(shell $(MAKE) OUTPUT=$(OUTPUT_FEATURES) CFLAGS="$(EXTRA_CFLAGS) $(FEATURE_CHECK_CFLAGS-$(1))" CXXFLAGS="$(EXTRA_CXXFLAGS) $(FEATURE_CHECK_CXXFLAGS-$(1))" LDFLAGS="$(LDFLAGS) $(FEATURE_CHECK_LDFLAGS-$(1))" -C $(feature_dir) $(OUTPUT_FEATURES)test-$1.bin >/dev/null 2>/dev/null && echo 1 || echo 0)
11endef 11endef
12 12
13feature_set = $(eval $(feature_set_code)) 13feature_set = $(eval $(feature_set_code))
@@ -40,6 +40,8 @@ FEATURE_TESTS_BASIC := \
40 libbfd \ 40 libbfd \
41 libelf \ 41 libelf \
42 libelf-getphdrnum \ 42 libelf-getphdrnum \
43 libelf-gelf_getnote \
44 libelf-getshdrstrndx \
43 libelf-mmap \ 45 libelf-mmap \
44 libnuma \ 46 libnuma \
45 numa_num_possible_cpus \ 47 numa_num_possible_cpus \
@@ -60,7 +62,8 @@ FEATURE_TESTS_BASIC := \
60 zlib \ 62 zlib \
61 lzma \ 63 lzma \
62 get_cpuid \ 64 get_cpuid \
63 bpf 65 bpf \
66 sdt
64 67
65# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list 68# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
66# of all feature tests 69# of all feature tests
diff --git a/tools/build/Makefile.include b/tools/build/Makefile.include
index be630bed66d2..ad22e4e7bc59 100644
--- a/tools/build/Makefile.include
+++ b/tools/build/Makefile.include
@@ -1,10 +1,6 @@
1build := -f $(srctree)/tools/build/Makefile.build dir=. obj 1build := -f $(srctree)/tools/build/Makefile.build dir=. obj
2 2
3ifdef CROSS_COMPILE
4fixdep:
5else
6fixdep: 3fixdep:
7 $(Q)$(MAKE) -C $(srctree)/tools/build CFLAGS= LDFLAGS= $(OUTPUT)fixdep 4 $(Q)$(MAKE) -C $(srctree)/tools/build CFLAGS= LDFLAGS= $(OUTPUT)fixdep
8endif
9 5
10.PHONY: fixdep 6.PHONY: fixdep
diff --git a/tools/build/feature/Makefile b/tools/build/feature/Makefile
index 3d88f09e188b..ac9c477a2a48 100644
--- a/tools/build/feature/Makefile
+++ b/tools/build/feature/Makefile
@@ -17,6 +17,8 @@ FILES= \
17 test-cplus-demangle.bin \ 17 test-cplus-demangle.bin \
18 test-libelf.bin \ 18 test-libelf.bin \
19 test-libelf-getphdrnum.bin \ 19 test-libelf-getphdrnum.bin \
20 test-libelf-gelf_getnote.bin \
21 test-libelf-getshdrstrndx.bin \
20 test-libelf-mmap.bin \ 22 test-libelf-mmap.bin \
21 test-libnuma.bin \ 23 test-libnuma.bin \
22 test-numa_num_possible_cpus.bin \ 24 test-numa_num_possible_cpus.bin \
@@ -43,11 +45,14 @@ FILES= \
43 test-zlib.bin \ 45 test-zlib.bin \
44 test-lzma.bin \ 46 test-lzma.bin \
45 test-bpf.bin \ 47 test-bpf.bin \
46 test-get_cpuid.bin 48 test-get_cpuid.bin \
49 test-sdt.bin \
50 test-cxx.bin
47 51
48FILES := $(addprefix $(OUTPUT),$(FILES)) 52FILES := $(addprefix $(OUTPUT),$(FILES))
49 53
50CC := $(CROSS_COMPILE)gcc -MD 54CC := $(CROSS_COMPILE)gcc -MD
55CXX := $(CROSS_COMPILE)g++ -MD
51PKG_CONFIG := $(CROSS_COMPILE)pkg-config 56PKG_CONFIG := $(CROSS_COMPILE)pkg-config
52 57
53all: $(FILES) 58all: $(FILES)
@@ -55,6 +60,9 @@ all: $(FILES)
55__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS) 60__BUILD = $(CC) $(CFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.c,$(@F)) $(LDFLAGS)
56 BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1 61 BUILD = $(__BUILD) > $(@:.bin=.make.output) 2>&1
57 62
63__BUILDXX = $(CXX) $(CXXFLAGS) -Wall -Werror -o $@ $(patsubst %.bin,%.cpp,$(@F)) $(LDFLAGS)
64 BUILDXX = $(__BUILDXX) > $(@:.bin=.make.output) 2>&1
65
58############################### 66###############################
59 67
60$(OUTPUT)test-all.bin: 68$(OUTPUT)test-all.bin:
@@ -98,6 +106,12 @@ $(OUTPUT)test-libelf-mmap.bin:
98$(OUTPUT)test-libelf-getphdrnum.bin: 106$(OUTPUT)test-libelf-getphdrnum.bin:
99 $(BUILD) -lelf 107 $(BUILD) -lelf
100 108
109$(OUTPUT)test-libelf-gelf_getnote.bin:
110 $(BUILD) -lelf
111
112$(OUTPUT)test-libelf-getshdrstrndx.bin:
113 $(BUILD) -lelf
114
101$(OUTPUT)test-libnuma.bin: 115$(OUTPUT)test-libnuma.bin:
102 $(BUILD) -lnuma 116 $(BUILD) -lnuma
103 117
@@ -205,6 +219,12 @@ $(OUTPUT)test-get_cpuid.bin:
205$(OUTPUT)test-bpf.bin: 219$(OUTPUT)test-bpf.bin:
206 $(BUILD) 220 $(BUILD)
207 221
222$(OUTPUT)test-sdt.bin:
223 $(BUILD)
224
225$(OUTPUT)test-cxx.bin:
226 $(BUILDXX) -std=gnu++11
227
208-include $(OUTPUT)*.d 228-include $(OUTPUT)*.d
209 229
210############################### 230###############################
diff --git a/tools/build/feature/test-all.c b/tools/build/feature/test-all.c
index a282e8cb84f3..699e43627397 100644
--- a/tools/build/feature/test-all.c
+++ b/tools/build/feature/test-all.c
@@ -49,6 +49,14 @@
49# include "test-libelf-getphdrnum.c" 49# include "test-libelf-getphdrnum.c"
50#undef main 50#undef main
51 51
52#define main main_test_libelf_gelf_getnote
53# include "test-libelf-gelf_getnote.c"
54#undef main
55
56#define main main_test_libelf_getshdrstrndx
57# include "test-libelf-getshdrstrndx.c"
58#undef main
59
52#define main main_test_libunwind 60#define main main_test_libunwind
53# include "test-libunwind.c" 61# include "test-libunwind.c"
54#undef main 62#undef main
@@ -137,6 +145,10 @@
137# include "test-libcrypto.c" 145# include "test-libcrypto.c"
138#undef main 146#undef main
139 147
148#define main main_test_sdt
149# include "test-sdt.c"
150#undef main
151
140int main(int argc, char *argv[]) 152int main(int argc, char *argv[])
141{ 153{
142 main_test_libpython(); 154 main_test_libpython();
@@ -149,6 +161,8 @@ int main(int argc, char *argv[])
149 main_test_dwarf(); 161 main_test_dwarf();
150 main_test_dwarf_getlocations(); 162 main_test_dwarf_getlocations();
151 main_test_libelf_getphdrnum(); 163 main_test_libelf_getphdrnum();
164 main_test_libelf_gelf_getnote();
165 main_test_libelf_getshdrstrndx();
152 main_test_libunwind(); 166 main_test_libunwind();
153 main_test_libaudit(); 167 main_test_libaudit();
154 main_test_libslang(); 168 main_test_libslang();
@@ -168,6 +182,7 @@ int main(int argc, char *argv[])
168 main_test_get_cpuid(); 182 main_test_get_cpuid();
169 main_test_bpf(); 183 main_test_bpf();
170 main_test_libcrypto(); 184 main_test_libcrypto();
185 main_test_sdt();
171 186
172 return 0; 187 return 0;
173} 188}
diff --git a/tools/build/feature/test-cxx.cpp b/tools/build/feature/test-cxx.cpp
new file mode 100644
index 000000000000..b1dee9a31d6c
--- /dev/null
+++ b/tools/build/feature/test-cxx.cpp
@@ -0,0 +1,15 @@
1#include <iostream>
2#include <memory>
3
4static void print_str(std::string s)
5{
6 std::cout << s << std::endl;
7}
8
9int main()
10{
11 std::string s("Hello World!");
12 print_str(std::move(s));
13 std::cout << "|" << s << "|" << std::endl;
14 return 0;
15}
diff --git a/tools/build/feature/test-libelf-gelf_getnote.c b/tools/build/feature/test-libelf-gelf_getnote.c
new file mode 100644
index 000000000000..d78cf4d5271f
--- /dev/null
+++ b/tools/build/feature/test-libelf-gelf_getnote.c
@@ -0,0 +1,7 @@
1#include <stdlib.h>
2#include <gelf.h>
3
4int main(void)
5{
6 return gelf_getnote(NULL, 0, NULL, NULL, NULL);
7}
diff --git a/tools/build/feature/test-libelf-getshdrstrndx.c b/tools/build/feature/test-libelf-getshdrstrndx.c
new file mode 100644
index 000000000000..f0c3b47cce28
--- /dev/null
+++ b/tools/build/feature/test-libelf-getshdrstrndx.c
@@ -0,0 +1,8 @@
1#include <libelf.h>
2
3int main(void)
4{
5 size_t dst;
6
7 return elf_getshdrstrndx(0, &dst);
8}
diff --git a/tools/build/feature/test-sdt.c b/tools/build/feature/test-sdt.c
new file mode 100644
index 000000000000..e4531a6e80ea
--- /dev/null
+++ b/tools/build/feature/test-sdt.c
@@ -0,0 +1,7 @@
1#include <sys/sdt.h>
2
3int main(void)
4{
5 DTRACE_PROBE(provider, name);
6 return 0;
7}
diff --git a/tools/gpio/Build b/tools/gpio/Build
new file mode 100644
index 000000000000..620c1937d957
--- /dev/null
+++ b/tools/gpio/Build
@@ -0,0 +1,3 @@
1lsgpio-y += lsgpio.o gpio-utils.o
2gpio-hammer-y += gpio-hammer.o gpio-utils.o
3gpio-event-mon-y += gpio-event-mon.o gpio-utils.o
diff --git a/tools/gpio/Makefile b/tools/gpio/Makefile
index c155d6bc47a7..250a891e6ef0 100644
--- a/tools/gpio/Makefile
+++ b/tools/gpio/Makefile
@@ -1,12 +1,75 @@
1include ../scripts/Makefile.include
2
3bindir ?= /usr/bin
4
5ifeq ($(srctree),)
6srctree := $(patsubst %/,%,$(dir $(shell pwd)))
7srctree := $(patsubst %/,%,$(dir $(srctree)))
8endif
9
10# Do not use make's built-in rules
11# (this improves performance and avoids hard-to-debug behaviour);
12MAKEFLAGS += -r
13
1CC = $(CROSS_COMPILE)gcc 14CC = $(CROSS_COMPILE)gcc
2CFLAGS += -O2 -Wall -g -D_GNU_SOURCE 15LD = $(CROSS_COMPILE)ld
16CFLAGS += -O2 -Wall -g -D_GNU_SOURCE -I$(OUTPUT)include
17
18ALL_TARGETS := lsgpio gpio-hammer gpio-event-mon
19ALL_PROGRAMS := $(patsubst %,$(OUTPUT)%,$(ALL_TARGETS))
20
21all: $(ALL_PROGRAMS)
3 22
4all: lsgpio 23export srctree OUTPUT CC LD CFLAGS
24include $(srctree)/tools/build/Makefile.include
5 25
6lsgpio: lsgpio.o gpio-utils.o 26#
27# We need the following to be outside of kernel tree
28#
29$(OUTPUT)include/linux/gpio.h: ../../include/uapi/linux/gpio.h
30 mkdir -p $(OUTPUT)include/linux 2>&1 || true
31 ln -sf $(CURDIR)/../../include/uapi/linux/gpio.h $@
7 32
8%.o: %.c gpio-utils.h 33prepare: $(OUTPUT)include/linux/gpio.h
34
35#
36# lsgpio
37#
38LSGPIO_IN := $(OUTPUT)lsgpio-in.o
39$(LSGPIO_IN): prepare FORCE
40 $(Q)$(MAKE) $(build)=lsgpio
41$(OUTPUT)lsgpio: $(LSGPIO_IN)
42 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
43
44#
45# gpio-hammer
46#
47GPIO_HAMMER_IN := $(OUTPUT)gpio-hammer-in.o
48$(GPIO_HAMMER_IN): prepare FORCE
49 $(Q)$(MAKE) $(build)=gpio-hammer
50$(OUTPUT)gpio-hammer: $(GPIO_HAMMER_IN)
51 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
52
53#
54# gpio-event-mon
55#
56GPIO_EVENT_MON_IN := $(OUTPUT)gpio-event-mon-in.o
57$(GPIO_EVENT_MON_IN): prepare FORCE
58 $(Q)$(MAKE) $(build)=gpio-event-mon
59$(OUTPUT)gpio-event-mon: $(GPIO_EVENT_MON_IN)
60 $(QUIET_LINK)$(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
9 61
10.PHONY: clean
11clean: 62clean:
12 rm -f *.o lsgpio 63 rm -f $(ALL_PROGRAMS)
64 rm -f $(OUTPUT)include/linux/gpio.h
65 find $(if $(OUTPUT),$(OUTPUT),.) -name '*.o' -delete -o -name '\.*.d' -delete
66
67install: $(ALL_PROGRAMS)
68 install -d -m 755 $(DESTDIR)$(bindir); \
69 for program in $(ALL_PROGRAMS); do \
70 install $$program $(DESTDIR)$(bindir); \
71 done
72
73FORCE:
74
75.PHONY: all install clean FORCE prepare
diff --git a/tools/gpio/gpio-event-mon.c b/tools/gpio/gpio-event-mon.c
new file mode 100644
index 000000000000..1c14c2595158
--- /dev/null
+++ b/tools/gpio/gpio-event-mon.c
@@ -0,0 +1,192 @@
1/*
2 * gpio-event-mon - monitor GPIO line events from userspace
3 *
4 * Copyright (C) 2016 Linus Walleij
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * Usage:
11 * gpio-event-mon -n <device-name> -o <offset>
12 */
13
14#include <unistd.h>
15#include <stdlib.h>
16#include <stdbool.h>
17#include <stdio.h>
18#include <dirent.h>
19#include <errno.h>
20#include <string.h>
21#include <poll.h>
22#include <fcntl.h>
23#include <getopt.h>
24#include <inttypes.h>
25#include <sys/ioctl.h>
26#include <linux/gpio.h>
27
28int monitor_device(const char *device_name,
29 unsigned int line,
30 u_int32_t handleflags,
31 u_int32_t eventflags,
32 unsigned int loops)
33{
34 struct gpioevent_request req;
35 struct gpiohandle_data data;
36 char *chrdev_name;
37 int fd;
38 int ret;
39 int i = 0;
40
41 ret = asprintf(&chrdev_name, "/dev/%s", device_name);
42 if (ret < 0)
43 return -ENOMEM;
44
45 fd = open(chrdev_name, 0);
46 if (fd == -1) {
47 ret = -errno;
48 fprintf(stderr, "Failed to open %s\n", chrdev_name);
49 goto exit_close_error;
50 }
51
52 req.lineoffset = line;
53 req.handleflags = handleflags;
54 req.eventflags = eventflags;
55 strcpy(req.consumer_label, "gpio-event-mon");
56
57 ret = ioctl(fd, GPIO_GET_LINEEVENT_IOCTL, &req);
58 if (ret == -1) {
59 ret = -errno;
60 fprintf(stderr, "Failed to issue GET EVENT "
61 "IOCTL (%d)\n",
62 ret);
63 goto exit_close_error;
64 }
65
66 /* Read initial states */
67 ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
68 if (ret == -1) {
69 ret = -errno;
70 fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
71 "VALUES IOCTL (%d)\n",
72 ret);
73 goto exit_close_error;
74 }
75
76 fprintf(stdout, "Monitoring line %d on %s\n", line, device_name);
77 fprintf(stdout, "Initial line value: %d\n", data.values[0]);
78
79 while (1) {
80 struct gpioevent_data event;
81
82 ret = read(req.fd, &event, sizeof(event));
83 if (ret == -1) {
84 if (errno == -EAGAIN) {
85 fprintf(stderr, "nothing available\n");
86 continue;
87 } else {
88 ret = -errno;
89 fprintf(stderr, "Failed to read event (%d)\n",
90 ret);
91 break;
92 }
93 }
94
95 if (ret != sizeof(event)) {
96 fprintf(stderr, "Reading event failed\n");
97 ret = -EIO;
98 break;
99 }
100 fprintf(stdout, "GPIO EVENT %" PRIu64 ": ", event.timestamp);
101 switch (event.id) {
102 case GPIOEVENT_EVENT_RISING_EDGE:
103 fprintf(stdout, "rising edge");
104 break;
105 case GPIOEVENT_EVENT_FALLING_EDGE:
106 fprintf(stdout, "falling edge");
107 break;
108 default:
109 fprintf(stdout, "unknown event");
110 }
111 fprintf(stdout, "\n");
112
113 i++;
114 if (i == loops)
115 break;
116 }
117
118exit_close_error:
119 if (close(fd) == -1)
120 perror("Failed to close GPIO character device file");
121 free(chrdev_name);
122 return ret;
123}
124
125void print_usage(void)
126{
127 fprintf(stderr, "Usage: gpio-event-mon [options]...\n"
128 "Listen to events on GPIO lines, 0->1 1->0\n"
129 " -n <name> Listen on GPIOs on a named device (must be stated)\n"
130 " -o <n> Offset to monitor\n"
131 " -d Set line as open drain\n"
132 " -s Set line as open source\n"
133 " -r Listen for rising edges\n"
134 " -f Listen for falling edges\n"
135 " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n"
136 " -? This helptext\n"
137 "\n"
138 "Example:\n"
139 "gpio-event-mon -n gpiochip0 -o 4 -r -f\n"
140 );
141}
142
143int main(int argc, char **argv)
144{
145 const char *device_name = NULL;
146 unsigned int line = -1;
147 unsigned int loops = 0;
148 u_int32_t handleflags = GPIOHANDLE_REQUEST_INPUT;
149 u_int32_t eventflags = 0;
150 int c;
151
152 while ((c = getopt(argc, argv, "c:n:o:dsrf?")) != -1) {
153 switch (c) {
154 case 'c':
155 loops = strtoul(optarg, NULL, 10);
156 break;
157 case 'n':
158 device_name = optarg;
159 break;
160 case 'o':
161 line = strtoul(optarg, NULL, 10);
162 break;
163 case 'd':
164 handleflags |= GPIOHANDLE_REQUEST_OPEN_DRAIN;
165 break;
166 case 's':
167 handleflags |= GPIOHANDLE_REQUEST_OPEN_SOURCE;
168 break;
169 case 'r':
170 eventflags |= GPIOEVENT_REQUEST_RISING_EDGE;
171 break;
172 case 'f':
173 eventflags |= GPIOEVENT_REQUEST_FALLING_EDGE;
174 break;
175 case '?':
176 print_usage();
177 return -1;
178 }
179 }
180
181 if (!device_name || line == -1) {
182 print_usage();
183 return -1;
184 }
185 if (!eventflags) {
186 printf("No flags specified, listening on both rising and "
187 "falling edges\n");
188 eventflags = GPIOEVENT_REQUEST_BOTH_EDGES;
189 }
190 return monitor_device(device_name, line, handleflags,
191 eventflags, loops);
192}
diff --git a/tools/gpio/gpio-hammer.c b/tools/gpio/gpio-hammer.c
new file mode 100644
index 000000000000..37b3f141053d
--- /dev/null
+++ b/tools/gpio/gpio-hammer.c
@@ -0,0 +1,189 @@
1/*
2 * gpio-hammer - example swiss army knife to shake GPIO lines on a system
3 *
4 * Copyright (C) 2016 Linus Walleij
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License version 2 as published by
8 * the Free Software Foundation.
9 *
10 * Usage:
11 * gpio-hammer -n <device-name> -o <offset1> -o <offset2>
12 */
13
14#include <unistd.h>
15#include <stdlib.h>
16#include <stdbool.h>
17#include <stdio.h>
18#include <dirent.h>
19#include <errno.h>
20#include <string.h>
21#include <poll.h>
22#include <fcntl.h>
23#include <getopt.h>
24#include <sys/ioctl.h>
25#include <linux/gpio.h>
26
27int hammer_device(const char *device_name, unsigned int *lines, int nlines,
28 unsigned int loops)
29{
30 struct gpiohandle_request req;
31 struct gpiohandle_data data;
32 char *chrdev_name;
33 char swirr[] = "-\\|/";
34 int fd;
35 int ret;
36 int i, j;
37 unsigned int iteration = 0;
38
39 ret = asprintf(&chrdev_name, "/dev/%s", device_name);
40 if (ret < 0)
41 return -ENOMEM;
42
43 fd = open(chrdev_name, 0);
44 if (fd == -1) {
45 ret = -errno;
46 fprintf(stderr, "Failed to open %s\n", chrdev_name);
47 goto exit_close_error;
48 }
49
50 /* Request lines as output */
51 for (i = 0; i < nlines; i++)
52 req.lineoffsets[i] = lines[i];
53 req.flags = GPIOHANDLE_REQUEST_OUTPUT; /* Request as output */
54 strcpy(req.consumer_label, "gpio-hammer");
55 req.lines = nlines;
56 ret = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, &req);
57 if (ret == -1) {
58 ret = -errno;
59 fprintf(stderr, "Failed to issue GET LINEHANDLE "
60 "IOCTL (%d)\n",
61 ret);
62 goto exit_close_error;
63 }
64
65 /* Read initial states */
66 ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
67 if (ret == -1) {
68 ret = -errno;
69 fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
70 "VALUES IOCTL (%d)\n",
71 ret);
72 goto exit_close_error;
73 }
74 fprintf(stdout, "Hammer lines [");
75 for (i = 0; i < nlines; i++) {
76 fprintf(stdout, "%d", lines[i]);
77 if (i != (nlines - 1))
78 fprintf(stdout, ", ");
79 }
80 fprintf(stdout, "] on %s, initial states: [", device_name);
81 for (i = 0; i < nlines; i++) {
82 fprintf(stdout, "%d", data.values[i]);
83 if (i != (nlines - 1))
84 fprintf(stdout, ", ");
85 }
86 fprintf(stdout, "]\n");
87
88 /* Hammertime! */
89 j = 0;
90 while (1) {
91 /* Invert all lines so we blink */
92 for (i = 0; i < nlines; i++)
93 data.values[i] = !data.values[i];
94
95 ret = ioctl(req.fd, GPIOHANDLE_SET_LINE_VALUES_IOCTL, &data);
96 if (ret == -1) {
97 ret = -errno;
98 fprintf(stderr, "Failed to issue GPIOHANDLE SET LINE "
99 "VALUES IOCTL (%d)\n",
100 ret);
101 goto exit_close_error;
102 }
103 /* Re-read values to get status */
104 ret = ioctl(req.fd, GPIOHANDLE_GET_LINE_VALUES_IOCTL, &data);
105 if (ret == -1) {
106 ret = -errno;
107 fprintf(stderr, "Failed to issue GPIOHANDLE GET LINE "
108 "VALUES IOCTL (%d)\n",
109 ret);
110 goto exit_close_error;
111 }
112
113 fprintf(stdout, "[%c] ", swirr[j]);
114 j++;
115 if (j == sizeof(swirr)-1)
116 j = 0;
117
118 fprintf(stdout, "[");
119 for (i = 0; i < nlines; i++) {
120 fprintf(stdout, "%d: %d", lines[i], data.values[i]);
121 if (i != (nlines - 1))
122 fprintf(stdout, ", ");
123 }
124 fprintf(stdout, "]\r");
125 fflush(stdout);
126 sleep(1);
127 iteration++;
128 if (loops && iteration == loops)
129 break;
130 }
131 fprintf(stdout, "\n");
132 ret = 0;
133
134exit_close_error:
135 if (close(fd) == -1)
136 perror("Failed to close GPIO character device file");
137 free(chrdev_name);
138 return ret;
139}
140
141void print_usage(void)
142{
143 fprintf(stderr, "Usage: gpio-hammer [options]...\n"
144 "Hammer GPIO lines, 0->1->0->1...\n"
145 " -n <name> Hammer GPIOs on a named device (must be stated)\n"
146 " -o <n> Offset[s] to hammer, at least one, several can be stated\n"
147 " [-c <n>] Do <n> loops (optional, infinite loop if not stated)\n"
148 " -? This helptext\n"
149 "\n"
150 "Example:\n"
151 "gpio-hammer -n gpiochip0 -o 4\n"
152 );
153}
154
155int main(int argc, char **argv)
156{
157 const char *device_name = NULL;
158 unsigned int lines[GPIOHANDLES_MAX];
159 unsigned int loops = 0;
160 int nlines;
161 int c;
162 int i;
163
164 i = 0;
165 while ((c = getopt(argc, argv, "c:n:o:?")) != -1) {
166 switch (c) {
167 case 'c':
168 loops = strtoul(optarg, NULL, 10);
169 break;
170 case 'n':
171 device_name = optarg;
172 break;
173 case 'o':
174 lines[i] = strtoul(optarg, NULL, 10);
175 i++;
176 break;
177 case '?':
178 print_usage();
179 return -1;
180 }
181 }
182 nlines = i;
183
184 if (!device_name || !nlines) {
185 print_usage();
186 return -1;
187 }
188 return hammer_device(device_name, lines, nlines, loops);
189}
diff --git a/tools/hv/bondvf.sh b/tools/hv/bondvf.sh
new file mode 100755
index 000000000000..8e960234013d
--- /dev/null
+++ b/tools/hv/bondvf.sh
@@ -0,0 +1,193 @@
1#!/bin/bash
2
3# This example script creates bonding network devices based on synthetic NIC
4# (the virtual network adapter usually provided by Hyper-V) and the matching
5# VF NIC (SRIOV virtual function). So the synthetic NIC and VF NIC can
6# function as one network device, and fail over to the synthetic NIC if VF is
7# down.
8#
9# Usage:
10# - After configured vSwitch and vNIC with SRIOV, start Linux virtual
11# machine (VM)
12# - Run this scripts on the VM. It will create configuration files in
13# distro specific directory.
14# - Reboot the VM, so that the bonding config are enabled.
15#
16# The config files are DHCP by default. You may edit them if you need to change
17# to Static IP or change other settings.
18#
19
20sysdir=/sys/class/net
21netvsc_cls={f8615163-df3e-46c5-913f-f2d2f965ed0e}
22bondcnt=0
23
24# Detect Distro
25if [ -f /etc/redhat-release ];
26then
27 cfgdir=/etc/sysconfig/network-scripts
28 distro=redhat
29elif grep -q 'Ubuntu' /etc/issue
30then
31 cfgdir=/etc/network
32 distro=ubuntu
33elif grep -q 'SUSE' /etc/issue
34then
35 cfgdir=/etc/sysconfig/network
36 distro=suse
37else
38 echo "Unsupported Distro"
39 exit 1
40fi
41
42echo Detected Distro: $distro, or compatible
43
44# Get a list of ethernet names
45list_eth=(`cd $sysdir && ls -d */ | cut -d/ -f1 | grep -v bond`)
46eth_cnt=${#list_eth[@]}
47
48echo List of net devices:
49
50# Get the MAC addresses
51for (( i=0; i < $eth_cnt; i++ ))
52do
53 list_mac[$i]=`cat $sysdir/${list_eth[$i]}/address`
54 echo ${list_eth[$i]}, ${list_mac[$i]}
55done
56
57# Find NIC with matching MAC
58for (( i=0; i < $eth_cnt-1; i++ ))
59do
60 for (( j=i+1; j < $eth_cnt; j++ ))
61 do
62 if [ "${list_mac[$i]}" = "${list_mac[$j]}" ]
63 then
64 list_match[$i]=${list_eth[$j]}
65 break
66 fi
67 done
68done
69
70function create_eth_cfg_redhat {
71 local fn=$cfgdir/ifcfg-$1
72
73 rm -f $fn
74 echo DEVICE=$1 >>$fn
75 echo TYPE=Ethernet >>$fn
76 echo BOOTPROTO=none >>$fn
77 echo ONBOOT=yes >>$fn
78 echo NM_CONTROLLED=no >>$fn
79 echo PEERDNS=yes >>$fn
80 echo IPV6INIT=yes >>$fn
81 echo MASTER=$2 >>$fn
82 echo SLAVE=yes >>$fn
83}
84
85function create_eth_cfg_pri_redhat {
86 create_eth_cfg_redhat $1 $2
87}
88
89function create_bond_cfg_redhat {
90 local fn=$cfgdir/ifcfg-$1
91
92 rm -f $fn
93 echo DEVICE=$1 >>$fn
94 echo TYPE=Bond >>$fn
95 echo BOOTPROTO=dhcp >>$fn
96 echo ONBOOT=yes >>$fn
97 echo NM_CONTROLLED=no >>$fn
98 echo PEERDNS=yes >>$fn
99 echo IPV6INIT=yes >>$fn
100 echo BONDING_MASTER=yes >>$fn
101 echo BONDING_OPTS=\"mode=active-backup miimon=100 primary=$2\" >>$fn
102}
103
104function create_eth_cfg_ubuntu {
105 local fn=$cfgdir/interfaces
106
107 echo $'\n'auto $1 >>$fn
108 echo iface $1 inet manual >>$fn
109 echo bond-master $2 >>$fn
110}
111
112function create_eth_cfg_pri_ubuntu {
113 local fn=$cfgdir/interfaces
114
115 create_eth_cfg_ubuntu $1 $2
116 echo bond-primary $1 >>$fn
117}
118
119function create_bond_cfg_ubuntu {
120 local fn=$cfgdir/interfaces
121
122 echo $'\n'auto $1 >>$fn
123 echo iface $1 inet dhcp >>$fn
124 echo bond-mode active-backup >>$fn
125 echo bond-miimon 100 >>$fn
126 echo bond-slaves none >>$fn
127}
128
129function create_eth_cfg_suse {
130 local fn=$cfgdir/ifcfg-$1
131
132 rm -f $fn
133 echo BOOTPROTO=none >>$fn
134 echo STARTMODE=auto >>$fn
135}
136
137function create_eth_cfg_pri_suse {
138 create_eth_cfg_suse $1
139}
140
141function create_bond_cfg_suse {
142 local fn=$cfgdir/ifcfg-$1
143
144 rm -f $fn
145 echo BOOTPROTO=dhcp >>$fn
146 echo STARTMODE=auto >>$fn
147 echo BONDING_MASTER=yes >>$fn
148 echo BONDING_SLAVE_0=$2 >>$fn
149 echo BONDING_SLAVE_1=$3 >>$fn
150 echo BONDING_MODULE_OPTS=\'mode=active-backup miimon=100 primary=$2\' >>$fn
151}
152
153function create_bond {
154 local bondname=bond$bondcnt
155 local primary
156 local secondary
157
158 local class_id1=`cat $sysdir/$1/device/class_id 2>/dev/null`
159 local class_id2=`cat $sysdir/$2/device/class_id 2>/dev/null`
160
161 if [ "$class_id1" = "$netvsc_cls" ]
162 then
163 primary=$2
164 secondary=$1
165 elif [ "$class_id2" = "$netvsc_cls" ]
166 then
167 primary=$1
168 secondary=$2
169 else
170 return 0
171 fi
172
173 echo $'\nBond name:' $bondname
174
175 echo configuring $primary
176 create_eth_cfg_pri_$distro $primary $bondname
177
178 echo configuring $secondary
179 create_eth_cfg_$distro $secondary $bondname
180
181 echo creating: $bondname with primary slave: $primary
182 create_bond_cfg_$distro $bondname $primary $secondary
183
184 let bondcnt=bondcnt+1
185}
186
187for (( i=0; i < $eth_cnt-1; i++ ))
188do
189 if [ -n "${list_match[$i]}" ]
190 then
191 create_bond ${list_eth[$i]} ${list_match[$i]}
192 fi
193done
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index 0d9f48ec42bb..bc7adb84e679 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -1433,7 +1433,7 @@ int main(int argc, char *argv[])
1433 openlog("KVP", 0, LOG_USER); 1433 openlog("KVP", 0, LOG_USER);
1434 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid()); 1434 syslog(LOG_INFO, "KVP starting; pid is:%d", getpid());
1435 1435
1436 kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR); 1436 kvp_fd = open("/dev/vmbus/hv_kvp", O_RDWR | O_CLOEXEC);
1437 1437
1438 if (kvp_fd < 0) { 1438 if (kvp_fd < 0) {
1439 syslog(LOG_ERR, "open /dev/vmbus/hv_kvp failed; error: %d %s", 1439 syslog(LOG_ERR, "open /dev/vmbus/hv_kvp failed; error: %d %s",
diff --git a/tools/hv/hv_vss_daemon.c b/tools/hv/hv_vss_daemon.c
index 5d51d6ff08e6..e0829809c897 100644
--- a/tools/hv/hv_vss_daemon.c
+++ b/tools/hv/hv_vss_daemon.c
@@ -250,6 +250,9 @@ int main(int argc, char *argv[])
250 syslog(LOG_ERR, "/etc/fstab and /proc/mounts"); 250 syslog(LOG_ERR, "/etc/fstab and /proc/mounts");
251 } 251 }
252 break; 252 break;
253 case VSS_OP_HOT_BACKUP:
254 syslog(LOG_INFO, "VSS: op=CHECK HOT BACKUP\n");
255 break;
253 default: 256 default:
254 syslog(LOG_ERR, "Illegal op:%d\n", op); 257 syslog(LOG_ERR, "Illegal op:%d\n", op);
255 } 258 }
diff --git a/tools/iio/Makefile b/tools/iio/Makefile
index 3a7a54f59713..5446d625e17d 100644
--- a/tools/iio/Makefile
+++ b/tools/iio/Makefile
@@ -1,16 +1,31 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2CFLAGS += -Wall -g -D_GNU_SOURCE 2CFLAGS += -Wall -g -D_GNU_SOURCE
3 3
4all: iio_event_monitor lsiio generic_buffer 4BINDIR=usr/bin
5INSTALL_PROGRAM=install -m 755 -p
6DEL_FILE=rm -f
7
8all: iio_event_monitor lsiio iio_generic_buffer
5 9
6iio_event_monitor: iio_event_monitor.o iio_utils.o 10iio_event_monitor: iio_event_monitor.o iio_utils.o
7 11
8lsiio: lsiio.o iio_utils.o 12lsiio: lsiio.o iio_utils.o
9 13
10generic_buffer: generic_buffer.o iio_utils.o 14iio_generic_buffer: iio_generic_buffer.o iio_utils.o
11 15
12%.o: %.c iio_utils.h 16%.o: %.c iio_utils.h
13 17
18install:
19 - mkdir -p $(INSTALL_ROOT)/$(BINDIR)
20 - $(INSTALL_PROGRAM) "iio_event_monitor" "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor"
21 - $(INSTALL_PROGRAM) "lsiio" "$(INSTALL_ROOT)/$(BINDIR)/lsiio"
22 - $(INSTALL_PROGRAM) "iio_generic_buffer" "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer"
23
24uninstall:
25 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_event_monitor"
26 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/lsiio"
27 $(DEL_FILE) "$(INSTALL_ROOT)/$(BINDIR)/iio_generic_buffer"
28
14.PHONY: clean 29.PHONY: clean
15clean: 30clean:
16 rm -f *.o iio_event_monitor lsiio generic_buffer 31 rm -f *.o iio_event_monitor lsiio iio_generic_buffer
diff --git a/tools/iio/generic_buffer.c b/tools/iio/iio_generic_buffer.c
index 2429c78de940..f39c0e9c0d5c 100644
--- a/tools/iio/generic_buffer.c
+++ b/tools/iio/iio_generic_buffer.c
@@ -32,6 +32,8 @@
32#include <endian.h> 32#include <endian.h>
33#include <getopt.h> 33#include <getopt.h>
34#include <inttypes.h> 34#include <inttypes.h>
35#include <stdbool.h>
36#include <signal.h>
35#include "iio_utils.h" 37#include "iio_utils.h"
36 38
37/** 39/**
@@ -249,11 +251,82 @@ void print_usage(void)
249 " -e Disable wait for event (new data)\n" 251 " -e Disable wait for event (new data)\n"
250 " -g Use trigger-less mode\n" 252 " -g Use trigger-less mode\n"
251 " -l <n> Set buffer length to n samples\n" 253 " -l <n> Set buffer length to n samples\n"
252 " -n <name> Set device name (mandatory)\n" 254 " --device-name -n <name>\n"
253 " -t <name> Set trigger name\n" 255 " --device-num -N <num>\n"
256 " Set device by name or number (mandatory)\n"
257 " --trigger-name -t <name>\n"
258 " --trigger-num -T <num>\n"
259 " Set trigger by name or number\n"
254 " -w <n> Set delay between reads in us (event-less mode)\n"); 260 " -w <n> Set delay between reads in us (event-less mode)\n");
255} 261}
256 262
263enum autochan autochannels = AUTOCHANNELS_DISABLED;
264char *dev_dir_name = NULL;
265char *buf_dir_name = NULL;
266bool current_trigger_set = false;
267
268void cleanup(void)
269{
270 int ret;
271
272 /* Disable trigger */
273 if (dev_dir_name && current_trigger_set) {
274 /* Disconnect the trigger - just write a dummy name. */
275 ret = write_sysfs_string("trigger/current_trigger",
276 dev_dir_name, "NULL");
277 if (ret < 0)
278 fprintf(stderr, "Failed to disable trigger: %s\n",
279 strerror(-ret));
280 current_trigger_set = false;
281 }
282
283 /* Disable buffer */
284 if (buf_dir_name) {
285 ret = write_sysfs_int("enable", buf_dir_name, 0);
286 if (ret < 0)
287 fprintf(stderr, "Failed to disable buffer: %s\n",
288 strerror(-ret));
289 }
290
291 /* Disable channels if auto-enabled */
292 if (dev_dir_name && autochannels == AUTOCHANNELS_ACTIVE) {
293 ret = enable_disable_all_channels(dev_dir_name, 0);
294 if (ret)
295 fprintf(stderr, "Failed to disable all channels\n");
296 autochannels = AUTOCHANNELS_DISABLED;
297 }
298}
299
300void sig_handler(int signum)
301{
302 fprintf(stderr, "Caught signal %d\n", signum);
303 cleanup();
304 exit(-signum);
305}
306
307void register_cleanup(void)
308{
309 struct sigaction sa = { .sa_handler = sig_handler };
310 const int signums[] = { SIGINT, SIGTERM, SIGABRT };
311 int ret, i;
312
313 for (i = 0; i < ARRAY_SIZE(signums); ++i) {
314 ret = sigaction(signums[i], &sa, NULL);
315 if (ret) {
316 perror("Failed to register signal handler");
317 exit(-1);
318 }
319 }
320}
321
322static const struct option longopts[] = {
323 { "device-name", 1, 0, 'n' },
324 { "device-num", 1, 0, 'N' },
325 { "trigger-name", 1, 0, 't' },
326 { "trigger-num", 1, 0, 'T' },
327 { },
328};
329
257int main(int argc, char **argv) 330int main(int argc, char **argv)
258{ 331{
259 unsigned long num_loops = 2; 332 unsigned long num_loops = 2;
@@ -261,26 +334,25 @@ int main(int argc, char **argv)
261 unsigned long buf_len = 128; 334 unsigned long buf_len = 128;
262 335
263 int ret, c, i, j, toread; 336 int ret, c, i, j, toread;
264 int fp; 337 int fp = -1;
265 338
266 int num_channels; 339 int num_channels = 0;
267 char *trigger_name = NULL, *device_name = NULL; 340 char *trigger_name = NULL, *device_name = NULL;
268 char *dev_dir_name, *buf_dir_name;
269 341
270 int datardytrigger = 1; 342 char *data = NULL;
271 char *data;
272 ssize_t read_size; 343 ssize_t read_size;
273 int dev_num, trig_num; 344 int dev_num = -1, trig_num = -1;
274 char *buffer_access; 345 char *buffer_access = NULL;
275 int scan_size; 346 int scan_size;
276 int noevents = 0; 347 int noevents = 0;
277 int notrigger = 0; 348 int notrigger = 0;
278 enum autochan autochannels = AUTOCHANNELS_DISABLED;
279 char *dummy; 349 char *dummy;
280 350
281 struct iio_channel_info *channels; 351 struct iio_channel_info *channels = NULL;
282 352
283 while ((c = getopt(argc, argv, "ac:egl:n:t:w:")) != -1) { 353 register_cleanup();
354
355 while ((c = getopt_long(argc, argv, "ac:egl:n:N:t:T:w:", longopts, NULL)) != -1) {
284 switch (c) { 356 switch (c) {
285 case 'a': 357 case 'a':
286 autochannels = AUTOCHANNELS_ENABLED; 358 autochannels = AUTOCHANNELS_ENABLED;
@@ -288,8 +360,10 @@ int main(int argc, char **argv)
288 case 'c': 360 case 'c':
289 errno = 0; 361 errno = 0;
290 num_loops = strtoul(optarg, &dummy, 10); 362 num_loops = strtoul(optarg, &dummy, 10);
291 if (errno) 363 if (errno) {
292 return -errno; 364 ret = -errno;
365 goto error;
366 }
293 367
294 break; 368 break;
295 case 'e': 369 case 'e':
@@ -301,49 +375,102 @@ int main(int argc, char **argv)
301 case 'l': 375 case 'l':
302 errno = 0; 376 errno = 0;
303 buf_len = strtoul(optarg, &dummy, 10); 377 buf_len = strtoul(optarg, &dummy, 10);
304 if (errno) 378 if (errno) {
305 return -errno; 379 ret = -errno;
380 goto error;
381 }
306 382
307 break; 383 break;
308 case 'n': 384 case 'n':
309 device_name = optarg; 385 device_name = strdup(optarg);
386 break;
387 case 'N':
388 errno = 0;
389 dev_num = strtoul(optarg, &dummy, 10);
390 if (errno) {
391 ret = -errno;
392 goto error;
393 }
310 break; 394 break;
311 case 't': 395 case 't':
312 trigger_name = optarg; 396 trigger_name = strdup(optarg);
313 datardytrigger = 0;
314 break; 397 break;
315 case 'w': 398 case 'T':
316 errno = 0; 399 errno = 0;
317 timedelay = strtoul(optarg, &dummy, 10); 400 trig_num = strtoul(optarg, &dummy, 10);
318 if (errno) 401 if (errno)
319 return -errno; 402 return -errno;
320 break; 403 break;
404 case 'w':
405 errno = 0;
406 timedelay = strtoul(optarg, &dummy, 10);
407 if (errno) {
408 ret = -errno;
409 goto error;
410 }
411 break;
321 case '?': 412 case '?':
322 print_usage(); 413 print_usage();
323 return -1; 414 ret = -1;
415 goto error;
324 } 416 }
325 } 417 }
326 418
327 if (!device_name) {
328 fprintf(stderr, "Device name not set\n");
329 print_usage();
330 return -1;
331 }
332
333 /* Find the device requested */ 419 /* Find the device requested */
334 dev_num = find_type_by_name(device_name, "iio:device"); 420 if (dev_num < 0 && !device_name) {
335 if (dev_num < 0) { 421 fprintf(stderr, "Device not set\n");
336 fprintf(stderr, "Failed to find the %s\n", device_name); 422 print_usage();
337 return dev_num; 423 ret = -1;
424 goto error;
425 } else if (dev_num >= 0 && device_name) {
426 fprintf(stderr, "Only one of --device-num or --device-name needs to be set\n");
427 print_usage();
428 ret = -1;
429 goto error;
430 } else if (dev_num < 0) {
431 dev_num = find_type_by_name(device_name, "iio:device");
432 if (dev_num < 0) {
433 fprintf(stderr, "Failed to find the %s\n", device_name);
434 ret = dev_num;
435 goto error;
436 }
338 } 437 }
339
340 printf("iio device number being used is %d\n", dev_num); 438 printf("iio device number being used is %d\n", dev_num);
341 439
342 ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num); 440 ret = asprintf(&dev_dir_name, "%siio:device%d", iio_dir, dev_num);
343 if (ret < 0) 441 if (ret < 0)
344 return -ENOMEM; 442 return -ENOMEM;
443 /* Fetch device_name if specified by number */
444 if (!device_name) {
445 device_name = malloc(IIO_MAX_NAME_LENGTH);
446 if (!device_name) {
447 ret = -ENOMEM;
448 goto error;
449 }
450 ret = read_sysfs_string("name", dev_dir_name, device_name);
451 if (ret < 0) {
452 fprintf(stderr, "Failed to read name of device %d\n", dev_num);
453 goto error;
454 }
455 }
345 456
346 if (!notrigger) { 457 if (notrigger) {
458 printf("trigger-less mode selected\n");
459 } else if (trig_num >= 0) {
460 char *trig_dev_name;
461 ret = asprintf(&trig_dev_name, "%strigger%d", iio_dir, trig_num);
462 if (ret < 0) {
463 return -ENOMEM;
464 }
465 trigger_name = malloc(IIO_MAX_NAME_LENGTH);
466 ret = read_sysfs_string("name", trig_dev_name, trigger_name);
467 free(trig_dev_name);
468 if (ret < 0) {
469 fprintf(stderr, "Failed to read trigger%d name from\n", trig_num);
470 return ret;
471 }
472 printf("iio trigger number being used is %d\n", trig_num);
473 } else {
347 if (!trigger_name) { 474 if (!trigger_name) {
348 /* 475 /*
349 * Build the trigger name. If it is device associated 476 * Build the trigger name. If it is device associated
@@ -354,7 +481,7 @@ int main(int argc, char **argv)
354 "%s-dev%d", device_name, dev_num); 481 "%s-dev%d", device_name, dev_num);
355 if (ret < 0) { 482 if (ret < 0) {
356 ret = -ENOMEM; 483 ret = -ENOMEM;
357 goto error_free_dev_dir_name; 484 goto error;
358 } 485 }
359 } 486 }
360 487
@@ -367,7 +494,7 @@ int main(int argc, char **argv)
367 "%s-trigger", device_name); 494 "%s-trigger", device_name);
368 if (ret < 0) { 495 if (ret < 0) {
369 ret = -ENOMEM; 496 ret = -ENOMEM;
370 goto error_free_dev_dir_name; 497 goto error;
371 } 498 }
372 } 499 }
373 500
@@ -376,12 +503,10 @@ int main(int argc, char **argv)
376 fprintf(stderr, "Failed to find the trigger %s\n", 503 fprintf(stderr, "Failed to find the trigger %s\n",
377 trigger_name); 504 trigger_name);
378 ret = trig_num; 505 ret = trig_num;
379 goto error_free_triggername; 506 goto error;
380 } 507 }
381 508
382 printf("iio trigger number being used is %d\n", trig_num); 509 printf("iio trigger number being used is %d\n", trig_num);
383 } else {
384 printf("trigger-less mode selected\n");
385 } 510 }
386 511
387 /* 512 /*
@@ -392,7 +517,7 @@ int main(int argc, char **argv)
392 if (ret) { 517 if (ret) {
393 fprintf(stderr, "Problem reading scan element information\n" 518 fprintf(stderr, "Problem reading scan element information\n"
394 "diag %s\n", dev_dir_name); 519 "diag %s\n", dev_dir_name);
395 goto error_free_triggername; 520 goto error;
396 } 521 }
397 if (num_channels && autochannels == AUTOCHANNELS_ENABLED) { 522 if (num_channels && autochannels == AUTOCHANNELS_ENABLED) {
398 fprintf(stderr, "Auto-channels selected but some channels " 523 fprintf(stderr, "Auto-channels selected but some channels "
@@ -407,7 +532,7 @@ int main(int argc, char **argv)
407 ret = enable_disable_all_channels(dev_dir_name, 1); 532 ret = enable_disable_all_channels(dev_dir_name, 1);
408 if (ret) { 533 if (ret) {
409 fprintf(stderr, "Failed to enable all channels\n"); 534 fprintf(stderr, "Failed to enable all channels\n");
410 goto error_free_triggername; 535 goto error;
411 } 536 }
412 537
413 /* This flags that we need to disable the channels again */ 538 /* This flags that we need to disable the channels again */
@@ -419,12 +544,12 @@ int main(int argc, char **argv)
419 fprintf(stderr, "Problem reading scan element " 544 fprintf(stderr, "Problem reading scan element "
420 "information\n" 545 "information\n"
421 "diag %s\n", dev_dir_name); 546 "diag %s\n", dev_dir_name);
422 goto error_disable_channels; 547 goto error;
423 } 548 }
424 if (!num_channels) { 549 if (!num_channels) {
425 fprintf(stderr, "Still no channels after " 550 fprintf(stderr, "Still no channels after "
426 "auto-enabling, giving up\n"); 551 "auto-enabling, giving up\n");
427 goto error_disable_channels; 552 goto error;
428 } 553 }
429 } 554 }
430 555
@@ -436,7 +561,7 @@ int main(int argc, char **argv)
436 "/*_en or pass -a to autoenable channels and " 561 "/*_en or pass -a to autoenable channels and "
437 "try again.\n", dev_dir_name); 562 "try again.\n", dev_dir_name);
438 ret = -ENOENT; 563 ret = -ENOENT;
439 goto error_free_triggername; 564 goto error;
440 } 565 }
441 566
442 /* 567 /*
@@ -448,7 +573,7 @@ int main(int argc, char **argv)
448 "%siio:device%d/buffer", iio_dir, dev_num); 573 "%siio:device%d/buffer", iio_dir, dev_num);
449 if (ret < 0) { 574 if (ret < 0) {
450 ret = -ENOMEM; 575 ret = -ENOMEM;
451 goto error_free_channels; 576 goto error;
452 } 577 }
453 578
454 if (!notrigger) { 579 if (!notrigger) {
@@ -463,34 +588,34 @@ int main(int argc, char **argv)
463 if (ret < 0) { 588 if (ret < 0) {
464 fprintf(stderr, 589 fprintf(stderr,
465 "Failed to write current_trigger file\n"); 590 "Failed to write current_trigger file\n");
466 goto error_free_buf_dir_name; 591 goto error;
467 } 592 }
468 } 593 }
469 594
470 /* Setup ring buffer parameters */ 595 /* Setup ring buffer parameters */
471 ret = write_sysfs_int("length", buf_dir_name, buf_len); 596 ret = write_sysfs_int("length", buf_dir_name, buf_len);
472 if (ret < 0) 597 if (ret < 0)
473 goto error_free_buf_dir_name; 598 goto error;
474 599
475 /* Enable the buffer */ 600 /* Enable the buffer */
476 ret = write_sysfs_int("enable", buf_dir_name, 1); 601 ret = write_sysfs_int("enable", buf_dir_name, 1);
477 if (ret < 0) { 602 if (ret < 0) {
478 fprintf(stderr, 603 fprintf(stderr,
479 "Failed to enable buffer: %s\n", strerror(-ret)); 604 "Failed to enable buffer: %s\n", strerror(-ret));
480 goto error_free_buf_dir_name; 605 goto error;
481 } 606 }
482 607
483 scan_size = size_from_channelarray(channels, num_channels); 608 scan_size = size_from_channelarray(channels, num_channels);
484 data = malloc(scan_size * buf_len); 609 data = malloc(scan_size * buf_len);
485 if (!data) { 610 if (!data) {
486 ret = -ENOMEM; 611 ret = -ENOMEM;
487 goto error_free_buf_dir_name; 612 goto error;
488 } 613 }
489 614
490 ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num); 615 ret = asprintf(&buffer_access, "/dev/iio:device%d", dev_num);
491 if (ret < 0) { 616 if (ret < 0) {
492 ret = -ENOMEM; 617 ret = -ENOMEM;
493 goto error_free_data; 618 goto error;
494 } 619 }
495 620
496 /* Attempt to open non blocking the access dev */ 621 /* Attempt to open non blocking the access dev */
@@ -498,7 +623,7 @@ int main(int argc, char **argv)
498 if (fp == -1) { /* TODO: If it isn't there make the node */ 623 if (fp == -1) { /* TODO: If it isn't there make the node */
499 ret = -errno; 624 ret = -errno;
500 fprintf(stderr, "Failed to open %s\n", buffer_access); 625 fprintf(stderr, "Failed to open %s\n", buffer_access);
501 goto error_free_buffer_access; 626 goto error;
502 } 627 }
503 628
504 for (j = 0; j < num_loops; j++) { 629 for (j = 0; j < num_loops; j++) {
@@ -511,7 +636,7 @@ int main(int argc, char **argv)
511 ret = poll(&pfd, 1, -1); 636 ret = poll(&pfd, 1, -1);
512 if (ret < 0) { 637 if (ret < 0) {
513 ret = -errno; 638 ret = -errno;
514 goto error_close_buffer_access; 639 goto error;
515 } else if (ret == 0) { 640 } else if (ret == 0) {
516 continue; 641 continue;
517 } 642 }
@@ -536,45 +661,21 @@ int main(int argc, char **argv)
536 num_channels); 661 num_channels);
537 } 662 }
538 663
539 /* Stop the buffer */ 664error:
540 ret = write_sysfs_int("enable", buf_dir_name, 0); 665 cleanup();
541 if (ret < 0)
542 goto error_close_buffer_access;
543 666
544 if (!notrigger) 667 if (fp >= 0 && close(fp) == -1)
545 /* Disconnect the trigger - just write a dummy name. */
546 ret = write_sysfs_string("trigger/current_trigger",
547 dev_dir_name, "NULL");
548 if (ret < 0)
549 fprintf(stderr, "Failed to write to %s\n",
550 dev_dir_name);
551
552error_close_buffer_access:
553 if (close(fp) == -1)
554 perror("Failed to close buffer"); 668 perror("Failed to close buffer");
555
556error_free_buffer_access:
557 free(buffer_access); 669 free(buffer_access);
558error_free_data:
559 free(data); 670 free(data);
560error_free_buf_dir_name:
561 free(buf_dir_name); 671 free(buf_dir_name);
562error_free_channels:
563 for (i = num_channels - 1; i >= 0; i--) { 672 for (i = num_channels - 1; i >= 0; i--) {
564 free(channels[i].name); 673 free(channels[i].name);
565 free(channels[i].generic_name); 674 free(channels[i].generic_name);
566 } 675 }
567 free(channels); 676 free(channels);
568error_free_triggername: 677 free(trigger_name);
569 if (datardytrigger) 678 free(device_name);
570 free(trigger_name);
571error_disable_channels:
572 if (autochannels == AUTOCHANNELS_ACTIVE) {
573 ret = enable_disable_all_channels(dev_dir_name, 0);
574 if (ret)
575 fprintf(stderr, "Failed to disable all channels\n");
576 }
577error_free_dev_dir_name:
578 free(dev_dir_name); 679 free(dev_dir_name);
579 680
580 return ret; 681 return ret;
diff --git a/tools/iio/iio_utils.c b/tools/iio/iio_utils.c
index 5eb6793f3972..7a6d61c6c012 100644
--- a/tools/iio/iio_utils.c
+++ b/tools/iio/iio_utils.c
@@ -121,10 +121,6 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
121 121
122 ret = -ENOENT; 122 ret = -ENOENT;
123 while (ent = readdir(dp), ent) 123 while (ent = readdir(dp), ent)
124 /*
125 * Do we allow devices to override a generic name with
126 * a specific one?
127 */
128 if ((strcmp(builtname, ent->d_name) == 0) || 124 if ((strcmp(builtname, ent->d_name) == 0) ||
129 (strcmp(builtname_generic, ent->d_name) == 0)) { 125 (strcmp(builtname_generic, ent->d_name) == 0)) {
130 ret = asprintf(&filename, 126 ret = asprintf(&filename,
@@ -178,6 +174,13 @@ int iioutils_get_type(unsigned *is_signed, unsigned *bytes, unsigned *bits_used,
178 sysfsfp = 0; 174 sysfsfp = 0;
179 free(filename); 175 free(filename);
180 filename = 0; 176 filename = 0;
177
178 /*
179 * Avoid having a more generic entry overwriting
180 * the settings.
181 */
182 if (strcmp(builtname, ent->d_name) == 0)
183 break;
181 } 184 }
182 185
183error_close_sysfsfp: 186error_close_sysfsfp:
diff --git a/tools/iio/lsiio.c b/tools/iio/lsiio.c
index 3d650e668252..ab0f5cf16025 100644
--- a/tools/iio/lsiio.c
+++ b/tools/iio/lsiio.c
@@ -51,7 +51,8 @@ static int dump_channels(const char *dev_dir_name)
51 51
52 while (ent = readdir(dp), ent) 52 while (ent = readdir(dp), ent)
53 if (check_prefix(ent->d_name, "in_") && 53 if (check_prefix(ent->d_name, "in_") &&
54 check_postfix(ent->d_name, "_raw")) 54 (check_postfix(ent->d_name, "_raw") ||
55 check_postfix(ent->d_name, "_input")))
55 printf(" %-10s\n", ent->d_name); 56 printf(" %-10s\n", ent->d_name);
56 57
57 return (closedir(dp) == -1) ? -errno : 0; 58 return (closedir(dp) == -1) ? -errno : 0;
diff --git a/tools/include/asm-generic/bitops/__ffs.h b/tools/include/asm-generic/bitops/__ffs.h
index c94175015a82..b3accfdf24b9 100644
--- a/tools/include/asm-generic/bitops/__ffs.h
+++ b/tools/include/asm-generic/bitops/__ffs.h
@@ -2,6 +2,7 @@
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_ 2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS___FFS_H_
3 3
4#include <asm/types.h> 4#include <asm/types.h>
5#include <asm/bitsperlong.h>
5 6
6/** 7/**
7 * __ffs - find first bit in word. 8 * __ffs - find first bit in word.
diff --git a/tools/include/asm-generic/bitops/__fls.h b/tools/include/asm-generic/bitops/__fls.h
index 494c9c615d1c..a60a7ccb6782 100644
--- a/tools/include/asm-generic/bitops/__fls.h
+++ b/tools/include/asm-generic/bitops/__fls.h
@@ -1 +1,43 @@
1#include "../../../../include/asm-generic/bitops/__fls.h" 1#ifndef _ASM_GENERIC_BITOPS___FLS_H_
2#define _ASM_GENERIC_BITOPS___FLS_H_
3
4#include <asm/types.h>
5
6/**
7 * __fls - find last (most-significant) set bit in a long word
8 * @word: the word to search
9 *
10 * Undefined if no set bit exists, so code should check against 0 first.
11 */
12static __always_inline unsigned long __fls(unsigned long word)
13{
14 int num = BITS_PER_LONG - 1;
15
16#if BITS_PER_LONG == 64
17 if (!(word & (~0ul << 32))) {
18 num -= 32;
19 word <<= 32;
20 }
21#endif
22 if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
23 num -= 16;
24 word <<= 16;
25 }
26 if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
27 num -= 8;
28 word <<= 8;
29 }
30 if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
31 num -= 4;
32 word <<= 4;
33 }
34 if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
35 num -= 2;
36 word <<= 2;
37 }
38 if (!(word & (~0ul << (BITS_PER_LONG-1))))
39 num -= 1;
40 return num;
41}
42
43#endif /* _ASM_GENERIC_BITOPS___FLS_H_ */
diff --git a/tools/include/asm-generic/bitops/arch_hweight.h b/tools/include/asm-generic/bitops/arch_hweight.h
index 318bb2b202b0..6a211f40665c 100644
--- a/tools/include/asm-generic/bitops/arch_hweight.h
+++ b/tools/include/asm-generic/bitops/arch_hweight.h
@@ -1 +1,25 @@
1#include "../../../../include/asm-generic/bitops/arch_hweight.h" 1#ifndef _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
2#define _ASM_GENERIC_BITOPS_ARCH_HWEIGHT_H_
3
4#include <asm/types.h>
5
6static inline unsigned int __arch_hweight32(unsigned int w)
7{
8 return __sw_hweight32(w);
9}
10
11static inline unsigned int __arch_hweight16(unsigned int w)
12{
13 return __sw_hweight16(w);
14}
15
16static inline unsigned int __arch_hweight8(unsigned int w)
17{
18 return __sw_hweight8(w);
19}
20
21static inline unsigned long __arch_hweight64(__u64 w)
22{
23 return __sw_hweight64(w);
24}
25#endif /* _ASM_GENERIC_BITOPS_HWEIGHT_H_ */
diff --git a/tools/include/asm-generic/bitops/atomic.h b/tools/include/asm-generic/bitops/atomic.h
index 4bccd7c3d5d6..18663f59d72f 100644
--- a/tools/include/asm-generic/bitops/atomic.h
+++ b/tools/include/asm-generic/bitops/atomic.h
@@ -2,6 +2,7 @@
2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_ 2#define _TOOLS_LINUX_ASM_GENERIC_BITOPS_ATOMIC_H_
3 3
4#include <asm/types.h> 4#include <asm/types.h>
5#include <asm/bitsperlong.h>
5 6
6static inline void set_bit(int nr, unsigned long *addr) 7static inline void set_bit(int nr, unsigned long *addr)
7{ 8{
diff --git a/tools/include/asm-generic/bitops/const_hweight.h b/tools/include/asm-generic/bitops/const_hweight.h
index 0afd644aff83..0a7e06623470 100644
--- a/tools/include/asm-generic/bitops/const_hweight.h
+++ b/tools/include/asm-generic/bitops/const_hweight.h
@@ -1 +1,43 @@
1#include "../../../../include/asm-generic/bitops/const_hweight.h" 1#ifndef _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
2#define _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_
3
4/*
5 * Compile time versions of __arch_hweightN()
6 */
7#define __const_hweight8(w) \
8 ((unsigned int) \
9 ((!!((w) & (1ULL << 0))) + \
10 (!!((w) & (1ULL << 1))) + \
11 (!!((w) & (1ULL << 2))) + \
12 (!!((w) & (1ULL << 3))) + \
13 (!!((w) & (1ULL << 4))) + \
14 (!!((w) & (1ULL << 5))) + \
15 (!!((w) & (1ULL << 6))) + \
16 (!!((w) & (1ULL << 7)))))
17
18#define __const_hweight16(w) (__const_hweight8(w) + __const_hweight8((w) >> 8 ))
19#define __const_hweight32(w) (__const_hweight16(w) + __const_hweight16((w) >> 16))
20#define __const_hweight64(w) (__const_hweight32(w) + __const_hweight32((w) >> 32))
21
22/*
23 * Generic interface.
24 */
25#define hweight8(w) (__builtin_constant_p(w) ? __const_hweight8(w) : __arch_hweight8(w))
26#define hweight16(w) (__builtin_constant_p(w) ? __const_hweight16(w) : __arch_hweight16(w))
27#define hweight32(w) (__builtin_constant_p(w) ? __const_hweight32(w) : __arch_hweight32(w))
28#define hweight64(w) (__builtin_constant_p(w) ? __const_hweight64(w) : __arch_hweight64(w))
29
30/*
31 * Interface for known constant arguments
32 */
33#define HWEIGHT8(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight8(w))
34#define HWEIGHT16(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight16(w))
35#define HWEIGHT32(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight32(w))
36#define HWEIGHT64(w) (BUILD_BUG_ON_ZERO(!__builtin_constant_p(w)) + __const_hweight64(w))
37
38/*
39 * Type invariant interface to the compile time constant hweight functions.
40 */
41#define HWEIGHT(w) HWEIGHT64((u64)w)
42
43#endif /* _ASM_GENERIC_BITOPS_CONST_HWEIGHT_H_ */
diff --git a/tools/include/asm-generic/bitops/fls.h b/tools/include/asm-generic/bitops/fls.h
index 0e4995fa0248..0576d1f42f43 100644
--- a/tools/include/asm-generic/bitops/fls.h
+++ b/tools/include/asm-generic/bitops/fls.h
@@ -1 +1,41 @@
1#include "../../../../include/asm-generic/bitops/fls.h" 1#ifndef _ASM_GENERIC_BITOPS_FLS_H_
2#define _ASM_GENERIC_BITOPS_FLS_H_
3
4/**
5 * fls - find last (most-significant) bit set
6 * @x: the word to search
7 *
8 * This is defined the same way as ffs.
9 * Note fls(0) = 0, fls(1) = 1, fls(0x80000000) = 32.
10 */
11
12static __always_inline int fls(int x)
13{
14 int r = 32;
15
16 if (!x)
17 return 0;
18 if (!(x & 0xffff0000u)) {
19 x <<= 16;
20 r -= 16;
21 }
22 if (!(x & 0xff000000u)) {
23 x <<= 8;
24 r -= 8;
25 }
26 if (!(x & 0xf0000000u)) {
27 x <<= 4;
28 r -= 4;
29 }
30 if (!(x & 0xc0000000u)) {
31 x <<= 2;
32 r -= 2;
33 }
34 if (!(x & 0x80000000u)) {
35 x <<= 1;
36 r -= 1;
37 }
38 return r;
39}
40
41#endif /* _ASM_GENERIC_BITOPS_FLS_H_ */
diff --git a/tools/include/asm-generic/bitops/fls64.h b/tools/include/asm-generic/bitops/fls64.h
index 35bee0071e78..b097cf8444e3 100644
--- a/tools/include/asm-generic/bitops/fls64.h
+++ b/tools/include/asm-generic/bitops/fls64.h
@@ -1 +1,36 @@
1#include "../../../../include/asm-generic/bitops/fls64.h" 1#ifndef _ASM_GENERIC_BITOPS_FLS64_H_
2#define _ASM_GENERIC_BITOPS_FLS64_H_
3
4#include <asm/types.h>
5
6/**
7 * fls64 - find last set bit in a 64-bit word
8 * @x: the word to search
9 *
10 * This is defined in a similar way as the libc and compiler builtin
11 * ffsll, but returns the position of the most significant set bit.
12 *
13 * fls64(value) returns 0 if value is 0 or the position of the last
14 * set bit if value is nonzero. The last (most significant) bit is
15 * at position 64.
16 */
17#if BITS_PER_LONG == 32
18static __always_inline int fls64(__u64 x)
19{
20 __u32 h = x >> 32;
21 if (h)
22 return fls(h) + 32;
23 return fls(x);
24}
25#elif BITS_PER_LONG == 64
26static __always_inline int fls64(__u64 x)
27{
28 if (x == 0)
29 return 0;
30 return __fls(x) + 1;
31}
32#else
33#error BITS_PER_LONG not 32 or 64
34#endif
35
36#endif /* _ASM_GENERIC_BITOPS_FLS64_H_ */
diff --git a/tools/include/asm-generic/bitsperlong.h b/tools/include/asm-generic/bitsperlong.h
new file mode 100644
index 000000000000..45eca517efb3
--- /dev/null
+++ b/tools/include/asm-generic/bitsperlong.h
@@ -0,0 +1,20 @@
1#ifndef __ASM_GENERIC_BITS_PER_LONG
2#define __ASM_GENERIC_BITS_PER_LONG
3
4#include <uapi/asm-generic/bitsperlong.h>
5
6#ifdef __SIZEOF_LONG__
7#define BITS_PER_LONG (__CHAR_BIT__ * __SIZEOF_LONG__)
8#else
9#define BITS_PER_LONG __WORDSIZE
10#endif
11
12#if BITS_PER_LONG != __BITS_PER_LONG
13#error Inconsistent word size. Check asm/bitsperlong.h
14#endif
15
16#ifndef BITS_PER_LONG_LONG
17#define BITS_PER_LONG_LONG 64
18#endif
19
20#endif /* __ASM_GENERIC_BITS_PER_LONG */
diff --git a/tools/perf/util/include/asm/alternative-asm.h b/tools/include/asm/alternative-asm.h
index 3a3a0f16456a..2a4d1bfa2988 100644
--- a/tools/perf/util/include/asm/alternative-asm.h
+++ b/tools/include/asm/alternative-asm.h
@@ -1,5 +1,5 @@
1#ifndef _PERF_ASM_ALTERNATIVE_ASM_H 1#ifndef _TOOLS_ASM_ALTERNATIVE_ASM_H
2#define _PERF_ASM_ALTERNATIVE_ASM_H 2#define _TOOLS_ASM_ALTERNATIVE_ASM_H
3 3
4/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */ 4/* Just disable it so we can build arch/x86/lib/memcpy_64.S for perf bench: */
5 5
diff --git a/tools/include/linux/bitmap.h b/tools/include/linux/bitmap.h
index 28f5493da491..43c1c5021e4b 100644
--- a/tools/include/linux/bitmap.h
+++ b/tools/include/linux/bitmap.h
@@ -3,6 +3,7 @@
3 3
4#include <string.h> 4#include <string.h>
5#include <linux/bitops.h> 5#include <linux/bitops.h>
6#include <stdlib.h>
6 7
7#define DECLARE_BITMAP(name,bits) \ 8#define DECLARE_BITMAP(name,bits) \
8 unsigned long name[BITS_TO_LONGS(bits)] 9 unsigned long name[BITS_TO_LONGS(bits)]
@@ -10,6 +11,8 @@
10int __bitmap_weight(const unsigned long *bitmap, int bits); 11int __bitmap_weight(const unsigned long *bitmap, int bits);
11void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1, 12void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
12 const unsigned long *bitmap2, int bits); 13 const unsigned long *bitmap2, int bits);
14int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
15 const unsigned long *bitmap2, unsigned int bits);
13 16
14#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1))) 17#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) & (BITS_PER_LONG - 1)))
15 18
@@ -65,4 +68,38 @@ static inline int test_and_set_bit(int nr, unsigned long *addr)
65 return (old & mask) != 0; 68 return (old & mask) != 0;
66} 69}
67 70
71/**
72 * bitmap_alloc - Allocate bitmap
73 * @nr: Bit to set
74 */
75static inline unsigned long *bitmap_alloc(int nbits)
76{
77 return calloc(1, BITS_TO_LONGS(nbits) * sizeof(unsigned long));
78}
79
80/*
81 * bitmap_scnprintf - print bitmap list into buffer
82 * @bitmap: bitmap
83 * @nbits: size of bitmap
84 * @buf: buffer to store output
85 * @size: size of @buf
86 */
87size_t bitmap_scnprintf(unsigned long *bitmap, int nbits,
88 char *buf, size_t size);
89
90/**
91 * bitmap_and - Do logical and on bitmaps
92 * @dst: resulting bitmap
93 * @src1: operand 1
94 * @src2: operand 2
95 * @nbits: size of bitmap
96 */
97static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
98 const unsigned long *src2, unsigned int nbits)
99{
100 if (small_const_nbits(nbits))
101 return (*dst = *src1 & *src2 & BITMAP_LAST_WORD_MASK(nbits)) != 0;
102 return __bitmap_and(dst, src1, src2, nbits);
103}
104
68#endif /* _PERF_BITOPS_H */ 105#endif /* _PERF_BITOPS_H */
diff --git a/tools/include/linux/bitops.h b/tools/include/linux/bitops.h
index 5ad9ee1dd7f6..49c929a104ee 100644
--- a/tools/include/linux/bitops.h
+++ b/tools/include/linux/bitops.h
@@ -9,7 +9,9 @@
9#define __WORDSIZE (__SIZEOF_LONG__ * 8) 9#define __WORDSIZE (__SIZEOF_LONG__ * 8)
10#endif 10#endif
11 11
12#define BITS_PER_LONG __WORDSIZE 12#ifndef BITS_PER_LONG
13# define BITS_PER_LONG __WORDSIZE
14#endif
13 15
14#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG)) 16#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
15#define BIT_WORD(nr) ((nr) / BITS_PER_LONG) 17#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
diff --git a/tools/include/linux/compiler.h b/tools/include/linux/compiler.h
index fa7208a32d76..e33fc1df3935 100644
--- a/tools/include/linux/compiler.h
+++ b/tools/include/linux/compiler.h
@@ -9,6 +9,17 @@
9# define __always_inline inline __attribute__((always_inline)) 9# define __always_inline inline __attribute__((always_inline))
10#endif 10#endif
11 11
12#ifdef __ANDROID__
13/*
14 * FIXME: Big hammer to get rid of tons of:
15 * "warning: always_inline function might not be inlinable"
16 *
17 * At least on android-ndk-r12/platforms/android-24/arch-arm
18 */
19#undef __always_inline
20#define __always_inline inline
21#endif
22
12#define __user 23#define __user
13 24
14#ifndef __attribute_const__ 25#ifndef __attribute_const__
diff --git a/tools/include/linux/coresight-pmu.h b/tools/include/linux/coresight-pmu.h
new file mode 100644
index 000000000000..7d410260661b
--- /dev/null
+++ b/tools/include/linux/coresight-pmu.h
@@ -0,0 +1,39 @@
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 _LINUX_CORESIGHT_PMU_H
19#define _LINUX_CORESIGHT_PMU_H
20
21#define CORESIGHT_ETM_PMU_NAME "cs_etm"
22#define CORESIGHT_ETM_PMU_SEED 0x10
23
24/* ETMv3.5/PTM's ETMCR config bit */
25#define ETM_OPT_CYCACC 12
26#define ETM_OPT_TS 28
27
28static inline int coresight_get_trace_id(int cpu)
29{
30 /*
31 * A trace ID of value 0 is invalid, so let's start at some
32 * random value that fits in 7 bits and go from there. Since
33 * the common convention is to have data trace IDs be I(N) + 1,
34 * set instruction trace IDs as a function of the CPU number.
35 */
36 return (CORESIGHT_ETM_PMU_SEED + (cpu * 2));
37}
38
39#endif
diff --git a/tools/include/linux/hash.h b/tools/include/linux/hash.h
index d026c6573018..ad6fa21d977b 100644
--- a/tools/include/linux/hash.h
+++ b/tools/include/linux/hash.h
@@ -1,5 +1,104 @@
1#include "../../../include/linux/hash.h" 1#ifndef _LINUX_HASH_H
2#define _LINUX_HASH_H
3/* Fast hashing routine for ints, longs and pointers.
4 (C) 2002 Nadia Yvette Chambers, IBM */
2 5
3#ifndef _TOOLS_LINUX_HASH_H 6#include <asm/types.h>
4#define _TOOLS_LINUX_HASH_H 7#include <linux/compiler.h>
8
9/*
10 * The "GOLDEN_RATIO_PRIME" is used in ifs/btrfs/brtfs_inode.h and
11 * fs/inode.c. It's not actually prime any more (the previous primes
12 * were actively bad for hashing), but the name remains.
13 */
14#if BITS_PER_LONG == 32
15#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_32
16#define hash_long(val, bits) hash_32(val, bits)
17#elif BITS_PER_LONG == 64
18#define hash_long(val, bits) hash_64(val, bits)
19#define GOLDEN_RATIO_PRIME GOLDEN_RATIO_64
20#else
21#error Wordsize not 32 or 64
22#endif
23
24/*
25 * This hash multiplies the input by a large odd number and takes the
26 * high bits. Since multiplication propagates changes to the most
27 * significant end only, it is essential that the high bits of the
28 * product be used for the hash value.
29 *
30 * Chuck Lever verified the effectiveness of this technique:
31 * http://www.citi.umich.edu/techreports/reports/citi-tr-00-1.pdf
32 *
33 * Although a random odd number will do, it turns out that the golden
34 * ratio phi = (sqrt(5)-1)/2, or its negative, has particularly nice
35 * properties. (See Knuth vol 3, section 6.4, exercise 9.)
36 *
37 * These are the negative, (1 - phi) = phi**2 = (3 - sqrt(5))/2,
38 * which is very slightly easier to multiply by and makes no
39 * difference to the hash distribution.
40 */
41#define GOLDEN_RATIO_32 0x61C88647
42#define GOLDEN_RATIO_64 0x61C8864680B583EBull
43
44#ifdef CONFIG_HAVE_ARCH_HASH
45/* This header may use the GOLDEN_RATIO_xx constants */
46#include <asm/hash.h>
47#endif
48
49/*
50 * The _generic versions exist only so lib/test_hash.c can compare
51 * the arch-optimized versions with the generic.
52 *
53 * Note that if you change these, any <asm/hash.h> that aren't updated
54 * to match need to have their HAVE_ARCH_* define values updated so the
55 * self-test will not false-positive.
56 */
57#ifndef HAVE_ARCH__HASH_32
58#define __hash_32 __hash_32_generic
59#endif
60static inline u32 __hash_32_generic(u32 val)
61{
62 return val * GOLDEN_RATIO_32;
63}
64
65#ifndef HAVE_ARCH_HASH_32
66#define hash_32 hash_32_generic
5#endif 67#endif
68static inline u32 hash_32_generic(u32 val, unsigned int bits)
69{
70 /* High bits are more random, so use them. */
71 return __hash_32(val) >> (32 - bits);
72}
73
74#ifndef HAVE_ARCH_HASH_64
75#define hash_64 hash_64_generic
76#endif
77static __always_inline u32 hash_64_generic(u64 val, unsigned int bits)
78{
79#if BITS_PER_LONG == 64
80 /* 64x64-bit multiply is efficient on all 64-bit processors */
81 return val * GOLDEN_RATIO_64 >> (64 - bits);
82#else
83 /* Hash 64 bits using only 32x32-bit multiply. */
84 return hash_32((u32)val ^ __hash_32(val >> 32), bits);
85#endif
86}
87
88static inline u32 hash_ptr(const void *ptr, unsigned int bits)
89{
90 return hash_long((unsigned long)ptr, bits);
91}
92
93/* This really should be called fold32_ptr; it does no hashing to speak of. */
94static inline u32 hash32_ptr(const void *ptr)
95{
96 unsigned long val = (unsigned long)ptr;
97
98#if BITS_PER_LONG == 64
99 val ^= (val >> 32);
100#endif
101 return (u32)val;
102}
103
104#endif /* _LINUX_HASH_H */
diff --git a/tools/include/linux/kernel.h b/tools/include/linux/kernel.h
index 76df53539c2a..28607db02bd3 100644
--- a/tools/include/linux/kernel.h
+++ b/tools/include/linux/kernel.h
@@ -2,8 +2,7 @@
2#define __TOOLS_LINUX_KERNEL_H 2#define __TOOLS_LINUX_KERNEL_H
3 3
4#include <stdarg.h> 4#include <stdarg.h>
5#include <stdio.h> 5#include <stddef.h>
6#include <stdlib.h>
7#include <assert.h> 6#include <assert.h>
8 7
9#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d)) 8#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
@@ -70,29 +69,8 @@
70#define cpu_to_le64(x) (x) 69#define cpu_to_le64(x) (x)
71#define cpu_to_le32(x) (x) 70#define cpu_to_le32(x) (x)
72 71
73static inline int 72int vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
74vscnprintf(char *buf, size_t size, const char *fmt, va_list args) 73int scnprintf(char * buf, size_t size, const char * fmt, ...);
75{
76 int i;
77 ssize_t ssize = size;
78
79 i = vsnprintf(buf, size, fmt, args);
80
81 return (i >= ssize) ? (ssize - 1) : i;
82}
83
84static inline int scnprintf(char * buf, size_t size, const char * fmt, ...)
85{
86 va_list args;
87 ssize_t ssize = size;
88 int i;
89
90 va_start(args, fmt);
91 i = vsnprintf(buf, size, fmt, args);
92 va_end(args);
93
94 return (i >= ssize) ? (ssize - 1) : i;
95}
96 74
97/* 75/*
98 * This looks more complex than it should be. But we need to 76 * This looks more complex than it should be. But we need to
diff --git a/tools/include/linux/poison.h b/tools/include/linux/poison.h
index 0c27bdf14233..51334edec506 100644
--- a/tools/include/linux/poison.h
+++ b/tools/include/linux/poison.h
@@ -1 +1,90 @@
1#include "../../../include/linux/poison.h" 1#ifndef _LINUX_POISON_H
2#define _LINUX_POISON_H
3
4/********** include/linux/list.h **********/
5
6/*
7 * Architectures might want to move the poison pointer offset
8 * into some well-recognized area such as 0xdead000000000000,
9 * that is also not mappable by user-space exploits:
10 */
11#ifdef CONFIG_ILLEGAL_POINTER_VALUE
12# define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
13#else
14# define POISON_POINTER_DELTA 0
15#endif
16
17/*
18 * These are non-NULL pointers that will result in page faults
19 * under normal circumstances, used to verify that nobody uses
20 * non-initialized list entries.
21 */
22#define LIST_POISON1 ((void *) 0x100 + POISON_POINTER_DELTA)
23#define LIST_POISON2 ((void *) 0x200 + POISON_POINTER_DELTA)
24
25/********** include/linux/timer.h **********/
26/*
27 * Magic number "tsta" to indicate a static timer initializer
28 * for the object debugging code.
29 */
30#define TIMER_ENTRY_STATIC ((void *) 0x300 + POISON_POINTER_DELTA)
31
32/********** mm/debug-pagealloc.c **********/
33#ifdef CONFIG_PAGE_POISONING_ZERO
34#define PAGE_POISON 0x00
35#else
36#define PAGE_POISON 0xaa
37#endif
38
39/********** mm/page_alloc.c ************/
40
41#define TAIL_MAPPING ((void *) 0x400 + POISON_POINTER_DELTA)
42
43/********** mm/slab.c **********/
44/*
45 * Magic nums for obj red zoning.
46 * Placed in the first word before and the first word after an obj.
47 */
48#define RED_INACTIVE 0x09F911029D74E35BULL /* when obj is inactive */
49#define RED_ACTIVE 0xD84156C5635688C0ULL /* when obj is active */
50
51#define SLUB_RED_INACTIVE 0xbb
52#define SLUB_RED_ACTIVE 0xcc
53
54/* ...and for poisoning */
55#define POISON_INUSE 0x5a /* for use-uninitialised poisoning */
56#define POISON_FREE 0x6b /* for use-after-free poisoning */
57#define POISON_END 0xa5 /* end-byte of poisoning */
58
59/********** arch/$ARCH/mm/init.c **********/
60#define POISON_FREE_INITMEM 0xcc
61
62/********** arch/ia64/hp/common/sba_iommu.c **********/
63/*
64 * arch/ia64/hp/common/sba_iommu.c uses a 16-byte poison string with a
65 * value of "SBAIOMMU POISON\0" for spill-over poisoning.
66 */
67
68/********** fs/jbd/journal.c **********/
69#define JBD_POISON_FREE 0x5b
70#define JBD2_POISON_FREE 0x5c
71
72/********** drivers/base/dmapool.c **********/
73#define POOL_POISON_FREED 0xa7 /* !inuse */
74#define POOL_POISON_ALLOCATED 0xa9 /* !initted */
75
76/********** drivers/atm/ **********/
77#define ATM_POISON_FREE 0x12
78#define ATM_POISON 0xdeadbeef
79
80/********** kernel/mutexes **********/
81#define MUTEX_DEBUG_INIT 0x11
82#define MUTEX_DEBUG_FREE 0x22
83
84/********** lib/flex_array.c **********/
85#define FLEX_ARRAY_FREE 0x6c /* for use-after-free poisoning */
86
87/********** security/ **********/
88#define KEY_DESTROY 0xbd
89
90#endif
diff --git a/tools/include/linux/string.h b/tools/include/linux/string.h
index e26223f1f287..f436d2420a18 100644
--- a/tools/include/linux/string.h
+++ b/tools/include/linux/string.h
@@ -8,8 +8,14 @@ void *memdup(const void *src, size_t len);
8 8
9int strtobool(const char *s, bool *res); 9int strtobool(const char *s, bool *res);
10 10
11#ifndef __UCLIBC__ 11/*
12 * glibc based builds needs the extern while uClibc doesn't.
13 * However uClibc headers also define __GLIBC__ hence the hack below
14 */
15#if defined(__GLIBC__) && !defined(__UCLIBC__)
12extern size_t strlcpy(char *dest, const char *src, size_t size); 16extern size_t strlcpy(char *dest, const char *src, size_t size);
13#endif 17#endif
14 18
19char *str_error_r(int errnum, char *buf, size_t buflen);
20
15#endif /* _LINUX_STRING_H_ */ 21#endif /* _LINUX_STRING_H_ */
diff --git a/tools/include/linux/time64.h b/tools/include/linux/time64.h
new file mode 100644
index 000000000000..df9265483d65
--- /dev/null
+++ b/tools/include/linux/time64.h
@@ -0,0 +1,12 @@
1#ifndef _TOOLS_LINUX_TIME64_H
2#define _TOOLS_LINUX_TIME64_H
3
4#define MSEC_PER_SEC 1000L
5#define USEC_PER_MSEC 1000L
6#define NSEC_PER_USEC 1000L
7#define NSEC_PER_MSEC 1000000L
8#define USEC_PER_SEC 1000000L
9#define NSEC_PER_SEC 1000000000L
10#define FSEC_PER_SEC 1000000000000000LL
11
12#endif /* _LINUX_TIME64_H */
diff --git a/tools/include/uapi/asm-generic/bitsperlong.h b/tools/include/uapi/asm-generic/bitsperlong.h
new file mode 100644
index 000000000000..23e6c416b85f
--- /dev/null
+++ b/tools/include/uapi/asm-generic/bitsperlong.h
@@ -0,0 +1,15 @@
1#ifndef _UAPI__ASM_GENERIC_BITS_PER_LONG
2#define _UAPI__ASM_GENERIC_BITS_PER_LONG
3
4/*
5 * There seems to be no way of detecting this automatically from user
6 * space, so 64 bit architectures should override this in their
7 * bitsperlong.h. In particular, an architecture that supports
8 * both 32 and 64 bit user space must not rely on CONFIG_64BIT
9 * to decide it, but rather check a compiler provided macro.
10 */
11#ifndef __BITS_PER_LONG
12#define __BITS_PER_LONG 32
13#endif
14
15#endif /* _UAPI__ASM_GENERIC_BITS_PER_LONG */
diff --git a/tools/include/uapi/asm-generic/mman-common.h b/tools/include/uapi/asm-generic/mman-common.h
new file mode 100644
index 000000000000..58274382a616
--- /dev/null
+++ b/tools/include/uapi/asm-generic/mman-common.h
@@ -0,0 +1,75 @@
1#ifndef __ASM_GENERIC_MMAN_COMMON_H
2#define __ASM_GENERIC_MMAN_COMMON_H
3
4/*
5 Author: Michael S. Tsirkin <mst@mellanox.co.il>, Mellanox Technologies Ltd.
6 Based on: asm-xxx/mman.h
7*/
8
9#define PROT_READ 0x1 /* page can be read */
10#define PROT_WRITE 0x2 /* page can be written */
11#define PROT_EXEC 0x4 /* page can be executed */
12#define PROT_SEM 0x8 /* page may be used for atomic ops */
13#define PROT_NONE 0x0 /* page can not be accessed */
14#define PROT_GROWSDOWN 0x01000000 /* mprotect flag: extend change to start of growsdown vma */
15#define PROT_GROWSUP 0x02000000 /* mprotect flag: extend change to end of growsup vma */
16
17#define MAP_SHARED 0x01 /* Share changes */
18#define MAP_PRIVATE 0x02 /* Changes are private */
19#define MAP_TYPE 0x0f /* Mask for type of mapping */
20#define MAP_FIXED 0x10 /* Interpret addr exactly */
21#define MAP_ANONYMOUS 0x20 /* don't use a file */
22#ifdef CONFIG_MMAP_ALLOW_UNINITIALIZED
23# define MAP_UNINITIALIZED 0x4000000 /* For anonymous mmap, memory could be uninitialized */
24#else
25# define MAP_UNINITIALIZED 0x0 /* Don't support this flag */
26#endif
27
28/*
29 * Flags for mlock
30 */
31#define MLOCK_ONFAULT 0x01 /* Lock pages in range after they are faulted in, do not prefault */
32
33#define MS_ASYNC 1 /* sync memory asynchronously */
34#define MS_INVALIDATE 2 /* invalidate the caches */
35#define MS_SYNC 4 /* synchronous memory sync */
36
37#define MADV_NORMAL 0 /* no further special treatment */
38#define MADV_RANDOM 1 /* expect random page references */
39#define MADV_SEQUENTIAL 2 /* expect sequential page references */
40#define MADV_WILLNEED 3 /* will need these pages */
41#define MADV_DONTNEED 4 /* don't need these pages */
42
43/* common parameters: try to keep these consistent across architectures */
44#define MADV_FREE 8 /* free pages only if memory pressure */
45#define MADV_REMOVE 9 /* remove these pages & resources */
46#define MADV_DONTFORK 10 /* don't inherit across fork */
47#define MADV_DOFORK 11 /* do inherit across fork */
48#define MADV_HWPOISON 100 /* poison a page for testing */
49#define MADV_SOFT_OFFLINE 101 /* soft offline page for testing */
50
51#define MADV_MERGEABLE 12 /* KSM may merge identical pages */
52#define MADV_UNMERGEABLE 13 /* KSM may not merge identical pages */
53
54#define MADV_HUGEPAGE 14 /* Worth backing with hugepages */
55#define MADV_NOHUGEPAGE 15 /* Not worth backing with hugepages */
56
57#define MADV_DONTDUMP 16 /* Explicity exclude from the core dump,
58 overrides the coredump filter bits */
59#define MADV_DODUMP 17 /* Clear the MADV_DONTDUMP flag */
60
61/* compatibility flags */
62#define MAP_FILE 0
63
64/*
65 * When MAP_HUGETLB is set bits [26:31] encode the log2 of the huge page size.
66 * This gives us 6 bits, which is enough until someone invents 128 bit address
67 * spaces.
68 *
69 * Assume these are all power of twos.
70 * When 0 use the default page size.
71 */
72#define MAP_HUGE_SHIFT 26
73#define MAP_HUGE_MASK 0x3f
74
75#endif /* __ASM_GENERIC_MMAN_COMMON_H */
diff --git a/tools/include/uapi/asm-generic/mman.h b/tools/include/uapi/asm-generic/mman.h
new file mode 100644
index 000000000000..10fa7857777f
--- /dev/null
+++ b/tools/include/uapi/asm-generic/mman.h
@@ -0,0 +1,22 @@
1#ifndef __ASM_GENERIC_MMAN_H
2#define __ASM_GENERIC_MMAN_H
3
4#include <uapi/asm-generic/mman-common.h>
5
6#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
7#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
8#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
9#define MAP_LOCKED 0x2000 /* pages are locked */
10#define MAP_NORESERVE 0x4000 /* don't check for reservations */
11#define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */
12#define MAP_NONBLOCK 0x10000 /* do not block on IO */
13#define MAP_STACK 0x20000 /* give out an address that is best suited for process/thread stacks */
14#define MAP_HUGETLB 0x40000 /* create a huge page mapping */
15
16/* Bits [26:31] are reserved, see mman-common.h for MAP_HUGETLB usage */
17
18#define MCL_CURRENT 1 /* lock all current mappings */
19#define MCL_FUTURE 2 /* lock all future mappings */
20#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
21
22#endif /* __ASM_GENERIC_MMAN_H */
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
new file mode 100644
index 000000000000..9e5fc168c8a3
--- /dev/null
+++ b/tools/include/uapi/linux/bpf.h
@@ -0,0 +1,473 @@
1/* Copyright (c) 2011-2014 PLUMgrid, http://plumgrid.com
2 *
3 * This program is free software; you can redistribute it and/or
4 * modify it under the terms of version 2 of the GNU General Public
5 * License as published by the Free Software Foundation.
6 */
7#ifndef _UAPI__LINUX_BPF_H__
8#define _UAPI__LINUX_BPF_H__
9
10#include <linux/types.h>
11#include <linux/bpf_common.h>
12
13/* Extended instruction set based on top of classic BPF */
14
15/* instruction classes */
16#define BPF_ALU64 0x07 /* alu mode in double word width */
17
18/* ld/ldx fields */
19#define BPF_DW 0x18 /* double word */
20#define BPF_XADD 0xc0 /* exclusive add */
21
22/* alu/jmp fields */
23#define BPF_MOV 0xb0 /* mov reg to reg */
24#define BPF_ARSH 0xc0 /* sign extending arithmetic shift right */
25
26/* change endianness of a register */
27#define BPF_END 0xd0 /* flags for endianness conversion: */
28#define BPF_TO_LE 0x00 /* convert to little-endian */
29#define BPF_TO_BE 0x08 /* convert to big-endian */
30#define BPF_FROM_LE BPF_TO_LE
31#define BPF_FROM_BE BPF_TO_BE
32
33#define BPF_JNE 0x50 /* jump != */
34#define BPF_JSGT 0x60 /* SGT is signed '>', GT in x86 */
35#define BPF_JSGE 0x70 /* SGE is signed '>=', GE in x86 */
36#define BPF_CALL 0x80 /* function call */
37#define BPF_EXIT 0x90 /* function return */
38
39/* Register numbers */
40enum {
41 BPF_REG_0 = 0,
42 BPF_REG_1,
43 BPF_REG_2,
44 BPF_REG_3,
45 BPF_REG_4,
46 BPF_REG_5,
47 BPF_REG_6,
48 BPF_REG_7,
49 BPF_REG_8,
50 BPF_REG_9,
51 BPF_REG_10,
52 __MAX_BPF_REG,
53};
54
55/* BPF has 10 general purpose 64-bit registers and stack frame. */
56#define MAX_BPF_REG __MAX_BPF_REG
57
58struct bpf_insn {
59 __u8 code; /* opcode */
60 __u8 dst_reg:4; /* dest register */
61 __u8 src_reg:4; /* source register */
62 __s16 off; /* signed offset */
63 __s32 imm; /* signed immediate constant */
64};
65
66/* BPF syscall commands, see bpf(2) man-page for details. */
67enum bpf_cmd {
68 BPF_MAP_CREATE,
69 BPF_MAP_LOOKUP_ELEM,
70 BPF_MAP_UPDATE_ELEM,
71 BPF_MAP_DELETE_ELEM,
72 BPF_MAP_GET_NEXT_KEY,
73 BPF_PROG_LOAD,
74 BPF_OBJ_PIN,
75 BPF_OBJ_GET,
76};
77
78enum bpf_map_type {
79 BPF_MAP_TYPE_UNSPEC,
80 BPF_MAP_TYPE_HASH,
81 BPF_MAP_TYPE_ARRAY,
82 BPF_MAP_TYPE_PROG_ARRAY,
83 BPF_MAP_TYPE_PERF_EVENT_ARRAY,
84 BPF_MAP_TYPE_PERCPU_HASH,
85 BPF_MAP_TYPE_PERCPU_ARRAY,
86 BPF_MAP_TYPE_STACK_TRACE,
87 BPF_MAP_TYPE_CGROUP_ARRAY,
88};
89
90enum bpf_prog_type {
91 BPF_PROG_TYPE_UNSPEC,
92 BPF_PROG_TYPE_SOCKET_FILTER,
93 BPF_PROG_TYPE_KPROBE,
94 BPF_PROG_TYPE_SCHED_CLS,
95 BPF_PROG_TYPE_SCHED_ACT,
96 BPF_PROG_TYPE_TRACEPOINT,
97 BPF_PROG_TYPE_XDP,
98};
99
100#define BPF_PSEUDO_MAP_FD 1
101
102/* flags for BPF_MAP_UPDATE_ELEM command */
103#define BPF_ANY 0 /* create new element or update existing */
104#define BPF_NOEXIST 1 /* create new element if it didn't exist */
105#define BPF_EXIST 2 /* update existing element */
106
107#define BPF_F_NO_PREALLOC (1U << 0)
108
109union bpf_attr {
110 struct { /* anonymous struct used by BPF_MAP_CREATE command */
111 __u32 map_type; /* one of enum bpf_map_type */
112 __u32 key_size; /* size of key in bytes */
113 __u32 value_size; /* size of value in bytes */
114 __u32 max_entries; /* max number of entries in a map */
115 __u32 map_flags; /* prealloc or not */
116 };
117
118 struct { /* anonymous struct used by BPF_MAP_*_ELEM commands */
119 __u32 map_fd;
120 __aligned_u64 key;
121 union {
122 __aligned_u64 value;
123 __aligned_u64 next_key;
124 };
125 __u64 flags;
126 };
127
128 struct { /* anonymous struct used by BPF_PROG_LOAD command */
129 __u32 prog_type; /* one of enum bpf_prog_type */
130 __u32 insn_cnt;
131 __aligned_u64 insns;
132 __aligned_u64 license;
133 __u32 log_level; /* verbosity level of verifier */
134 __u32 log_size; /* size of user buffer */
135 __aligned_u64 log_buf; /* user supplied buffer */
136 __u32 kern_version; /* checked when prog_type=kprobe */
137 };
138
139 struct { /* anonymous struct used by BPF_OBJ_* commands */
140 __aligned_u64 pathname;
141 __u32 bpf_fd;
142 };
143} __attribute__((aligned(8)));
144
145/* integer value in 'imm' field of BPF_CALL instruction selects which helper
146 * function eBPF program intends to call
147 */
148enum bpf_func_id {
149 BPF_FUNC_unspec,
150 BPF_FUNC_map_lookup_elem, /* void *map_lookup_elem(&map, &key) */
151 BPF_FUNC_map_update_elem, /* int map_update_elem(&map, &key, &value, flags) */
152 BPF_FUNC_map_delete_elem, /* int map_delete_elem(&map, &key) */
153 BPF_FUNC_probe_read, /* int bpf_probe_read(void *dst, int size, void *src) */
154 BPF_FUNC_ktime_get_ns, /* u64 bpf_ktime_get_ns(void) */
155 BPF_FUNC_trace_printk, /* int bpf_trace_printk(const char *fmt, int fmt_size, ...) */
156 BPF_FUNC_get_prandom_u32, /* u32 prandom_u32(void) */
157 BPF_FUNC_get_smp_processor_id, /* u32 raw_smp_processor_id(void) */
158
159 /**
160 * skb_store_bytes(skb, offset, from, len, flags) - store bytes into packet
161 * @skb: pointer to skb
162 * @offset: offset within packet from skb->mac_header
163 * @from: pointer where to copy bytes from
164 * @len: number of bytes to store into packet
165 * @flags: bit 0 - if true, recompute skb->csum
166 * other bits - reserved
167 * Return: 0 on success
168 */
169 BPF_FUNC_skb_store_bytes,
170
171 /**
172 * l3_csum_replace(skb, offset, from, to, flags) - recompute IP checksum
173 * @skb: pointer to skb
174 * @offset: offset within packet where IP checksum is located
175 * @from: old value of header field
176 * @to: new value of header field
177 * @flags: bits 0-3 - size of header field
178 * other bits - reserved
179 * Return: 0 on success
180 */
181 BPF_FUNC_l3_csum_replace,
182
183 /**
184 * l4_csum_replace(skb, offset, from, to, flags) - recompute TCP/UDP checksum
185 * @skb: pointer to skb
186 * @offset: offset within packet where TCP/UDP checksum is located
187 * @from: old value of header field
188 * @to: new value of header field
189 * @flags: bits 0-3 - size of header field
190 * bit 4 - is pseudo header
191 * other bits - reserved
192 * Return: 0 on success
193 */
194 BPF_FUNC_l4_csum_replace,
195
196 /**
197 * bpf_tail_call(ctx, prog_array_map, index) - jump into another BPF program
198 * @ctx: context pointer passed to next program
199 * @prog_array_map: pointer to map which type is BPF_MAP_TYPE_PROG_ARRAY
200 * @index: index inside array that selects specific program to run
201 * Return: 0 on success
202 */
203 BPF_FUNC_tail_call,
204
205 /**
206 * bpf_clone_redirect(skb, ifindex, flags) - redirect to another netdev
207 * @skb: pointer to skb
208 * @ifindex: ifindex of the net device
209 * @flags: bit 0 - if set, redirect to ingress instead of egress
210 * other bits - reserved
211 * Return: 0 on success
212 */
213 BPF_FUNC_clone_redirect,
214
215 /**
216 * u64 bpf_get_current_pid_tgid(void)
217 * Return: current->tgid << 32 | current->pid
218 */
219 BPF_FUNC_get_current_pid_tgid,
220
221 /**
222 * u64 bpf_get_current_uid_gid(void)
223 * Return: current_gid << 32 | current_uid
224 */
225 BPF_FUNC_get_current_uid_gid,
226
227 /**
228 * bpf_get_current_comm(char *buf, int size_of_buf)
229 * stores current->comm into buf
230 * Return: 0 on success
231 */
232 BPF_FUNC_get_current_comm,
233
234 /**
235 * bpf_get_cgroup_classid(skb) - retrieve a proc's classid
236 * @skb: pointer to skb
237 * Return: classid if != 0
238 */
239 BPF_FUNC_get_cgroup_classid,
240 BPF_FUNC_skb_vlan_push, /* bpf_skb_vlan_push(skb, vlan_proto, vlan_tci) */
241 BPF_FUNC_skb_vlan_pop, /* bpf_skb_vlan_pop(skb) */
242
243 /**
244 * bpf_skb_[gs]et_tunnel_key(skb, key, size, flags)
245 * retrieve or populate tunnel metadata
246 * @skb: pointer to skb
247 * @key: pointer to 'struct bpf_tunnel_key'
248 * @size: size of 'struct bpf_tunnel_key'
249 * @flags: room for future extensions
250 * Retrun: 0 on success
251 */
252 BPF_FUNC_skb_get_tunnel_key,
253 BPF_FUNC_skb_set_tunnel_key,
254 BPF_FUNC_perf_event_read, /* u64 bpf_perf_event_read(&map, index) */
255 /**
256 * bpf_redirect(ifindex, flags) - redirect to another netdev
257 * @ifindex: ifindex of the net device
258 * @flags: bit 0 - if set, redirect to ingress instead of egress
259 * other bits - reserved
260 * Return: TC_ACT_REDIRECT
261 */
262 BPF_FUNC_redirect,
263
264 /**
265 * bpf_get_route_realm(skb) - retrieve a dst's tclassid
266 * @skb: pointer to skb
267 * Return: realm if != 0
268 */
269 BPF_FUNC_get_route_realm,
270
271 /**
272 * bpf_perf_event_output(ctx, map, index, data, size) - output perf raw sample
273 * @ctx: struct pt_regs*
274 * @map: pointer to perf_event_array map
275 * @index: index of event in the map
276 * @data: data on stack to be output as raw data
277 * @size: size of data
278 * Return: 0 on success
279 */
280 BPF_FUNC_perf_event_output,
281 BPF_FUNC_skb_load_bytes,
282
283 /**
284 * bpf_get_stackid(ctx, map, flags) - walk user or kernel stack and return id
285 * @ctx: struct pt_regs*
286 * @map: pointer to stack_trace map
287 * @flags: bits 0-7 - numer of stack frames to skip
288 * bit 8 - collect user stack instead of kernel
289 * bit 9 - compare stacks by hash only
290 * bit 10 - if two different stacks hash into the same stackid
291 * discard old
292 * other bits - reserved
293 * Return: >= 0 stackid on success or negative error
294 */
295 BPF_FUNC_get_stackid,
296
297 /**
298 * bpf_csum_diff(from, from_size, to, to_size, seed) - calculate csum diff
299 * @from: raw from buffer
300 * @from_size: length of from buffer
301 * @to: raw to buffer
302 * @to_size: length of to buffer
303 * @seed: optional seed
304 * Return: csum result
305 */
306 BPF_FUNC_csum_diff,
307
308 /**
309 * bpf_skb_[gs]et_tunnel_opt(skb, opt, size)
310 * retrieve or populate tunnel options metadata
311 * @skb: pointer to skb
312 * @opt: pointer to raw tunnel option data
313 * @size: size of @opt
314 * Return: 0 on success for set, option size for get
315 */
316 BPF_FUNC_skb_get_tunnel_opt,
317 BPF_FUNC_skb_set_tunnel_opt,
318
319 /**
320 * bpf_skb_change_proto(skb, proto, flags)
321 * Change protocol of the skb. Currently supported is
322 * v4 -> v6, v6 -> v4 transitions. The helper will also
323 * resize the skb. eBPF program is expected to fill the
324 * new headers via skb_store_bytes and lX_csum_replace.
325 * @skb: pointer to skb
326 * @proto: new skb->protocol type
327 * @flags: reserved
328 * Return: 0 on success or negative error
329 */
330 BPF_FUNC_skb_change_proto,
331
332 /**
333 * bpf_skb_change_type(skb, type)
334 * Change packet type of skb.
335 * @skb: pointer to skb
336 * @type: new skb->pkt_type type
337 * Return: 0 on success or negative error
338 */
339 BPF_FUNC_skb_change_type,
340
341 /**
342 * bpf_skb_under_cgroup(skb, map, index) - Check cgroup2 membership of skb
343 * @skb: pointer to skb
344 * @map: pointer to bpf_map in BPF_MAP_TYPE_CGROUP_ARRAY type
345 * @index: index of the cgroup in the bpf_map
346 * Return:
347 * == 0 skb failed the cgroup2 descendant test
348 * == 1 skb succeeded the cgroup2 descendant test
349 * < 0 error
350 */
351 BPF_FUNC_skb_under_cgroup,
352
353 /**
354 * bpf_get_hash_recalc(skb)
355 * Retrieve and possibly recalculate skb->hash.
356 * @skb: pointer to skb
357 * Return: hash
358 */
359 BPF_FUNC_get_hash_recalc,
360
361 /**
362 * u64 bpf_get_current_task(void)
363 * Returns current task_struct
364 * Return: current
365 */
366 BPF_FUNC_get_current_task,
367
368 /**
369 * bpf_probe_write_user(void *dst, void *src, int len)
370 * safely attempt to write to a location
371 * @dst: destination address in userspace
372 * @src: source address on stack
373 * @len: number of bytes to copy
374 * Return: 0 on success or negative error
375 */
376 BPF_FUNC_probe_write_user,
377
378 __BPF_FUNC_MAX_ID,
379};
380
381/* All flags used by eBPF helper functions, placed here. */
382
383/* BPF_FUNC_skb_store_bytes flags. */
384#define BPF_F_RECOMPUTE_CSUM (1ULL << 0)
385#define BPF_F_INVALIDATE_HASH (1ULL << 1)
386
387/* BPF_FUNC_l3_csum_replace and BPF_FUNC_l4_csum_replace flags.
388 * First 4 bits are for passing the header field size.
389 */
390#define BPF_F_HDR_FIELD_MASK 0xfULL
391
392/* BPF_FUNC_l4_csum_replace flags. */
393#define BPF_F_PSEUDO_HDR (1ULL << 4)
394#define BPF_F_MARK_MANGLED_0 (1ULL << 5)
395
396/* BPF_FUNC_clone_redirect and BPF_FUNC_redirect flags. */
397#define BPF_F_INGRESS (1ULL << 0)
398
399/* BPF_FUNC_skb_set_tunnel_key and BPF_FUNC_skb_get_tunnel_key flags. */
400#define BPF_F_TUNINFO_IPV6 (1ULL << 0)
401
402/* BPF_FUNC_get_stackid flags. */
403#define BPF_F_SKIP_FIELD_MASK 0xffULL
404#define BPF_F_USER_STACK (1ULL << 8)
405#define BPF_F_FAST_STACK_CMP (1ULL << 9)
406#define BPF_F_REUSE_STACKID (1ULL << 10)
407
408/* BPF_FUNC_skb_set_tunnel_key flags. */
409#define BPF_F_ZERO_CSUM_TX (1ULL << 1)
410#define BPF_F_DONT_FRAGMENT (1ULL << 2)
411
412/* BPF_FUNC_perf_event_output and BPF_FUNC_perf_event_read flags. */
413#define BPF_F_INDEX_MASK 0xffffffffULL
414#define BPF_F_CURRENT_CPU BPF_F_INDEX_MASK
415/* BPF_FUNC_perf_event_output for sk_buff input context. */
416#define BPF_F_CTXLEN_MASK (0xfffffULL << 32)
417
418/* user accessible mirror of in-kernel sk_buff.
419 * new fields can only be added to the end of this structure
420 */
421struct __sk_buff {
422 __u32 len;
423 __u32 pkt_type;
424 __u32 mark;
425 __u32 queue_mapping;
426 __u32 protocol;
427 __u32 vlan_present;
428 __u32 vlan_tci;
429 __u32 vlan_proto;
430 __u32 priority;
431 __u32 ingress_ifindex;
432 __u32 ifindex;
433 __u32 tc_index;
434 __u32 cb[5];
435 __u32 hash;
436 __u32 tc_classid;
437 __u32 data;
438 __u32 data_end;
439};
440
441struct bpf_tunnel_key {
442 __u32 tunnel_id;
443 union {
444 __u32 remote_ipv4;
445 __u32 remote_ipv6[4];
446 };
447 __u8 tunnel_tos;
448 __u8 tunnel_ttl;
449 __u16 tunnel_ext;
450 __u32 tunnel_label;
451};
452
453/* User return codes for XDP prog type.
454 * A valid XDP program must return one of these defined values. All other
455 * return codes are reserved for future use. Unknown return codes will result
456 * in packet drop.
457 */
458enum xdp_action {
459 XDP_ABORTED = 0,
460 XDP_DROP,
461 XDP_PASS,
462 XDP_TX,
463};
464
465/* user accessible metadata for XDP packet hook
466 * new fields must be added to the end of this structure
467 */
468struct xdp_md {
469 __u32 data;
470 __u32 data_end;
471};
472
473#endif /* _UAPI__LINUX_BPF_H__ */
diff --git a/tools/include/uapi/linux/bpf_common.h b/tools/include/uapi/linux/bpf_common.h
new file mode 100644
index 000000000000..a5c220e0828f
--- /dev/null
+++ b/tools/include/uapi/linux/bpf_common.h
@@ -0,0 +1,55 @@
1#ifndef _UAPI__LINUX_BPF_COMMON_H__
2#define _UAPI__LINUX_BPF_COMMON_H__
3
4/* Instruction classes */
5#define BPF_CLASS(code) ((code) & 0x07)
6#define BPF_LD 0x00
7#define BPF_LDX 0x01
8#define BPF_ST 0x02
9#define BPF_STX 0x03
10#define BPF_ALU 0x04
11#define BPF_JMP 0x05
12#define BPF_RET 0x06
13#define BPF_MISC 0x07
14
15/* ld/ldx fields */
16#define BPF_SIZE(code) ((code) & 0x18)
17#define BPF_W 0x00
18#define BPF_H 0x08
19#define BPF_B 0x10
20#define BPF_MODE(code) ((code) & 0xe0)
21#define BPF_IMM 0x00
22#define BPF_ABS 0x20
23#define BPF_IND 0x40
24#define BPF_MEM 0x60
25#define BPF_LEN 0x80
26#define BPF_MSH 0xa0
27
28/* alu/jmp fields */
29#define BPF_OP(code) ((code) & 0xf0)
30#define BPF_ADD 0x00
31#define BPF_SUB 0x10
32#define BPF_MUL 0x20
33#define BPF_DIV 0x30
34#define BPF_OR 0x40
35#define BPF_AND 0x50
36#define BPF_LSH 0x60
37#define BPF_RSH 0x70
38#define BPF_NEG 0x80
39#define BPF_MOD 0x90
40#define BPF_XOR 0xa0
41
42#define BPF_JA 0x00
43#define BPF_JEQ 0x10
44#define BPF_JGT 0x20
45#define BPF_JGE 0x30
46#define BPF_JSET 0x40
47#define BPF_SRC(code) ((code) & 0x08)
48#define BPF_K 0x00
49#define BPF_X 0x08
50
51#ifndef BPF_MAXINSNS
52#define BPF_MAXINSNS 4096
53#endif
54
55#endif /* _UAPI__LINUX_BPF_COMMON_H__ */
diff --git a/tools/include/uapi/linux/hw_breakpoint.h b/tools/include/uapi/linux/hw_breakpoint.h
new file mode 100644
index 000000000000..b04000a2296a
--- /dev/null
+++ b/tools/include/uapi/linux/hw_breakpoint.h
@@ -0,0 +1,30 @@
1#ifndef _UAPI_LINUX_HW_BREAKPOINT_H
2#define _UAPI_LINUX_HW_BREAKPOINT_H
3
4enum {
5 HW_BREAKPOINT_LEN_1 = 1,
6 HW_BREAKPOINT_LEN_2 = 2,
7 HW_BREAKPOINT_LEN_4 = 4,
8 HW_BREAKPOINT_LEN_8 = 8,
9};
10
11enum {
12 HW_BREAKPOINT_EMPTY = 0,
13 HW_BREAKPOINT_R = 1,
14 HW_BREAKPOINT_W = 2,
15 HW_BREAKPOINT_RW = HW_BREAKPOINT_R | HW_BREAKPOINT_W,
16 HW_BREAKPOINT_X = 4,
17 HW_BREAKPOINT_INVALID = HW_BREAKPOINT_RW | HW_BREAKPOINT_X,
18};
19
20enum bp_type_idx {
21 TYPE_INST = 0,
22#ifdef CONFIG_HAVE_MIXED_BREAKPOINTS_REGS
23 TYPE_DATA = 0,
24#else
25 TYPE_DATA = 1,
26#endif
27 TYPE_MAX
28};
29
30#endif /* _UAPI_LINUX_HW_BREAKPOINT_H */
diff --git a/tools/include/uapi/linux/mman.h b/tools/include/uapi/linux/mman.h
new file mode 100644
index 000000000000..81d8edf11789
--- /dev/null
+++ b/tools/include/uapi/linux/mman.h
@@ -0,0 +1,13 @@
1#ifndef _UAPI_LINUX_MMAN_H
2#define _UAPI_LINUX_MMAN_H
3
4#include <uapi/asm/mman.h>
5
6#define MREMAP_MAYMOVE 1
7#define MREMAP_FIXED 2
8
9#define OVERCOMMIT_GUESS 0
10#define OVERCOMMIT_ALWAYS 1
11#define OVERCOMMIT_NEVER 2
12
13#endif /* _UAPI_LINUX_MMAN_H */
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
new file mode 100644
index 000000000000..c66a485a24ac
--- /dev/null
+++ b/tools/include/uapi/linux/perf_event.h
@@ -0,0 +1,983 @@
1/*
2 * Performance events:
3 *
4 * Copyright (C) 2008-2009, Thomas Gleixner <tglx@linutronix.de>
5 * Copyright (C) 2008-2011, Red Hat, Inc., Ingo Molnar
6 * Copyright (C) 2008-2011, Red Hat, Inc., Peter Zijlstra
7 *
8 * Data type definitions, declarations, prototypes.
9 *
10 * Started by: Thomas Gleixner and Ingo Molnar
11 *
12 * For licencing details see kernel-base/COPYING
13 */
14#ifndef _UAPI_LINUX_PERF_EVENT_H
15#define _UAPI_LINUX_PERF_EVENT_H
16
17#include <linux/types.h>
18#include <linux/ioctl.h>
19#include <asm/byteorder.h>
20
21/*
22 * User-space ABI bits:
23 */
24
25/*
26 * attr.type
27 */
28enum perf_type_id {
29 PERF_TYPE_HARDWARE = 0,
30 PERF_TYPE_SOFTWARE = 1,
31 PERF_TYPE_TRACEPOINT = 2,
32 PERF_TYPE_HW_CACHE = 3,
33 PERF_TYPE_RAW = 4,
34 PERF_TYPE_BREAKPOINT = 5,
35
36 PERF_TYPE_MAX, /* non-ABI */
37};
38
39/*
40 * Generalized performance event event_id types, used by the
41 * attr.event_id parameter of the sys_perf_event_open()
42 * syscall:
43 */
44enum perf_hw_id {
45 /*
46 * Common hardware events, generalized by the kernel:
47 */
48 PERF_COUNT_HW_CPU_CYCLES = 0,
49 PERF_COUNT_HW_INSTRUCTIONS = 1,
50 PERF_COUNT_HW_CACHE_REFERENCES = 2,
51 PERF_COUNT_HW_CACHE_MISSES = 3,
52 PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
53 PERF_COUNT_HW_BRANCH_MISSES = 5,
54 PERF_COUNT_HW_BUS_CYCLES = 6,
55 PERF_COUNT_HW_STALLED_CYCLES_FRONTEND = 7,
56 PERF_COUNT_HW_STALLED_CYCLES_BACKEND = 8,
57 PERF_COUNT_HW_REF_CPU_CYCLES = 9,
58
59 PERF_COUNT_HW_MAX, /* non-ABI */
60};
61
62/*
63 * Generalized hardware cache events:
64 *
65 * { L1-D, L1-I, LLC, ITLB, DTLB, BPU, NODE } x
66 * { read, write, prefetch } x
67 * { accesses, misses }
68 */
69enum perf_hw_cache_id {
70 PERF_COUNT_HW_CACHE_L1D = 0,
71 PERF_COUNT_HW_CACHE_L1I = 1,
72 PERF_COUNT_HW_CACHE_LL = 2,
73 PERF_COUNT_HW_CACHE_DTLB = 3,
74 PERF_COUNT_HW_CACHE_ITLB = 4,
75 PERF_COUNT_HW_CACHE_BPU = 5,
76 PERF_COUNT_HW_CACHE_NODE = 6,
77
78 PERF_COUNT_HW_CACHE_MAX, /* non-ABI */
79};
80
81enum perf_hw_cache_op_id {
82 PERF_COUNT_HW_CACHE_OP_READ = 0,
83 PERF_COUNT_HW_CACHE_OP_WRITE = 1,
84 PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
85
86 PERF_COUNT_HW_CACHE_OP_MAX, /* non-ABI */
87};
88
89enum perf_hw_cache_op_result_id {
90 PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
91 PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
92
93 PERF_COUNT_HW_CACHE_RESULT_MAX, /* non-ABI */
94};
95
96/*
97 * Special "software" events provided by the kernel, even if the hardware
98 * does not support performance events. These events measure various
99 * physical and sw events of the kernel (and allow the profiling of them as
100 * well):
101 */
102enum perf_sw_ids {
103 PERF_COUNT_SW_CPU_CLOCK = 0,
104 PERF_COUNT_SW_TASK_CLOCK = 1,
105 PERF_COUNT_SW_PAGE_FAULTS = 2,
106 PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
107 PERF_COUNT_SW_CPU_MIGRATIONS = 4,
108 PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
109 PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
110 PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
111 PERF_COUNT_SW_EMULATION_FAULTS = 8,
112 PERF_COUNT_SW_DUMMY = 9,
113 PERF_COUNT_SW_BPF_OUTPUT = 10,
114
115 PERF_COUNT_SW_MAX, /* non-ABI */
116};
117
118/*
119 * Bits that can be set in attr.sample_type to request information
120 * in the overflow packets.
121 */
122enum perf_event_sample_format {
123 PERF_SAMPLE_IP = 1U << 0,
124 PERF_SAMPLE_TID = 1U << 1,
125 PERF_SAMPLE_TIME = 1U << 2,
126 PERF_SAMPLE_ADDR = 1U << 3,
127 PERF_SAMPLE_READ = 1U << 4,
128 PERF_SAMPLE_CALLCHAIN = 1U << 5,
129 PERF_SAMPLE_ID = 1U << 6,
130 PERF_SAMPLE_CPU = 1U << 7,
131 PERF_SAMPLE_PERIOD = 1U << 8,
132 PERF_SAMPLE_STREAM_ID = 1U << 9,
133 PERF_SAMPLE_RAW = 1U << 10,
134 PERF_SAMPLE_BRANCH_STACK = 1U << 11,
135 PERF_SAMPLE_REGS_USER = 1U << 12,
136 PERF_SAMPLE_STACK_USER = 1U << 13,
137 PERF_SAMPLE_WEIGHT = 1U << 14,
138 PERF_SAMPLE_DATA_SRC = 1U << 15,
139 PERF_SAMPLE_IDENTIFIER = 1U << 16,
140 PERF_SAMPLE_TRANSACTION = 1U << 17,
141 PERF_SAMPLE_REGS_INTR = 1U << 18,
142
143 PERF_SAMPLE_MAX = 1U << 19, /* non-ABI */
144};
145
146/*
147 * values to program into branch_sample_type when PERF_SAMPLE_BRANCH is set
148 *
149 * If the user does not pass priv level information via branch_sample_type,
150 * the kernel uses the event's priv level. Branch and event priv levels do
151 * not have to match. Branch priv level is checked for permissions.
152 *
153 * The branch types can be combined, however BRANCH_ANY covers all types
154 * of branches and therefore it supersedes all the other types.
155 */
156enum perf_branch_sample_type_shift {
157 PERF_SAMPLE_BRANCH_USER_SHIFT = 0, /* user branches */
158 PERF_SAMPLE_BRANCH_KERNEL_SHIFT = 1, /* kernel branches */
159 PERF_SAMPLE_BRANCH_HV_SHIFT = 2, /* hypervisor branches */
160
161 PERF_SAMPLE_BRANCH_ANY_SHIFT = 3, /* any branch types */
162 PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT = 4, /* any call branch */
163 PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT = 5, /* any return branch */
164 PERF_SAMPLE_BRANCH_IND_CALL_SHIFT = 6, /* indirect calls */
165 PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT = 7, /* transaction aborts */
166 PERF_SAMPLE_BRANCH_IN_TX_SHIFT = 8, /* in transaction */
167 PERF_SAMPLE_BRANCH_NO_TX_SHIFT = 9, /* not in transaction */
168 PERF_SAMPLE_BRANCH_COND_SHIFT = 10, /* conditional branches */
169
170 PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT = 11, /* call/ret stack */
171 PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT = 12, /* indirect jumps */
172 PERF_SAMPLE_BRANCH_CALL_SHIFT = 13, /* direct call */
173
174 PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
175 PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
176
177 PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
178};
179
180enum perf_branch_sample_type {
181 PERF_SAMPLE_BRANCH_USER = 1U << PERF_SAMPLE_BRANCH_USER_SHIFT,
182 PERF_SAMPLE_BRANCH_KERNEL = 1U << PERF_SAMPLE_BRANCH_KERNEL_SHIFT,
183 PERF_SAMPLE_BRANCH_HV = 1U << PERF_SAMPLE_BRANCH_HV_SHIFT,
184
185 PERF_SAMPLE_BRANCH_ANY = 1U << PERF_SAMPLE_BRANCH_ANY_SHIFT,
186 PERF_SAMPLE_BRANCH_ANY_CALL = 1U << PERF_SAMPLE_BRANCH_ANY_CALL_SHIFT,
187 PERF_SAMPLE_BRANCH_ANY_RETURN = 1U << PERF_SAMPLE_BRANCH_ANY_RETURN_SHIFT,
188 PERF_SAMPLE_BRANCH_IND_CALL = 1U << PERF_SAMPLE_BRANCH_IND_CALL_SHIFT,
189 PERF_SAMPLE_BRANCH_ABORT_TX = 1U << PERF_SAMPLE_BRANCH_ABORT_TX_SHIFT,
190 PERF_SAMPLE_BRANCH_IN_TX = 1U << PERF_SAMPLE_BRANCH_IN_TX_SHIFT,
191 PERF_SAMPLE_BRANCH_NO_TX = 1U << PERF_SAMPLE_BRANCH_NO_TX_SHIFT,
192 PERF_SAMPLE_BRANCH_COND = 1U << PERF_SAMPLE_BRANCH_COND_SHIFT,
193
194 PERF_SAMPLE_BRANCH_CALL_STACK = 1U << PERF_SAMPLE_BRANCH_CALL_STACK_SHIFT,
195 PERF_SAMPLE_BRANCH_IND_JUMP = 1U << PERF_SAMPLE_BRANCH_IND_JUMP_SHIFT,
196 PERF_SAMPLE_BRANCH_CALL = 1U << PERF_SAMPLE_BRANCH_CALL_SHIFT,
197
198 PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
199 PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
200
201 PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
202};
203
204#define PERF_SAMPLE_BRANCH_PLM_ALL \
205 (PERF_SAMPLE_BRANCH_USER|\
206 PERF_SAMPLE_BRANCH_KERNEL|\
207 PERF_SAMPLE_BRANCH_HV)
208
209/*
210 * Values to determine ABI of the registers dump.
211 */
212enum perf_sample_regs_abi {
213 PERF_SAMPLE_REGS_ABI_NONE = 0,
214 PERF_SAMPLE_REGS_ABI_32 = 1,
215 PERF_SAMPLE_REGS_ABI_64 = 2,
216};
217
218/*
219 * Values for the memory transaction event qualifier, mostly for
220 * abort events. Multiple bits can be set.
221 */
222enum {
223 PERF_TXN_ELISION = (1 << 0), /* From elision */
224 PERF_TXN_TRANSACTION = (1 << 1), /* From transaction */
225 PERF_TXN_SYNC = (1 << 2), /* Instruction is related */
226 PERF_TXN_ASYNC = (1 << 3), /* Instruction not related */
227 PERF_TXN_RETRY = (1 << 4), /* Retry possible */
228 PERF_TXN_CONFLICT = (1 << 5), /* Conflict abort */
229 PERF_TXN_CAPACITY_WRITE = (1 << 6), /* Capacity write abort */
230 PERF_TXN_CAPACITY_READ = (1 << 7), /* Capacity read abort */
231
232 PERF_TXN_MAX = (1 << 8), /* non-ABI */
233
234 /* bits 32..63 are reserved for the abort code */
235
236 PERF_TXN_ABORT_MASK = (0xffffffffULL << 32),
237 PERF_TXN_ABORT_SHIFT = 32,
238};
239
240/*
241 * The format of the data returned by read() on a perf event fd,
242 * as specified by attr.read_format:
243 *
244 * struct read_format {
245 * { u64 value;
246 * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
247 * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
248 * { u64 id; } && PERF_FORMAT_ID
249 * } && !PERF_FORMAT_GROUP
250 *
251 * { u64 nr;
252 * { u64 time_enabled; } && PERF_FORMAT_TOTAL_TIME_ENABLED
253 * { u64 time_running; } && PERF_FORMAT_TOTAL_TIME_RUNNING
254 * { u64 value;
255 * { u64 id; } && PERF_FORMAT_ID
256 * } cntr[nr];
257 * } && PERF_FORMAT_GROUP
258 * };
259 */
260enum perf_event_read_format {
261 PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0,
262 PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
263 PERF_FORMAT_ID = 1U << 2,
264 PERF_FORMAT_GROUP = 1U << 3,
265
266 PERF_FORMAT_MAX = 1U << 4, /* non-ABI */
267};
268
269#define PERF_ATTR_SIZE_VER0 64 /* sizeof first published struct */
270#define PERF_ATTR_SIZE_VER1 72 /* add: config2 */
271#define PERF_ATTR_SIZE_VER2 80 /* add: branch_sample_type */
272#define PERF_ATTR_SIZE_VER3 96 /* add: sample_regs_user */
273 /* add: sample_stack_user */
274#define PERF_ATTR_SIZE_VER4 104 /* add: sample_regs_intr */
275#define PERF_ATTR_SIZE_VER5 112 /* add: aux_watermark */
276
277/*
278 * Hardware event_id to monitor via a performance monitoring event:
279 *
280 * @sample_max_stack: Max number of frame pointers in a callchain,
281 * should be < /proc/sys/kernel/perf_event_max_stack
282 */
283struct perf_event_attr {
284
285 /*
286 * Major type: hardware/software/tracepoint/etc.
287 */
288 __u32 type;
289
290 /*
291 * Size of the attr structure, for fwd/bwd compat.
292 */
293 __u32 size;
294
295 /*
296 * Type specific configuration information.
297 */
298 __u64 config;
299
300 union {
301 __u64 sample_period;
302 __u64 sample_freq;
303 };
304
305 __u64 sample_type;
306 __u64 read_format;
307
308 __u64 disabled : 1, /* off by default */
309 inherit : 1, /* children inherit it */
310 pinned : 1, /* must always be on PMU */
311 exclusive : 1, /* only group on PMU */
312 exclude_user : 1, /* don't count user */
313 exclude_kernel : 1, /* ditto kernel */
314 exclude_hv : 1, /* ditto hypervisor */
315 exclude_idle : 1, /* don't count when idle */
316 mmap : 1, /* include mmap data */
317 comm : 1, /* include comm data */
318 freq : 1, /* use freq, not period */
319 inherit_stat : 1, /* per task counts */
320 enable_on_exec : 1, /* next exec enables */
321 task : 1, /* trace fork/exit */
322 watermark : 1, /* wakeup_watermark */
323 /*
324 * precise_ip:
325 *
326 * 0 - SAMPLE_IP can have arbitrary skid
327 * 1 - SAMPLE_IP must have constant skid
328 * 2 - SAMPLE_IP requested to have 0 skid
329 * 3 - SAMPLE_IP must have 0 skid
330 *
331 * See also PERF_RECORD_MISC_EXACT_IP
332 */
333 precise_ip : 2, /* skid constraint */
334 mmap_data : 1, /* non-exec mmap data */
335 sample_id_all : 1, /* sample_type all events */
336
337 exclude_host : 1, /* don't count in host */
338 exclude_guest : 1, /* don't count in guest */
339
340 exclude_callchain_kernel : 1, /* exclude kernel callchains */
341 exclude_callchain_user : 1, /* exclude user callchains */
342 mmap2 : 1, /* include mmap with inode data */
343 comm_exec : 1, /* flag comm events that are due to an exec */
344 use_clockid : 1, /* use @clockid for time fields */
345 context_switch : 1, /* context switch data */
346 write_backward : 1, /* Write ring buffer from end to beginning */
347 __reserved_1 : 36;
348
349 union {
350 __u32 wakeup_events; /* wakeup every n events */
351 __u32 wakeup_watermark; /* bytes before wakeup */
352 };
353
354 __u32 bp_type;
355 union {
356 __u64 bp_addr;
357 __u64 config1; /* extension of config */
358 };
359 union {
360 __u64 bp_len;
361 __u64 config2; /* extension of config1 */
362 };
363 __u64 branch_sample_type; /* enum perf_branch_sample_type */
364
365 /*
366 * Defines set of user regs to dump on samples.
367 * See asm/perf_regs.h for details.
368 */
369 __u64 sample_regs_user;
370
371 /*
372 * Defines size of the user stack to dump on samples.
373 */
374 __u32 sample_stack_user;
375
376 __s32 clockid;
377 /*
378 * Defines set of regs to dump for each sample
379 * state captured on:
380 * - precise = 0: PMU interrupt
381 * - precise > 0: sampled instruction
382 *
383 * See asm/perf_regs.h for details.
384 */
385 __u64 sample_regs_intr;
386
387 /*
388 * Wakeup watermark for AUX area
389 */
390 __u32 aux_watermark;
391 __u16 sample_max_stack;
392 __u16 __reserved_2; /* align to __u64 */
393};
394
395#define perf_flags(attr) (*(&(attr)->read_format + 1))
396
397/*
398 * Ioctls that can be done on a perf event fd:
399 */
400#define PERF_EVENT_IOC_ENABLE _IO ('$', 0)
401#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
402#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
403#define PERF_EVENT_IOC_RESET _IO ('$', 3)
404#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64)
405#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
406#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
407#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)
408#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)
409#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32)
410
411enum perf_event_ioc_flags {
412 PERF_IOC_FLAG_GROUP = 1U << 0,
413};
414
415/*
416 * Structure of the page that can be mapped via mmap
417 */
418struct perf_event_mmap_page {
419 __u32 version; /* version number of this structure */
420 __u32 compat_version; /* lowest version this is compat with */
421
422 /*
423 * Bits needed to read the hw events in user-space.
424 *
425 * u32 seq, time_mult, time_shift, index, width;
426 * u64 count, enabled, running;
427 * u64 cyc, time_offset;
428 * s64 pmc = 0;
429 *
430 * do {
431 * seq = pc->lock;
432 * barrier()
433 *
434 * enabled = pc->time_enabled;
435 * running = pc->time_running;
436 *
437 * if (pc->cap_usr_time && enabled != running) {
438 * cyc = rdtsc();
439 * time_offset = pc->time_offset;
440 * time_mult = pc->time_mult;
441 * time_shift = pc->time_shift;
442 * }
443 *
444 * index = pc->index;
445 * count = pc->offset;
446 * if (pc->cap_user_rdpmc && index) {
447 * width = pc->pmc_width;
448 * pmc = rdpmc(index - 1);
449 * }
450 *
451 * barrier();
452 * } while (pc->lock != seq);
453 *
454 * NOTE: for obvious reason this only works on self-monitoring
455 * processes.
456 */
457 __u32 lock; /* seqlock for synchronization */
458 __u32 index; /* hardware event identifier */
459 __s64 offset; /* add to hardware event value */
460 __u64 time_enabled; /* time event active */
461 __u64 time_running; /* time event on cpu */
462 union {
463 __u64 capabilities;
464 struct {
465 __u64 cap_bit0 : 1, /* Always 0, deprecated, see commit 860f085b74e9 */
466 cap_bit0_is_deprecated : 1, /* Always 1, signals that bit 0 is zero */
467
468 cap_user_rdpmc : 1, /* The RDPMC instruction can be used to read counts */
469 cap_user_time : 1, /* The time_* fields are used */
470 cap_user_time_zero : 1, /* The time_zero field is used */
471 cap_____res : 59;
472 };
473 };
474
475 /*
476 * If cap_user_rdpmc this field provides the bit-width of the value
477 * read using the rdpmc() or equivalent instruction. This can be used
478 * to sign extend the result like:
479 *
480 * pmc <<= 64 - width;
481 * pmc >>= 64 - width; // signed shift right
482 * count += pmc;
483 */
484 __u16 pmc_width;
485
486 /*
487 * If cap_usr_time the below fields can be used to compute the time
488 * delta since time_enabled (in ns) using rdtsc or similar.
489 *
490 * u64 quot, rem;
491 * u64 delta;
492 *
493 * quot = (cyc >> time_shift);
494 * rem = cyc & (((u64)1 << time_shift) - 1);
495 * delta = time_offset + quot * time_mult +
496 * ((rem * time_mult) >> time_shift);
497 *
498 * Where time_offset,time_mult,time_shift and cyc are read in the
499 * seqcount loop described above. This delta can then be added to
500 * enabled and possible running (if index), improving the scaling:
501 *
502 * enabled += delta;
503 * if (index)
504 * running += delta;
505 *
506 * quot = count / running;
507 * rem = count % running;
508 * count = quot * enabled + (rem * enabled) / running;
509 */
510 __u16 time_shift;
511 __u32 time_mult;
512 __u64 time_offset;
513 /*
514 * If cap_usr_time_zero, the hardware clock (e.g. TSC) can be calculated
515 * from sample timestamps.
516 *
517 * time = timestamp - time_zero;
518 * quot = time / time_mult;
519 * rem = time % time_mult;
520 * cyc = (quot << time_shift) + (rem << time_shift) / time_mult;
521 *
522 * And vice versa:
523 *
524 * quot = cyc >> time_shift;
525 * rem = cyc & (((u64)1 << time_shift) - 1);
526 * timestamp = time_zero + quot * time_mult +
527 * ((rem * time_mult) >> time_shift);
528 */
529 __u64 time_zero;
530 __u32 size; /* Header size up to __reserved[] fields. */
531
532 /*
533 * Hole for extension of the self monitor capabilities
534 */
535
536 __u8 __reserved[118*8+4]; /* align to 1k. */
537
538 /*
539 * Control data for the mmap() data buffer.
540 *
541 * User-space reading the @data_head value should issue an smp_rmb(),
542 * after reading this value.
543 *
544 * When the mapping is PROT_WRITE the @data_tail value should be
545 * written by userspace to reflect the last read data, after issueing
546 * an smp_mb() to separate the data read from the ->data_tail store.
547 * In this case the kernel will not over-write unread data.
548 *
549 * See perf_output_put_handle() for the data ordering.
550 *
551 * data_{offset,size} indicate the location and size of the perf record
552 * buffer within the mmapped area.
553 */
554 __u64 data_head; /* head in the data section */
555 __u64 data_tail; /* user-space written tail */
556 __u64 data_offset; /* where the buffer starts */
557 __u64 data_size; /* data buffer size */
558
559 /*
560 * AUX area is defined by aux_{offset,size} fields that should be set
561 * by the userspace, so that
562 *
563 * aux_offset >= data_offset + data_size
564 *
565 * prior to mmap()ing it. Size of the mmap()ed area should be aux_size.
566 *
567 * Ring buffer pointers aux_{head,tail} have the same semantics as
568 * data_{head,tail} and same ordering rules apply.
569 */
570 __u64 aux_head;
571 __u64 aux_tail;
572 __u64 aux_offset;
573 __u64 aux_size;
574};
575
576#define PERF_RECORD_MISC_CPUMODE_MASK (7 << 0)
577#define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0)
578#define PERF_RECORD_MISC_KERNEL (1 << 0)
579#define PERF_RECORD_MISC_USER (2 << 0)
580#define PERF_RECORD_MISC_HYPERVISOR (3 << 0)
581#define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0)
582#define PERF_RECORD_MISC_GUEST_USER (5 << 0)
583
584/*
585 * Indicates that /proc/PID/maps parsing are truncated by time out.
586 */
587#define PERF_RECORD_MISC_PROC_MAP_PARSE_TIMEOUT (1 << 12)
588/*
589 * PERF_RECORD_MISC_MMAP_DATA and PERF_RECORD_MISC_COMM_EXEC are used on
590 * different events so can reuse the same bit position.
591 * Ditto PERF_RECORD_MISC_SWITCH_OUT.
592 */
593#define PERF_RECORD_MISC_MMAP_DATA (1 << 13)
594#define PERF_RECORD_MISC_COMM_EXEC (1 << 13)
595#define PERF_RECORD_MISC_SWITCH_OUT (1 << 13)
596/*
597 * Indicates that the content of PERF_SAMPLE_IP points to
598 * the actual instruction that triggered the event. See also
599 * perf_event_attr::precise_ip.
600 */
601#define PERF_RECORD_MISC_EXACT_IP (1 << 14)
602/*
603 * Reserve the last bit to indicate some extended misc field
604 */
605#define PERF_RECORD_MISC_EXT_RESERVED (1 << 15)
606
607struct perf_event_header {
608 __u32 type;
609 __u16 misc;
610 __u16 size;
611};
612
613enum perf_event_type {
614
615 /*
616 * If perf_event_attr.sample_id_all is set then all event types will
617 * have the sample_type selected fields related to where/when
618 * (identity) an event took place (TID, TIME, ID, STREAM_ID, CPU,
619 * IDENTIFIER) described in PERF_RECORD_SAMPLE below, it will be stashed
620 * just after the perf_event_header and the fields already present for
621 * the existing fields, i.e. at the end of the payload. That way a newer
622 * perf.data file will be supported by older perf tools, with these new
623 * optional fields being ignored.
624 *
625 * struct sample_id {
626 * { u32 pid, tid; } && PERF_SAMPLE_TID
627 * { u64 time; } && PERF_SAMPLE_TIME
628 * { u64 id; } && PERF_SAMPLE_ID
629 * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
630 * { u32 cpu, res; } && PERF_SAMPLE_CPU
631 * { u64 id; } && PERF_SAMPLE_IDENTIFIER
632 * } && perf_event_attr::sample_id_all
633 *
634 * Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID. The
635 * advantage of PERF_SAMPLE_IDENTIFIER is that its position is fixed
636 * relative to header.size.
637 */
638
639 /*
640 * The MMAP events record the PROT_EXEC mappings so that we can
641 * correlate userspace IPs to code. They have the following structure:
642 *
643 * struct {
644 * struct perf_event_header header;
645 *
646 * u32 pid, tid;
647 * u64 addr;
648 * u64 len;
649 * u64 pgoff;
650 * char filename[];
651 * struct sample_id sample_id;
652 * };
653 */
654 PERF_RECORD_MMAP = 1,
655
656 /*
657 * struct {
658 * struct perf_event_header header;
659 * u64 id;
660 * u64 lost;
661 * struct sample_id sample_id;
662 * };
663 */
664 PERF_RECORD_LOST = 2,
665
666 /*
667 * struct {
668 * struct perf_event_header header;
669 *
670 * u32 pid, tid;
671 * char comm[];
672 * struct sample_id sample_id;
673 * };
674 */
675 PERF_RECORD_COMM = 3,
676
677 /*
678 * struct {
679 * struct perf_event_header header;
680 * u32 pid, ppid;
681 * u32 tid, ptid;
682 * u64 time;
683 * struct sample_id sample_id;
684 * };
685 */
686 PERF_RECORD_EXIT = 4,
687
688 /*
689 * struct {
690 * struct perf_event_header header;
691 * u64 time;
692 * u64 id;
693 * u64 stream_id;
694 * struct sample_id sample_id;
695 * };
696 */
697 PERF_RECORD_THROTTLE = 5,
698 PERF_RECORD_UNTHROTTLE = 6,
699
700 /*
701 * struct {
702 * struct perf_event_header header;
703 * u32 pid, ppid;
704 * u32 tid, ptid;
705 * u64 time;
706 * struct sample_id sample_id;
707 * };
708 */
709 PERF_RECORD_FORK = 7,
710
711 /*
712 * struct {
713 * struct perf_event_header header;
714 * u32 pid, tid;
715 *
716 * struct read_format values;
717 * struct sample_id sample_id;
718 * };
719 */
720 PERF_RECORD_READ = 8,
721
722 /*
723 * struct {
724 * struct perf_event_header header;
725 *
726 * #
727 * # Note that PERF_SAMPLE_IDENTIFIER duplicates PERF_SAMPLE_ID.
728 * # The advantage of PERF_SAMPLE_IDENTIFIER is that its position
729 * # is fixed relative to header.
730 * #
731 *
732 * { u64 id; } && PERF_SAMPLE_IDENTIFIER
733 * { u64 ip; } && PERF_SAMPLE_IP
734 * { u32 pid, tid; } && PERF_SAMPLE_TID
735 * { u64 time; } && PERF_SAMPLE_TIME
736 * { u64 addr; } && PERF_SAMPLE_ADDR
737 * { u64 id; } && PERF_SAMPLE_ID
738 * { u64 stream_id;} && PERF_SAMPLE_STREAM_ID
739 * { u32 cpu, res; } && PERF_SAMPLE_CPU
740 * { u64 period; } && PERF_SAMPLE_PERIOD
741 *
742 * { struct read_format values; } && PERF_SAMPLE_READ
743 *
744 * { u64 nr,
745 * u64 ips[nr]; } && PERF_SAMPLE_CALLCHAIN
746 *
747 * #
748 * # The RAW record below is opaque data wrt the ABI
749 * #
750 * # That is, the ABI doesn't make any promises wrt to
751 * # the stability of its content, it may vary depending
752 * # on event, hardware, kernel version and phase of
753 * # the moon.
754 * #
755 * # In other words, PERF_SAMPLE_RAW contents are not an ABI.
756 * #
757 *
758 * { u32 size;
759 * char data[size];}&& PERF_SAMPLE_RAW
760 *
761 * { u64 nr;
762 * { u64 from, to, flags } lbr[nr];} && PERF_SAMPLE_BRANCH_STACK
763 *
764 * { u64 abi; # enum perf_sample_regs_abi
765 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_USER
766 *
767 * { u64 size;
768 * char data[size];
769 * u64 dyn_size; } && PERF_SAMPLE_STACK_USER
770 *
771 * { u64 weight; } && PERF_SAMPLE_WEIGHT
772 * { u64 data_src; } && PERF_SAMPLE_DATA_SRC
773 * { u64 transaction; } && PERF_SAMPLE_TRANSACTION
774 * { u64 abi; # enum perf_sample_regs_abi
775 * u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
776 * };
777 */
778 PERF_RECORD_SAMPLE = 9,
779
780 /*
781 * The MMAP2 records are an augmented version of MMAP, they add
782 * maj, min, ino numbers to be used to uniquely identify each mapping
783 *
784 * struct {
785 * struct perf_event_header header;
786 *
787 * u32 pid, tid;
788 * u64 addr;
789 * u64 len;
790 * u64 pgoff;
791 * u32 maj;
792 * u32 min;
793 * u64 ino;
794 * u64 ino_generation;
795 * u32 prot, flags;
796 * char filename[];
797 * struct sample_id sample_id;
798 * };
799 */
800 PERF_RECORD_MMAP2 = 10,
801
802 /*
803 * Records that new data landed in the AUX buffer part.
804 *
805 * struct {
806 * struct perf_event_header header;
807 *
808 * u64 aux_offset;
809 * u64 aux_size;
810 * u64 flags;
811 * struct sample_id sample_id;
812 * };
813 */
814 PERF_RECORD_AUX = 11,
815
816 /*
817 * Indicates that instruction trace has started
818 *
819 * struct {
820 * struct perf_event_header header;
821 * u32 pid;
822 * u32 tid;
823 * };
824 */
825 PERF_RECORD_ITRACE_START = 12,
826
827 /*
828 * Records the dropped/lost sample number.
829 *
830 * struct {
831 * struct perf_event_header header;
832 *
833 * u64 lost;
834 * struct sample_id sample_id;
835 * };
836 */
837 PERF_RECORD_LOST_SAMPLES = 13,
838
839 /*
840 * Records a context switch in or out (flagged by
841 * PERF_RECORD_MISC_SWITCH_OUT). See also
842 * PERF_RECORD_SWITCH_CPU_WIDE.
843 *
844 * struct {
845 * struct perf_event_header header;
846 * struct sample_id sample_id;
847 * };
848 */
849 PERF_RECORD_SWITCH = 14,
850
851 /*
852 * CPU-wide version of PERF_RECORD_SWITCH with next_prev_pid and
853 * next_prev_tid that are the next (switching out) or previous
854 * (switching in) pid/tid.
855 *
856 * struct {
857 * struct perf_event_header header;
858 * u32 next_prev_pid;
859 * u32 next_prev_tid;
860 * struct sample_id sample_id;
861 * };
862 */
863 PERF_RECORD_SWITCH_CPU_WIDE = 15,
864
865 PERF_RECORD_MAX, /* non-ABI */
866};
867
868#define PERF_MAX_STACK_DEPTH 127
869#define PERF_MAX_CONTEXTS_PER_STACK 8
870
871enum perf_callchain_context {
872 PERF_CONTEXT_HV = (__u64)-32,
873 PERF_CONTEXT_KERNEL = (__u64)-128,
874 PERF_CONTEXT_USER = (__u64)-512,
875
876 PERF_CONTEXT_GUEST = (__u64)-2048,
877 PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176,
878 PERF_CONTEXT_GUEST_USER = (__u64)-2560,
879
880 PERF_CONTEXT_MAX = (__u64)-4095,
881};
882
883/**
884 * PERF_RECORD_AUX::flags bits
885 */
886#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */
887#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */
888
889#define PERF_FLAG_FD_NO_GROUP (1UL << 0)
890#define PERF_FLAG_FD_OUTPUT (1UL << 1)
891#define PERF_FLAG_PID_CGROUP (1UL << 2) /* pid=cgroup id, per-cpu mode only */
892#define PERF_FLAG_FD_CLOEXEC (1UL << 3) /* O_CLOEXEC */
893
894union perf_mem_data_src {
895 __u64 val;
896 struct {
897 __u64 mem_op:5, /* type of opcode */
898 mem_lvl:14, /* memory hierarchy level */
899 mem_snoop:5, /* snoop mode */
900 mem_lock:2, /* lock instr */
901 mem_dtlb:7, /* tlb access */
902 mem_rsvd:31;
903 };
904};
905
906/* type of opcode (load/store/prefetch,code) */
907#define PERF_MEM_OP_NA 0x01 /* not available */
908#define PERF_MEM_OP_LOAD 0x02 /* load instruction */
909#define PERF_MEM_OP_STORE 0x04 /* store instruction */
910#define PERF_MEM_OP_PFETCH 0x08 /* prefetch */
911#define PERF_MEM_OP_EXEC 0x10 /* code (execution) */
912#define PERF_MEM_OP_SHIFT 0
913
914/* memory hierarchy (memory level, hit or miss) */
915#define PERF_MEM_LVL_NA 0x01 /* not available */
916#define PERF_MEM_LVL_HIT 0x02 /* hit level */
917#define PERF_MEM_LVL_MISS 0x04 /* miss level */
918#define PERF_MEM_LVL_L1 0x08 /* L1 */
919#define PERF_MEM_LVL_LFB 0x10 /* Line Fill Buffer */
920#define PERF_MEM_LVL_L2 0x20 /* L2 */
921#define PERF_MEM_LVL_L3 0x40 /* L3 */
922#define PERF_MEM_LVL_LOC_RAM 0x80 /* Local DRAM */
923#define PERF_MEM_LVL_REM_RAM1 0x100 /* Remote DRAM (1 hop) */
924#define PERF_MEM_LVL_REM_RAM2 0x200 /* Remote DRAM (2 hops) */
925#define PERF_MEM_LVL_REM_CCE1 0x400 /* Remote Cache (1 hop) */
926#define PERF_MEM_LVL_REM_CCE2 0x800 /* Remote Cache (2 hops) */
927#define PERF_MEM_LVL_IO 0x1000 /* I/O memory */
928#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */
929#define PERF_MEM_LVL_SHIFT 5
930
931/* snoop mode */
932#define PERF_MEM_SNOOP_NA 0x01 /* not available */
933#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */
934#define PERF_MEM_SNOOP_HIT 0x04 /* snoop hit */
935#define PERF_MEM_SNOOP_MISS 0x08 /* snoop miss */
936#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */
937#define PERF_MEM_SNOOP_SHIFT 19
938
939/* locked instruction */
940#define PERF_MEM_LOCK_NA 0x01 /* not available */
941#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */
942#define PERF_MEM_LOCK_SHIFT 24
943
944/* TLB access */
945#define PERF_MEM_TLB_NA 0x01 /* not available */
946#define PERF_MEM_TLB_HIT 0x02 /* hit level */
947#define PERF_MEM_TLB_MISS 0x04 /* miss level */
948#define PERF_MEM_TLB_L1 0x08 /* L1 */
949#define PERF_MEM_TLB_L2 0x10 /* L2 */
950#define PERF_MEM_TLB_WK 0x20 /* Hardware Walker*/
951#define PERF_MEM_TLB_OS 0x40 /* OS fault handler */
952#define PERF_MEM_TLB_SHIFT 26
953
954#define PERF_MEM_S(a, s) \
955 (((__u64)PERF_MEM_##a##_##s) << PERF_MEM_##a##_SHIFT)
956
957/*
958 * single taken branch record layout:
959 *
960 * from: source instruction (may not always be a branch insn)
961 * to: branch target
962 * mispred: branch target was mispredicted
963 * predicted: branch target was predicted
964 *
965 * support for mispred, predicted is optional. In case it
966 * is not supported mispred = predicted = 0.
967 *
968 * in_tx: running in a hardware transaction
969 * abort: aborting a hardware transaction
970 * cycles: cycles from last branch (or 0 if not supported)
971 */
972struct perf_branch_entry {
973 __u64 from;
974 __u64 to;
975 __u64 mispred:1, /* target mispredicted */
976 predicted:1,/* target predicted */
977 in_tx:1, /* in transaction */
978 abort:1, /* transaction abort */
979 cycles:16, /* cycle count to last branch */
980 reserved:44;
981};
982
983#endif /* _UAPI_LINUX_PERF_EVENT_H */
diff --git a/tools/laptop/dslm/.gitignore b/tools/laptop/dslm/.gitignore
new file mode 100644
index 000000000000..9fc984e64386
--- /dev/null
+++ b/tools/laptop/dslm/.gitignore
@@ -0,0 +1 @@
dslm
diff --git a/tools/laptop/dslm/Makefile b/tools/laptop/dslm/Makefile
new file mode 100644
index 000000000000..ff613b31730b
--- /dev/null
+++ b/tools/laptop/dslm/Makefile
@@ -0,0 +1,9 @@
1CC := $(CROSS_COMPILE)gcc
2CFLAGS := -I../../usr/include
3
4PROGS := dslm
5
6all: $(PROGS)
7
8clean:
9 rm -fr $(PROGS)
diff --git a/tools/laptop/dslm/dslm.c b/tools/laptop/dslm/dslm.c
new file mode 100644
index 000000000000..d5dd2d4b04d8
--- /dev/null
+++ b/tools/laptop/dslm/dslm.c
@@ -0,0 +1,166 @@
1/*
2 * dslm.c
3 * Simple Disk Sleep Monitor
4 * by Bartek Kania
5 * Licensed under the GPL
6 */
7#include <unistd.h>
8#include <stdlib.h>
9#include <stdio.h>
10#include <fcntl.h>
11#include <errno.h>
12#include <time.h>
13#include <string.h>
14#include <signal.h>
15#include <sys/ioctl.h>
16#include <linux/hdreg.h>
17
18#ifdef DEBUG
19#define D(x) x
20#else
21#define D(x)
22#endif
23
24int endit = 0;
25
26/* Check if the disk is in powersave-mode
27 * Most of the code is stolen from hdparm.
28 * 1 = active, 0 = standby/sleep, -1 = unknown */
29static int check_powermode(int fd)
30{
31 unsigned char args[4] = {WIN_CHECKPOWERMODE1,0,0,0};
32 int state;
33
34 if (ioctl(fd, HDIO_DRIVE_CMD, &args)
35 && (args[0] = WIN_CHECKPOWERMODE2) /* try again with 0x98 */
36 && ioctl(fd, HDIO_DRIVE_CMD, &args)) {
37 if (errno != EIO || args[0] != 0 || args[1] != 0) {
38 state = -1; /* "unknown"; */
39 } else
40 state = 0; /* "sleeping"; */
41 } else {
42 state = (args[2] == 255) ? 1 : 0;
43 }
44 D(printf(" drive state is: %d\n", state));
45
46 return state;
47}
48
49static char *state_name(int i)
50{
51 if (i == -1) return "unknown";
52 if (i == 0) return "sleeping";
53 if (i == 1) return "active";
54
55 return "internal error";
56}
57
58static char *myctime(time_t time)
59{
60 char *ts = ctime(&time);
61 ts[strlen(ts) - 1] = 0;
62
63 return ts;
64}
65
66static void measure(int fd)
67{
68 time_t start_time;
69 int last_state;
70 time_t last_time;
71 int curr_state;
72 time_t curr_time = 0;
73 time_t time_diff;
74 time_t active_time = 0;
75 time_t sleep_time = 0;
76 time_t unknown_time = 0;
77 time_t total_time = 0;
78 int changes = 0;
79 float tmp;
80
81 printf("Starting measurements\n");
82
83 last_state = check_powermode(fd);
84 start_time = last_time = time(0);
85 printf(" System is in state %s\n\n", state_name(last_state));
86
87 while(!endit) {
88 sleep(1);
89 curr_state = check_powermode(fd);
90
91 if (curr_state != last_state || endit) {
92 changes++;
93 curr_time = time(0);
94 time_diff = curr_time - last_time;
95
96 if (last_state == 1) active_time += time_diff;
97 else if (last_state == 0) sleep_time += time_diff;
98 else unknown_time += time_diff;
99
100 last_state = curr_state;
101 last_time = curr_time;
102
103 printf("%s: State-change to %s\n", myctime(curr_time),
104 state_name(curr_state));
105 }
106 }
107 changes--; /* Compensate for SIGINT */
108
109 total_time = time(0) - start_time;
110 printf("\nTotal running time: %lus\n", curr_time - start_time);
111 printf(" State changed %d times\n", changes);
112
113 tmp = (float)sleep_time / (float)total_time * 100;
114 printf(" Time in sleep state: %lus (%.2f%%)\n", sleep_time, tmp);
115 tmp = (float)active_time / (float)total_time * 100;
116 printf(" Time in active state: %lus (%.2f%%)\n", active_time, tmp);
117 tmp = (float)unknown_time / (float)total_time * 100;
118 printf(" Time in unknown state: %lus (%.2f%%)\n", unknown_time, tmp);
119}
120
121static void ender(int s)
122{
123 endit = 1;
124}
125
126static void usage(void)
127{
128 puts("usage: dslm [-w <time>] <disk>");
129 exit(0);
130}
131
132int main(int argc, char **argv)
133{
134 int fd;
135 char *disk = 0;
136 int settle_time = 60;
137
138 /* Parse the simple command-line */
139 if (argc == 2)
140 disk = argv[1];
141 else if (argc == 4) {
142 settle_time = atoi(argv[2]);
143 disk = argv[3];
144 } else
145 usage();
146
147 if (!(fd = open(disk, O_RDONLY|O_NONBLOCK))) {
148 printf("Can't open %s, because: %s\n", disk, strerror(errno));
149 exit(-1);
150 }
151
152 if (settle_time) {
153 printf("Waiting %d seconds for the system to settle down to "
154 "'normal'\n", settle_time);
155 sleep(settle_time);
156 } else
157 puts("Not waiting for system to settle down");
158
159 signal(SIGINT, ender);
160
161 measure(fd);
162
163 close(fd);
164
165 return 0;
166}
diff --git a/tools/lguest/lguest.c b/tools/lguest/lguest.c
index d9836c5eb694..11c8d9bc762e 100644
--- a/tools/lguest/lguest.c
+++ b/tools/lguest/lguest.c
@@ -3266,6 +3266,9 @@ int main(int argc, char *argv[])
3266 } 3266 }
3267 } 3267 }
3268 3268
3269 /* If we exit via err(), this kills all the threads, restores tty. */
3270 atexit(cleanup_devices);
3271
3269 /* We always have a console device, and it's always device 1. */ 3272 /* We always have a console device, and it's always device 1. */
3270 setup_console(); 3273 setup_console();
3271 3274
@@ -3369,9 +3372,6 @@ int main(int argc, char *argv[])
3369 /* Ensure that we terminate if a device-servicing child dies. */ 3372 /* Ensure that we terminate if a device-servicing child dies. */
3370 signal(SIGCHLD, kill_launcher); 3373 signal(SIGCHLD, kill_launcher);
3371 3374
3372 /* If we exit via err(), this kills all the threads, restores tty. */
3373 atexit(cleanup_devices);
3374
3375 /* If requested, chroot to a directory */ 3375 /* If requested, chroot to a directory */
3376 if (chroot_path) { 3376 if (chroot_path) {
3377 if (chroot(chroot_path) != 0) 3377 if (chroot(chroot_path) != 0)
diff --git a/tools/lib/api/Build b/tools/lib/api/Build
index 954c644f7ad9..6e2373db5598 100644
--- a/tools/lib/api/Build
+++ b/tools/lib/api/Build
@@ -2,3 +2,8 @@ libapi-y += fd/
2libapi-y += fs/ 2libapi-y += fs/
3libapi-y += cpu.o 3libapi-y += cpu.o
4libapi-y += debug.o 4libapi-y += debug.o
5libapi-y += str_error_r.o
6
7$(OUTPUT)str_error_r.o: ../str_error_r.c FORCE
8 $(call rule_mkdir)
9 $(call if_changed_dep,cc_o_c)
diff --git a/tools/lib/api/Makefile b/tools/lib/api/Makefile
index 316f308a63ea..0a6fda9837f7 100644
--- a/tools/lib/api/Makefile
+++ b/tools/lib/api/Makefile
@@ -10,15 +10,23 @@ endif
10 10
11CC = $(CROSS_COMPILE)gcc 11CC = $(CROSS_COMPILE)gcc
12AR = $(CROSS_COMPILE)ar 12AR = $(CROSS_COMPILE)ar
13LD = $(CROSS_COMPILE)ld
13 14
14MAKEFLAGS += --no-print-directory 15MAKEFLAGS += --no-print-directory
15 16
16LIBFILE = $(OUTPUT)libapi.a 17LIBFILE = $(OUTPUT)libapi.a
17 18
18CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 19CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
19CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 20CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
21
22# Treat warnings as errors unless directed not to
23ifneq ($(WERROR),0)
24 CFLAGS += -Werror
25endif
26
20CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 27CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64
21CFLAGS += -I$(srctree)/tools/lib/api 28CFLAGS += -I$(srctree)/tools/lib/api
29CFLAGS += -I$(srctree)/tools/include
22 30
23RM = rm -f 31RM = rm -f
24 32
diff --git a/tools/lib/api/fd/array.c b/tools/lib/api/fd/array.c
index 0e636c4339b8..b0a035fc87b3 100644
--- a/tools/lib/api/fd/array.c
+++ b/tools/lib/api/fd/array.c
@@ -85,7 +85,8 @@ int fdarray__add(struct fdarray *fda, int fd, short revents)
85} 85}
86 86
87int fdarray__filter(struct fdarray *fda, short revents, 87int fdarray__filter(struct fdarray *fda, short revents,
88 void (*entry_destructor)(struct fdarray *fda, int fd)) 88 void (*entry_destructor)(struct fdarray *fda, int fd, void *arg),
89 void *arg)
89{ 90{
90 int fd, nr = 0; 91 int fd, nr = 0;
91 92
@@ -95,7 +96,7 @@ int fdarray__filter(struct fdarray *fda, short revents,
95 for (fd = 0; fd < fda->nr; ++fd) { 96 for (fd = 0; fd < fda->nr; ++fd) {
96 if (fda->entries[fd].revents & revents) { 97 if (fda->entries[fd].revents & revents) {
97 if (entry_destructor) 98 if (entry_destructor)
98 entry_destructor(fda, fd); 99 entry_destructor(fda, fd, arg);
99 100
100 continue; 101 continue;
101 } 102 }
diff --git a/tools/lib/api/fd/array.h b/tools/lib/api/fd/array.h
index 45db01818f45..71287dddc05f 100644
--- a/tools/lib/api/fd/array.h
+++ b/tools/lib/api/fd/array.h
@@ -22,6 +22,7 @@ struct fdarray {
22 struct pollfd *entries; 22 struct pollfd *entries;
23 union { 23 union {
24 int idx; 24 int idx;
25 void *ptr;
25 } *priv; 26 } *priv;
26}; 27};
27 28
@@ -34,7 +35,8 @@ void fdarray__delete(struct fdarray *fda);
34int fdarray__add(struct fdarray *fda, int fd, short revents); 35int fdarray__add(struct fdarray *fda, int fd, short revents);
35int fdarray__poll(struct fdarray *fda, int timeout); 36int fdarray__poll(struct fdarray *fda, int timeout);
36int fdarray__filter(struct fdarray *fda, short revents, 37int fdarray__filter(struct fdarray *fda, short revents,
37 void (*entry_destructor)(struct fdarray *fda, int fd)); 38 void (*entry_destructor)(struct fdarray *fda, int fd, void *arg),
39 void *arg);
38int fdarray__grow(struct fdarray *fda, int extra); 40int fdarray__grow(struct fdarray *fda, int extra);
39int fdarray__fprintf(struct fdarray *fda, FILE *fp); 41int fdarray__fprintf(struct fdarray *fda, FILE *fp);
40 42
diff --git a/tools/lib/api/fs/fs.c b/tools/lib/api/fs/fs.c
index 08556cf2c70d..f99f49e4a31e 100644
--- a/tools/lib/api/fs/fs.c
+++ b/tools/lib/api/fs/fs.c
@@ -34,6 +34,10 @@
34#define TRACEFS_MAGIC 0x74726163 34#define TRACEFS_MAGIC 0x74726163
35#endif 35#endif
36 36
37#ifndef HUGETLBFS_MAGIC
38#define HUGETLBFS_MAGIC 0x958458f6
39#endif
40
37static const char * const sysfs__fs_known_mountpoints[] = { 41static const char * const sysfs__fs_known_mountpoints[] = {
38 "/sys", 42 "/sys",
39 0, 43 0,
@@ -67,6 +71,10 @@ static const char * const tracefs__known_mountpoints[] = {
67 0, 71 0,
68}; 72};
69 73
74static const char * const hugetlbfs__known_mountpoints[] = {
75 0,
76};
77
70struct fs { 78struct fs {
71 const char *name; 79 const char *name;
72 const char * const *mounts; 80 const char * const *mounts;
@@ -80,6 +88,7 @@ enum {
80 FS__PROCFS = 1, 88 FS__PROCFS = 1,
81 FS__DEBUGFS = 2, 89 FS__DEBUGFS = 2,
82 FS__TRACEFS = 3, 90 FS__TRACEFS = 3,
91 FS__HUGETLBFS = 4,
83}; 92};
84 93
85#ifndef TRACEFS_MAGIC 94#ifndef TRACEFS_MAGIC
@@ -107,6 +116,11 @@ static struct fs fs__entries[] = {
107 .mounts = tracefs__known_mountpoints, 116 .mounts = tracefs__known_mountpoints,
108 .magic = TRACEFS_MAGIC, 117 .magic = TRACEFS_MAGIC,
109 }, 118 },
119 [FS__HUGETLBFS] = {
120 .name = "hugetlbfs",
121 .mounts = hugetlbfs__known_mountpoints,
122 .magic = HUGETLBFS_MAGIC,
123 },
110}; 124};
111 125
112static bool fs__read_mounts(struct fs *fs) 126static bool fs__read_mounts(struct fs *fs)
@@ -265,6 +279,7 @@ FS(sysfs, FS__SYSFS);
265FS(procfs, FS__PROCFS); 279FS(procfs, FS__PROCFS);
266FS(debugfs, FS__DEBUGFS); 280FS(debugfs, FS__DEBUGFS);
267FS(tracefs, FS__TRACEFS); 281FS(tracefs, FS__TRACEFS);
282FS(hugetlbfs, FS__HUGETLBFS);
268 283
269int filename__read_int(const char *filename, int *value) 284int filename__read_int(const char *filename, int *value)
270{ 285{
@@ -283,6 +298,11 @@ int filename__read_int(const char *filename, int *value)
283 return err; 298 return err;
284} 299}
285 300
301/*
302 * Parses @value out of @filename with strtoull.
303 * By using 0 for base, the strtoull detects the
304 * base automatically (see man strtoull).
305 */
286int filename__read_ull(const char *filename, unsigned long long *value) 306int filename__read_ull(const char *filename, unsigned long long *value)
287{ 307{
288 char line[64]; 308 char line[64];
@@ -292,7 +312,7 @@ int filename__read_ull(const char *filename, unsigned long long *value)
292 return -1; 312 return -1;
293 313
294 if (read(fd, line, sizeof(line)) > 0) { 314 if (read(fd, line, sizeof(line)) > 0) {
295 *value = strtoull(line, NULL, 10); 315 *value = strtoull(line, NULL, 0);
296 if (*value != ULLONG_MAX) 316 if (*value != ULLONG_MAX)
297 err = 0; 317 err = 0;
298 } 318 }
diff --git a/tools/lib/api/fs/fs.h b/tools/lib/api/fs/fs.h
index 16c9c2ed7c5b..a63269f5d20c 100644
--- a/tools/lib/api/fs/fs.h
+++ b/tools/lib/api/fs/fs.h
@@ -21,6 +21,7 @@ FS(sysfs)
21FS(procfs) 21FS(procfs)
22FS(debugfs) 22FS(debugfs)
23FS(tracefs) 23FS(tracefs)
24FS(hugetlbfs)
24 25
25#undef FS 26#undef FS
26 27
diff --git a/tools/lib/api/fs/tracing_path.c b/tools/lib/api/fs/tracing_path.c
index a26bb5ea8283..251b7c342a87 100644
--- a/tools/lib/api/fs/tracing_path.c
+++ b/tools/lib/api/fs/tracing_path.c
@@ -5,6 +5,7 @@
5#include <stdio.h> 5#include <stdio.h>
6#include <stdlib.h> 6#include <stdlib.h>
7#include <string.h> 7#include <string.h>
8#include <linux/string.h>
8#include <errno.h> 9#include <errno.h>
9#include <unistd.h> 10#include <unistd.h>
10#include "fs.h" 11#include "fs.h"
@@ -118,7 +119,7 @@ static int strerror_open(int err, char *buf, size_t size, const char *filename)
118 } 119 }
119 break; 120 break;
120 default: 121 default:
121 snprintf(buf, size, "%s", strerror_r(err, sbuf, sizeof(sbuf))); 122 snprintf(buf, size, "%s", str_error_r(err, sbuf, sizeof(sbuf)));
122 break; 123 break;
123 } 124 }
124 125
diff --git a/tools/lib/bitmap.c b/tools/lib/bitmap.c
index 0a1adc1111fd..38748b0e342f 100644
--- a/tools/lib/bitmap.c
+++ b/tools/lib/bitmap.c
@@ -29,3 +29,47 @@ void __bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
29 for (k = 0; k < nr; k++) 29 for (k = 0; k < nr; k++)
30 dst[k] = bitmap1[k] | bitmap2[k]; 30 dst[k] = bitmap1[k] | bitmap2[k];
31} 31}
32
33size_t bitmap_scnprintf(unsigned long *bitmap, int nbits,
34 char *buf, size_t size)
35{
36 /* current bit is 'cur', most recently seen range is [rbot, rtop] */
37 int cur, rbot, rtop;
38 bool first = true;
39 size_t ret = 0;
40
41 rbot = cur = find_first_bit(bitmap, nbits);
42 while (cur < nbits) {
43 rtop = cur;
44 cur = find_next_bit(bitmap, nbits, cur + 1);
45 if (cur < nbits && cur <= rtop + 1)
46 continue;
47
48 if (!first)
49 ret += scnprintf(buf + ret, size - ret, ",");
50
51 first = false;
52
53 ret += scnprintf(buf + ret, size - ret, "%d", rbot);
54 if (rbot < rtop)
55 ret += scnprintf(buf + ret, size - ret, "-%d", rtop);
56
57 rbot = cur;
58 }
59 return ret;
60}
61
62int __bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
63 const unsigned long *bitmap2, unsigned int bits)
64{
65 unsigned int k;
66 unsigned int lim = bits/BITS_PER_LONG;
67 unsigned long result = 0;
68
69 for (k = 0; k < lim; k++)
70 result |= (dst[k] = bitmap1[k] & bitmap2[k]);
71 if (bits % BITS_PER_LONG)
72 result |= (dst[k] = bitmap1[k] & bitmap2[k] &
73 BITMAP_LAST_WORD_MASK(bits));
74 return result != 0;
75}
diff --git a/tools/lib/bpf/Makefile b/tools/lib/bpf/Makefile
index fc1bc75ae56d..62d89d50fcbd 100644
--- a/tools/lib/bpf/Makefile
+++ b/tools/lib/bpf/Makefile
@@ -68,7 +68,7 @@ FEATURE_USER = .libbpf
68FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf 68FEATURE_TESTS = libelf libelf-getphdrnum libelf-mmap bpf
69FEATURE_DISPLAY = libelf bpf 69FEATURE_DISPLAY = libelf bpf
70 70
71INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/arch/$(ARCH)/include/uapi -I$(srctree)/include/uapi 71INCLUDES = -I. -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(ARCH)/include/uapi -I$(srctree)/tools/include/uapi
72FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES) 72FEATURE_CHECK_CFLAGS-bpf = $(INCLUDES)
73 73
74check_feat := 1 74check_feat := 1
@@ -154,6 +154,12 @@ all: fixdep $(VERSION_FILES) all_cmd
154all_cmd: $(CMD_TARGETS) 154all_cmd: $(CMD_TARGETS)
155 155
156$(BPF_IN): force elfdep bpfdep 156$(BPF_IN): force elfdep bpfdep
157 @(test -f ../../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \
158 (diff -B ../../include/uapi/linux/bpf.h ../../../include/uapi/linux/bpf.h >/dev/null) || \
159 echo "Warning: tools/include/uapi/linux/bpf.h differs from kernel" >&2 )) || true
160 @(test -f ../../../include/uapi/linux/bpf_common.h -a -f ../../../include/uapi/linux/bpf_common.h && ( \
161 (diff -B ../../include/uapi/linux/bpf_common.h ../../../include/uapi/linux/bpf_common.h >/dev/null) || \
162 echo "Warning: tools/include/uapi/linux/bpf_common.h differs from kernel" >&2 )) || true
157 $(Q)$(MAKE) $(build)=libbpf 163 $(Q)$(MAKE) $(build)=libbpf
158 164
159$(OUTPUT)libbpf.so: $(BPF_IN) 165$(OUTPUT)libbpf.so: $(BPF_IN)
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 1f91cc941b7c..4212ed62235b 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -4,6 +4,19 @@
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc. 6 * Copyright (C) 2015 Huawei Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation;
11 * version 2.1 of the License (not later!)
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, see <http://www.gnu.org/licenses>
7 */ 20 */
8 21
9#include <stdlib.h> 22#include <stdlib.h>
diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h
index a76465541292..e8ba54087497 100644
--- a/tools/lib/bpf/bpf.h
+++ b/tools/lib/bpf/bpf.h
@@ -4,6 +4,19 @@
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc. 6 * Copyright (C) 2015 Huawei Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation;
11 * version 2.1 of the License (not later!)
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, see <http://www.gnu.org/licenses>
7 */ 20 */
8#ifndef __BPF_BPF_H 21#ifndef __BPF_BPF_H
9#define __BPF_BPF_H 22#define __BPF_BPF_H
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 7e543c3102d4..b699aea9a025 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4,6 +4,19 @@
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc. 6 * Copyright (C) 2015 Huawei Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation;
11 * version 2.1 of the License (not later!)
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, see <http://www.gnu.org/licenses>
7 */ 20 */
8 21
9#include <stdlib.h> 22#include <stdlib.h>
@@ -24,6 +37,10 @@
24#include "libbpf.h" 37#include "libbpf.h"
25#include "bpf.h" 38#include "bpf.h"
26 39
40#ifndef EM_BPF
41#define EM_BPF 247
42#endif
43
27#define __printf(a, b) __attribute__((format(printf, a, b))) 44#define __printf(a, b) __attribute__((format(printf, a, b)))
28 45
29__printf(1, 2) 46__printf(1, 2)
@@ -71,12 +88,13 @@ static const char *libbpf_strerror_table[NR_ERRNO] = {
71 [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf", 88 [ERRCODE_OFFSET(LIBELF)] = "Something wrong in libelf",
72 [ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid", 89 [ERRCODE_OFFSET(FORMAT)] = "BPF object format invalid",
73 [ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost", 90 [ERRCODE_OFFSET(KVERSION)] = "'version' section incorrect or lost",
74 [ERRCODE_OFFSET(ENDIAN)] = "Endian missmatch", 91 [ERRCODE_OFFSET(ENDIAN)] = "Endian mismatch",
75 [ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf", 92 [ERRCODE_OFFSET(INTERNAL)] = "Internal error in libbpf",
76 [ERRCODE_OFFSET(RELOC)] = "Relocation failed", 93 [ERRCODE_OFFSET(RELOC)] = "Relocation failed",
77 [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading", 94 [ERRCODE_OFFSET(VERIFY)] = "Kernel verifier blocks program loading",
78 [ERRCODE_OFFSET(PROG2BIG)] = "Program too big", 95 [ERRCODE_OFFSET(PROG2BIG)] = "Program too big",
79 [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version", 96 [ERRCODE_OFFSET(KVER)] = "Incorrect kernel version",
97 [ERRCODE_OFFSET(PROGTYPE)] = "Kernel doesn't support this program type",
80}; 98};
81 99
82int libbpf_strerror(int err, char *buf, size_t size) 100int libbpf_strerror(int err, char *buf, size_t size)
@@ -145,6 +163,7 @@ struct bpf_program {
145 char *section_name; 163 char *section_name;
146 struct bpf_insn *insns; 164 struct bpf_insn *insns;
147 size_t insns_cnt; 165 size_t insns_cnt;
166 enum bpf_prog_type type;
148 167
149 struct { 168 struct {
150 int insn_idx; 169 int insn_idx;
@@ -286,6 +305,7 @@ bpf_program__init(void *data, size_t size, char *name, int idx,
286 prog->idx = idx; 305 prog->idx = idx;
287 prog->instances.fds = NULL; 306 prog->instances.fds = NULL;
288 prog->instances.nr = -1; 307 prog->instances.nr = -1;
308 prog->type = BPF_PROG_TYPE_KPROBE;
289 309
290 return 0; 310 return 0;
291errout: 311errout:
@@ -423,7 +443,8 @@ static int bpf_object__elf_init(struct bpf_object *obj)
423 } 443 }
424 ep = &obj->efile.ehdr; 444 ep = &obj->efile.ehdr;
425 445
426 if ((ep->e_type != ET_REL) || (ep->e_machine != 0)) { 446 /* Old LLVM set e_machine to EM_NONE */
447 if ((ep->e_type != ET_REL) || (ep->e_machine && (ep->e_machine != EM_BPF))) {
427 pr_warning("%s is not an eBPF object file\n", 448 pr_warning("%s is not an eBPF object file\n",
428 obj->path); 449 obj->path);
429 err = -LIBBPF_ERRNO__FORMAT; 450 err = -LIBBPF_ERRNO__FORMAT;
@@ -881,8 +902,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
881} 902}
882 903
883static int 904static int
884load_program(struct bpf_insn *insns, int insns_cnt, 905load_program(enum bpf_prog_type type, struct bpf_insn *insns,
885 char *license, u32 kern_version, int *pfd) 906 int insns_cnt, char *license, u32 kern_version, int *pfd)
886{ 907{
887 int ret; 908 int ret;
888 char *log_buf; 909 char *log_buf;
@@ -894,9 +915,8 @@ load_program(struct bpf_insn *insns, int insns_cnt,
894 if (!log_buf) 915 if (!log_buf)
895 pr_warning("Alloc log buffer for bpf loader error, continue without log\n"); 916 pr_warning("Alloc log buffer for bpf loader error, continue without log\n");
896 917
897 ret = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns, 918 ret = bpf_load_program(type, insns, insns_cnt, license,
898 insns_cnt, license, kern_version, 919 kern_version, log_buf, BPF_LOG_BUF_SIZE);
899 log_buf, BPF_LOG_BUF_SIZE);
900 920
901 if (ret >= 0) { 921 if (ret >= 0) {
902 *pfd = ret; 922 *pfd = ret;
@@ -912,15 +932,27 @@ load_program(struct bpf_insn *insns, int insns_cnt,
912 pr_warning("-- BEGIN DUMP LOG ---\n"); 932 pr_warning("-- BEGIN DUMP LOG ---\n");
913 pr_warning("\n%s\n", log_buf); 933 pr_warning("\n%s\n", log_buf);
914 pr_warning("-- END LOG --\n"); 934 pr_warning("-- END LOG --\n");
935 } else if (insns_cnt >= BPF_MAXINSNS) {
936 pr_warning("Program too large (%d insns), at most %d insns\n",
937 insns_cnt, BPF_MAXINSNS);
938 ret = -LIBBPF_ERRNO__PROG2BIG;
915 } else { 939 } else {
916 if (insns_cnt >= BPF_MAXINSNS) { 940 /* Wrong program type? */
917 pr_warning("Program too large (%d insns), at most %d insns\n", 941 if (type != BPF_PROG_TYPE_KPROBE) {
918 insns_cnt, BPF_MAXINSNS); 942 int fd;
919 ret = -LIBBPF_ERRNO__PROG2BIG; 943
920 } else if (log_buf) { 944 fd = bpf_load_program(BPF_PROG_TYPE_KPROBE, insns,
921 pr_warning("log buffer is empty\n"); 945 insns_cnt, license, kern_version,
922 ret = -LIBBPF_ERRNO__KVER; 946 NULL, 0);
947 if (fd >= 0) {
948 close(fd);
949 ret = -LIBBPF_ERRNO__PROGTYPE;
950 goto out;
951 }
923 } 952 }
953
954 if (log_buf)
955 ret = -LIBBPF_ERRNO__KVER;
924 } 956 }
925 957
926out: 958out:
@@ -955,7 +987,7 @@ bpf_program__load(struct bpf_program *prog,
955 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n", 987 pr_warning("Program '%s' is inconsistent: nr(%d) != 1\n",
956 prog->section_name, prog->instances.nr); 988 prog->section_name, prog->instances.nr);
957 } 989 }
958 err = load_program(prog->insns, prog->insns_cnt, 990 err = load_program(prog->type, prog->insns, prog->insns_cnt,
959 license, kern_version, &fd); 991 license, kern_version, &fd);
960 if (!err) 992 if (!err)
961 prog->instances.fds[0] = fd; 993 prog->instances.fds[0] = fd;
@@ -984,7 +1016,7 @@ bpf_program__load(struct bpf_program *prog,
984 continue; 1016 continue;
985 } 1017 }
986 1018
987 err = load_program(result.new_insn_ptr, 1019 err = load_program(prog->type, result.new_insn_ptr,
988 result.new_insn_cnt, 1020 result.new_insn_cnt,
989 license, kern_version, &fd); 1021 license, kern_version, &fd);
990 1022
@@ -1186,20 +1218,14 @@ bpf_object__next(struct bpf_object *prev)
1186 return next; 1218 return next;
1187} 1219}
1188 1220
1189const char * 1221const char *bpf_object__name(struct bpf_object *obj)
1190bpf_object__get_name(struct bpf_object *obj)
1191{ 1222{
1192 if (!obj) 1223 return obj ? obj->path : ERR_PTR(-EINVAL);
1193 return ERR_PTR(-EINVAL);
1194 return obj->path;
1195} 1224}
1196 1225
1197unsigned int 1226unsigned int bpf_object__kversion(struct bpf_object *obj)
1198bpf_object__get_kversion(struct bpf_object *obj)
1199{ 1227{
1200 if (!obj) 1228 return obj ? obj->kern_version : 0;
1201 return 0;
1202 return obj->kern_version;
1203} 1229}
1204 1230
1205struct bpf_program * 1231struct bpf_program *
@@ -1224,9 +1250,8 @@ bpf_program__next(struct bpf_program *prev, struct bpf_object *obj)
1224 return &obj->programs[idx]; 1250 return &obj->programs[idx];
1225} 1251}
1226 1252
1227int bpf_program__set_private(struct bpf_program *prog, 1253int bpf_program__set_priv(struct bpf_program *prog, void *priv,
1228 void *priv, 1254 bpf_program_clear_priv_t clear_priv)
1229 bpf_program_clear_priv_t clear_priv)
1230{ 1255{
1231 if (prog->priv && prog->clear_priv) 1256 if (prog->priv && prog->clear_priv)
1232 prog->clear_priv(prog, prog->priv); 1257 prog->clear_priv(prog, prog->priv);
@@ -1236,10 +1261,9 @@ int bpf_program__set_private(struct bpf_program *prog,
1236 return 0; 1261 return 0;
1237} 1262}
1238 1263
1239int bpf_program__get_private(struct bpf_program *prog, void **ppriv) 1264void *bpf_program__priv(struct bpf_program *prog)
1240{ 1265{
1241 *ppriv = prog->priv; 1266 return prog ? prog->priv : ERR_PTR(-EINVAL);
1242 return 0;
1243} 1267}
1244 1268
1245const char *bpf_program__title(struct bpf_program *prog, bool needs_copy) 1269const char *bpf_program__title(struct bpf_program *prog, bool needs_copy)
@@ -1311,32 +1335,61 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n)
1311 return fd; 1335 return fd;
1312} 1336}
1313 1337
1314int bpf_map__get_fd(struct bpf_map *map) 1338static void bpf_program__set_type(struct bpf_program *prog,
1339 enum bpf_prog_type type)
1315{ 1340{
1316 if (!map) 1341 prog->type = type;
1317 return -EINVAL;
1318
1319 return map->fd;
1320} 1342}
1321 1343
1322int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef) 1344int bpf_program__set_tracepoint(struct bpf_program *prog)
1323{ 1345{
1324 if (!map || !pdef) 1346 if (!prog)
1325 return -EINVAL; 1347 return -EINVAL;
1348 bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
1349 return 0;
1350}
1326 1351
1327 *pdef = map->def; 1352int bpf_program__set_kprobe(struct bpf_program *prog)
1353{
1354 if (!prog)
1355 return -EINVAL;
1356 bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
1328 return 0; 1357 return 0;
1329} 1358}
1330 1359
1331const char *bpf_map__get_name(struct bpf_map *map) 1360static bool bpf_program__is_type(struct bpf_program *prog,
1361 enum bpf_prog_type type)
1332{ 1362{
1333 if (!map) 1363 return prog ? (prog->type == type) : false;
1334 return NULL; 1364}
1335 return map->name; 1365
1366bool bpf_program__is_tracepoint(struct bpf_program *prog)
1367{
1368 return bpf_program__is_type(prog, BPF_PROG_TYPE_TRACEPOINT);
1369}
1370
1371bool bpf_program__is_kprobe(struct bpf_program *prog)
1372{
1373 return bpf_program__is_type(prog, BPF_PROG_TYPE_KPROBE);
1374}
1375
1376int bpf_map__fd(struct bpf_map *map)
1377{
1378 return map ? map->fd : -EINVAL;
1336} 1379}
1337 1380
1338int bpf_map__set_private(struct bpf_map *map, void *priv, 1381const struct bpf_map_def *bpf_map__def(struct bpf_map *map)
1339 bpf_map_clear_priv_t clear_priv) 1382{
1383 return map ? &map->def : ERR_PTR(-EINVAL);
1384}
1385
1386const char *bpf_map__name(struct bpf_map *map)
1387{
1388 return map ? map->name : NULL;
1389}
1390
1391int bpf_map__set_priv(struct bpf_map *map, void *priv,
1392 bpf_map_clear_priv_t clear_priv)
1340{ 1393{
1341 if (!map) 1394 if (!map)
1342 return -EINVAL; 1395 return -EINVAL;
@@ -1351,14 +1404,9 @@ int bpf_map__set_private(struct bpf_map *map, void *priv,
1351 return 0; 1404 return 0;
1352} 1405}
1353 1406
1354int bpf_map__get_private(struct bpf_map *map, void **ppriv) 1407void *bpf_map__priv(struct bpf_map *map)
1355{ 1408{
1356 if (!map) 1409 return map ? map->priv : ERR_PTR(-EINVAL);
1357 return -EINVAL;
1358
1359 if (ppriv)
1360 *ppriv = map->priv;
1361 return 0;
1362} 1410}
1363 1411
1364struct bpf_map * 1412struct bpf_map *
@@ -1389,7 +1437,7 @@ bpf_map__next(struct bpf_map *prev, struct bpf_object *obj)
1389} 1437}
1390 1438
1391struct bpf_map * 1439struct bpf_map *
1392bpf_object__get_map_by_name(struct bpf_object *obj, const char *name) 1440bpf_object__find_map_by_name(struct bpf_object *obj, const char *name)
1393{ 1441{
1394 struct bpf_map *pos; 1442 struct bpf_map *pos;
1395 1443
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index a51594c7b518..dd7a513efb10 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -4,6 +4,19 @@
4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org> 4 * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com> 5 * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
6 * Copyright (C) 2015 Huawei Inc. 6 * Copyright (C) 2015 Huawei Inc.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation;
11 * version 2.1 of the License (not later!)
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this program; if not, see <http://www.gnu.org/licenses>
7 */ 20 */
8#ifndef __BPF_LIBBPF_H 21#ifndef __BPF_LIBBPF_H
9#define __BPF_LIBBPF_H 22#define __BPF_LIBBPF_H
@@ -19,13 +32,14 @@ enum libbpf_errno {
19 LIBBPF_ERRNO__LIBELF = __LIBBPF_ERRNO__START, 32 LIBBPF_ERRNO__LIBELF = __LIBBPF_ERRNO__START,
20 LIBBPF_ERRNO__FORMAT, /* BPF object format invalid */ 33 LIBBPF_ERRNO__FORMAT, /* BPF object format invalid */
21 LIBBPF_ERRNO__KVERSION, /* Incorrect or no 'version' section */ 34 LIBBPF_ERRNO__KVERSION, /* Incorrect or no 'version' section */
22 LIBBPF_ERRNO__ENDIAN, /* Endian missmatch */ 35 LIBBPF_ERRNO__ENDIAN, /* Endian mismatch */
23 LIBBPF_ERRNO__INTERNAL, /* Internal error in libbpf */ 36 LIBBPF_ERRNO__INTERNAL, /* Internal error in libbpf */
24 LIBBPF_ERRNO__RELOC, /* Relocation failed */ 37 LIBBPF_ERRNO__RELOC, /* Relocation failed */
25 LIBBPF_ERRNO__LOAD, /* Load program failure for unknown reason */ 38 LIBBPF_ERRNO__LOAD, /* Load program failure for unknown reason */
26 LIBBPF_ERRNO__VERIFY, /* Kernel verifier blocks program loading */ 39 LIBBPF_ERRNO__VERIFY, /* Kernel verifier blocks program loading */
27 LIBBPF_ERRNO__PROG2BIG, /* Program too big */ 40 LIBBPF_ERRNO__PROG2BIG, /* Program too big */
28 LIBBPF_ERRNO__KVER, /* Incorrect kernel version */ 41 LIBBPF_ERRNO__KVER, /* Incorrect kernel version */
42 LIBBPF_ERRNO__PROGTYPE, /* Kernel doesn't support this program type */
29 __LIBBPF_ERRNO__END, 43 __LIBBPF_ERRNO__END,
30}; 44};
31 45
@@ -55,8 +69,8 @@ void bpf_object__close(struct bpf_object *object);
55/* Load/unload object into/from kernel */ 69/* Load/unload object into/from kernel */
56int bpf_object__load(struct bpf_object *obj); 70int bpf_object__load(struct bpf_object *obj);
57int bpf_object__unload(struct bpf_object *obj); 71int bpf_object__unload(struct bpf_object *obj);
58const char *bpf_object__get_name(struct bpf_object *obj); 72const char *bpf_object__name(struct bpf_object *obj);
59unsigned int bpf_object__get_kversion(struct bpf_object *obj); 73unsigned int bpf_object__kversion(struct bpf_object *obj);
60 74
61struct bpf_object *bpf_object__next(struct bpf_object *prev); 75struct bpf_object *bpf_object__next(struct bpf_object *prev);
62#define bpf_object__for_each_safe(pos, tmp) \ 76#define bpf_object__for_each_safe(pos, tmp) \
@@ -78,11 +92,10 @@ struct bpf_program *bpf_program__next(struct bpf_program *prog,
78typedef void (*bpf_program_clear_priv_t)(struct bpf_program *, 92typedef void (*bpf_program_clear_priv_t)(struct bpf_program *,
79 void *); 93 void *);
80 94
81int bpf_program__set_private(struct bpf_program *prog, void *priv, 95int bpf_program__set_priv(struct bpf_program *prog, void *priv,
82 bpf_program_clear_priv_t clear_priv); 96 bpf_program_clear_priv_t clear_priv);
83 97
84int bpf_program__get_private(struct bpf_program *prog, 98void *bpf_program__priv(struct bpf_program *prog);
85 void **ppriv);
86 99
87const char *bpf_program__title(struct bpf_program *prog, bool needs_copy); 100const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
88 101
@@ -153,6 +166,15 @@ int bpf_program__set_prep(struct bpf_program *prog, int nr_instance,
153int bpf_program__nth_fd(struct bpf_program *prog, int n); 166int bpf_program__nth_fd(struct bpf_program *prog, int n);
154 167
155/* 168/*
169 * Adjust type of bpf program. Default is kprobe.
170 */
171int bpf_program__set_tracepoint(struct bpf_program *prog);
172int bpf_program__set_kprobe(struct bpf_program *prog);
173
174bool bpf_program__is_tracepoint(struct bpf_program *prog);
175bool bpf_program__is_kprobe(struct bpf_program *prog);
176
177/*
156 * We don't need __attribute__((packed)) now since it is 178 * We don't need __attribute__((packed)) now since it is
157 * unnecessary for 'bpf_map_def' because they are all aligned. 179 * unnecessary for 'bpf_map_def' because they are all aligned.
158 * In addition, using it will trigger -Wpacked warning message, 180 * In addition, using it will trigger -Wpacked warning message,
@@ -171,7 +193,7 @@ struct bpf_map_def {
171 */ 193 */
172struct bpf_map; 194struct bpf_map;
173struct bpf_map * 195struct bpf_map *
174bpf_object__get_map_by_name(struct bpf_object *obj, const char *name); 196bpf_object__find_map_by_name(struct bpf_object *obj, const char *name);
175 197
176struct bpf_map * 198struct bpf_map *
177bpf_map__next(struct bpf_map *map, struct bpf_object *obj); 199bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
@@ -180,13 +202,13 @@ bpf_map__next(struct bpf_map *map, struct bpf_object *obj);
180 (pos) != NULL; \ 202 (pos) != NULL; \
181 (pos) = bpf_map__next((pos), (obj))) 203 (pos) = bpf_map__next((pos), (obj)))
182 204
183int bpf_map__get_fd(struct bpf_map *map); 205int bpf_map__fd(struct bpf_map *map);
184int bpf_map__get_def(struct bpf_map *map, struct bpf_map_def *pdef); 206const struct bpf_map_def *bpf_map__def(struct bpf_map *map);
185const char *bpf_map__get_name(struct bpf_map *map); 207const char *bpf_map__name(struct bpf_map *map);
186 208
187typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *); 209typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
188int bpf_map__set_private(struct bpf_map *map, void *priv, 210int bpf_map__set_priv(struct bpf_map *map, void *priv,
189 bpf_map_clear_priv_t clear_priv); 211 bpf_map_clear_priv_t clear_priv);
190int bpf_map__get_private(struct bpf_map *map, void **ppriv); 212void *bpf_map__priv(struct bpf_map *map);
191 213
192#endif 214#endif
diff --git a/tools/lib/str_error_r.c b/tools/lib/str_error_r.c
new file mode 100644
index 000000000000..503ae072244c
--- /dev/null
+++ b/tools/lib/str_error_r.c
@@ -0,0 +1,26 @@
1#undef _GNU_SOURCE
2#include <string.h>
3#include <stdio.h>
4#include <linux/string.h>
5
6/*
7 * The tools so far have been using the strerror_r() GNU variant, that returns
8 * a string, be it the buffer passed or something else.
9 *
10 * But that, besides being tricky in cases where we expect that the function
11 * using strerror_r() returns the error formatted in a provided buffer (we have
12 * to check if it returned something else and copy that instead), breaks the
13 * build on systems not using glibc, like Alpine Linux, where musl libc is
14 * used.
15 *
16 * So, introduce yet another wrapper, str_error_r(), that has the GNU
17 * interface, but uses the portable XSI variant of strerror_r(), so that users
18 * rest asured that the provided buffer is used and it is what is returned.
19 */
20char *str_error_r(int errnum, char *buf, size_t buflen)
21{
22 int err = strerror_r(errnum, buf, buflen);
23 if (err)
24 snprintf(buf, buflen, "INTERNAL ERROR: strerror_r(%d, %p, %zd)=%d", errnum, buf, buflen, err);
25 return buf;
26}
diff --git a/tools/lib/subcmd/Makefile b/tools/lib/subcmd/Makefile
index a8103700c172..ce4b7e527566 100644
--- a/tools/lib/subcmd/Makefile
+++ b/tools/lib/subcmd/Makefile
@@ -19,7 +19,13 @@ MAKEFLAGS += --no-print-directory
19LIBFILE = $(OUTPUT)libsubcmd.a 19LIBFILE = $(OUTPUT)libsubcmd.a
20 20
21CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS) 21CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
22CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -Werror -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC 22CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -O6 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
23
24# Treat warnings as errors unless directed not to
25ifneq ($(WERROR),0)
26 CFLAGS += -Werror
27endif
28
23CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE 29CFLAGS += -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -D_GNU_SOURCE
24 30
25CFLAGS += -I$(srctree)/tools/include/ 31CFLAGS += -I$(srctree)/tools/include/
diff --git a/tools/lib/subcmd/pager.c b/tools/lib/subcmd/pager.c
index d50f3b58606b..6518bea926d6 100644
--- a/tools/lib/subcmd/pager.c
+++ b/tools/lib/subcmd/pager.c
@@ -3,6 +3,7 @@
3#include <stdio.h> 3#include <stdio.h>
4#include <string.h> 4#include <string.h>
5#include <signal.h> 5#include <signal.h>
6#include <sys/ioctl.h>
6#include "pager.h" 7#include "pager.h"
7#include "run-command.h" 8#include "run-command.h"
8#include "sigchain.h" 9#include "sigchain.h"
@@ -14,6 +15,7 @@
14 */ 15 */
15 16
16static int spawned_pager; 17static int spawned_pager;
18static int pager_columns;
17 19
18void pager_init(const char *pager_env) 20void pager_init(const char *pager_env)
19{ 21{
@@ -58,9 +60,12 @@ static void wait_for_pager_signal(int signo)
58void setup_pager(void) 60void setup_pager(void)
59{ 61{
60 const char *pager = getenv(subcmd_config.pager_env); 62 const char *pager = getenv(subcmd_config.pager_env);
63 struct winsize sz;
61 64
62 if (!isatty(1)) 65 if (!isatty(1))
63 return; 66 return;
67 if (ioctl(1, TIOCGWINSZ, &sz) == 0)
68 pager_columns = sz.ws_col;
64 if (!pager) 69 if (!pager)
65 pager = getenv("PAGER"); 70 pager = getenv("PAGER");
66 if (!(pager || access("/usr/bin/pager", X_OK))) 71 if (!(pager || access("/usr/bin/pager", X_OK)))
@@ -98,3 +103,14 @@ int pager_in_use(void)
98{ 103{
99 return spawned_pager; 104 return spawned_pager;
100} 105}
106
107int pager_get_columns(void)
108{
109 char *s;
110
111 s = getenv("COLUMNS");
112 if (s)
113 return atoi(s);
114
115 return (pager_columns ? pager_columns : 80) - 2;
116}
diff --git a/tools/lib/subcmd/pager.h b/tools/lib/subcmd/pager.h
index 8b83714ecf73..623f5542d05d 100644
--- a/tools/lib/subcmd/pager.h
+++ b/tools/lib/subcmd/pager.h
@@ -5,5 +5,6 @@ extern void pager_init(const char *pager_env);
5 5
6extern void setup_pager(void); 6extern void setup_pager(void);
7extern int pager_in_use(void); 7extern int pager_in_use(void);
8extern int pager_get_columns(void);
8 9
9#endif /* __SUBCMD_PAGER_H */ 10#endif /* __SUBCMD_PAGER_H */
diff --git a/tools/lib/subcmd/run-command.c b/tools/lib/subcmd/run-command.c
index f4f6c9eb8e59..911f83942723 100644
--- a/tools/lib/subcmd/run-command.c
+++ b/tools/lib/subcmd/run-command.c
@@ -3,6 +3,7 @@
3#include <sys/stat.h> 3#include <sys/stat.h>
4#include <fcntl.h> 4#include <fcntl.h>
5#include <string.h> 5#include <string.h>
6#include <linux/string.h>
6#include <errno.h> 7#include <errno.h>
7#include <sys/wait.h> 8#include <sys/wait.h>
8#include "subcmd-util.h" 9#include "subcmd-util.h"
@@ -109,7 +110,7 @@ int start_command(struct child_process *cmd)
109 110
110 if (cmd->dir && chdir(cmd->dir)) 111 if (cmd->dir && chdir(cmd->dir))
111 die("exec %s: cd to %s failed (%s)", cmd->argv[0], 112 die("exec %s: cd to %s failed (%s)", cmd->argv[0],
112 cmd->dir, strerror_r(errno, sbuf, sizeof(sbuf))); 113 cmd->dir, str_error_r(errno, sbuf, sizeof(sbuf)));
113 if (cmd->env) { 114 if (cmd->env) {
114 for (; *cmd->env; cmd->env++) { 115 for (; *cmd->env; cmd->env++) {
115 if (strchr(*cmd->env, '=')) 116 if (strchr(*cmd->env, '='))
@@ -173,7 +174,7 @@ static int wait_or_whine(pid_t pid)
173 if (errno == EINTR) 174 if (errno == EINTR)
174 continue; 175 continue;
175 fprintf(stderr, " Error: waitpid failed (%s)", 176 fprintf(stderr, " Error: waitpid failed (%s)",
176 strerror_r(errno, sbuf, sizeof(sbuf))); 177 str_error_r(errno, sbuf, sizeof(sbuf)));
177 return -ERR_RUN_COMMAND_WAITPID; 178 return -ERR_RUN_COMMAND_WAITPID;
178 } 179 }
179 if (waiting != pid) 180 if (waiting != pid)
diff --git a/tools/lib/traceevent/.gitignore b/tools/lib/traceevent/.gitignore
index 3c60335fe7be..9e9f25fb1922 100644
--- a/tools/lib/traceevent/.gitignore
+++ b/tools/lib/traceevent/.gitignore
@@ -1,2 +1,3 @@
1TRACEEVENT-CFLAGS 1TRACEEVENT-CFLAGS
2libtraceevent-dynamic-list 2libtraceevent-dynamic-list
3libtraceevent.so.*
diff --git a/tools/lib/traceevent/event-parse.c b/tools/lib/traceevent/event-parse.c
index a8b6357d1ffe..664c90c8e22b 100644
--- a/tools/lib/traceevent/event-parse.c
+++ b/tools/lib/traceevent/event-parse.c
@@ -23,6 +23,7 @@
23 * Frederic Weisbecker gave his permission to relicense the code to 23 * Frederic Weisbecker gave his permission to relicense the code to
24 * the Lesser General Public License. 24 * the Lesser General Public License.
25 */ 25 */
26#include <inttypes.h>
26#include <stdio.h> 27#include <stdio.h>
27#include <stdlib.h> 28#include <stdlib.h>
28#include <string.h> 29#include <string.h>
@@ -31,8 +32,9 @@
31#include <errno.h> 32#include <errno.h>
32#include <stdint.h> 33#include <stdint.h>
33#include <limits.h> 34#include <limits.h>
35#include <linux/string.h>
34 36
35#include <netinet/ip6.h> 37#include <netinet/in.h>
36#include "event-parse.h" 38#include "event-parse.h"
37#include "event-utils.h" 39#include "event-utils.h"
38 40
@@ -6131,12 +6133,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused,
6131 const char *msg; 6133 const char *msg;
6132 6134
6133 if (errnum >= 0) { 6135 if (errnum >= 0) {
6134 msg = strerror_r(errnum, buf, buflen); 6136 str_error_r(errnum, buf, buflen);
6135 if (msg != buf) {
6136 size_t len = strlen(msg);
6137 memcpy(buf, msg, min(buflen - 1, len));
6138 *(buf + min(buflen - 1, len)) = '\0';
6139 }
6140 return 0; 6137 return 0;
6141 } 6138 }
6142 6139
diff --git a/tools/lib/traceevent/kbuffer-parse.c b/tools/lib/traceevent/kbuffer-parse.c
index 3bcada3ae05a..65984f1c2974 100644
--- a/tools/lib/traceevent/kbuffer-parse.c
+++ b/tools/lib/traceevent/kbuffer-parse.c
@@ -622,6 +622,7 @@ void *kbuffer_read_at_offset(struct kbuffer *kbuf, int offset,
622 622
623 /* Reset the buffer */ 623 /* Reset the buffer */
624 kbuffer_load_subbuffer(kbuf, kbuf->subbuffer); 624 kbuffer_load_subbuffer(kbuf, kbuf->subbuffer);
625 data = kbuffer_read_event(kbuf, ts);
625 626
626 while (kbuf->curr < offset) { 627 while (kbuf->curr < offset) {
627 data = kbuffer_next_event(kbuf, ts); 628 data = kbuffer_next_event(kbuf, ts);
diff --git a/tools/lib/traceevent/parse-filter.c b/tools/lib/traceevent/parse-filter.c
index 88cccea3ca99..7c214ceb9386 100644
--- a/tools/lib/traceevent/parse-filter.c
+++ b/tools/lib/traceevent/parse-filter.c
@@ -28,11 +28,16 @@
28#include "event-utils.h" 28#include "event-utils.h"
29 29
30#define COMM "COMM" 30#define COMM "COMM"
31#define CPU "CPU"
31 32
32static struct format_field comm = { 33static struct format_field comm = {
33 .name = "COMM", 34 .name = "COMM",
34}; 35};
35 36
37static struct format_field cpu = {
38 .name = "CPU",
39};
40
36struct event_list { 41struct event_list {
37 struct event_list *next; 42 struct event_list *next;
38 struct event_format *event; 43 struct event_format *event;
@@ -382,14 +387,17 @@ create_arg_item(struct event_format *event, const char *token,
382 /* Consider this a field */ 387 /* Consider this a field */
383 field = pevent_find_any_field(event, token); 388 field = pevent_find_any_field(event, token);
384 if (!field) { 389 if (!field) {
385 if (strcmp(token, COMM) != 0) { 390 /* If token is 'COMM' or 'CPU' then it is special */
391 if (strcmp(token, COMM) == 0) {
392 field = &comm;
393 } else if (strcmp(token, CPU) == 0) {
394 field = &cpu;
395 } else {
386 /* not a field, Make it false */ 396 /* not a field, Make it false */
387 arg->type = FILTER_ARG_BOOLEAN; 397 arg->type = FILTER_ARG_BOOLEAN;
388 arg->boolean.value = FILTER_FALSE; 398 arg->boolean.value = FILTER_FALSE;
389 break; 399 break;
390 } 400 }
391 /* If token is 'COMM' then it is special */
392 field = &comm;
393 } 401 }
394 arg->type = FILTER_ARG_FIELD; 402 arg->type = FILTER_ARG_FIELD;
395 arg->field.field = field; 403 arg->field.field = field;
@@ -1718,6 +1726,10 @@ get_value(struct event_format *event,
1718 return (unsigned long)name; 1726 return (unsigned long)name;
1719 } 1727 }
1720 1728
1729 /* Handle our dummy "cpu" field */
1730 if (field == &cpu)
1731 return record->cpu;
1732
1721 pevent_read_number_field(field, record->data, &val); 1733 pevent_read_number_field(field, record->data, &val);
1722 1734
1723 if (!(field->flags & FIELD_IS_SIGNED)) 1735 if (!(field->flags & FIELD_IS_SIGNED))
diff --git a/tools/lib/vsprintf.c b/tools/lib/vsprintf.c
new file mode 100644
index 000000000000..45f9a06daa56
--- /dev/null
+++ b/tools/lib/vsprintf.c
@@ -0,0 +1,24 @@
1#include <sys/types.h>
2#include <linux/kernel.h>
3#include <stdio.h>
4
5int vscnprintf(char *buf, size_t size, const char *fmt, va_list args)
6{
7 int i = vsnprintf(buf, size, fmt, args);
8 ssize_t ssize = size;
9
10 return (i >= ssize) ? (ssize - 1) : i;
11}
12
13int scnprintf(char * buf, size_t size, const char * fmt, ...)
14{
15 ssize_t ssize = size;
16 va_list args;
17 int i;
18
19 va_start(args, fmt);
20 i = vsnprintf(buf, size, fmt, args);
21 va_end(args);
22
23 return (i >= ssize) ? (ssize - 1) : i;
24}
diff --git a/tools/objtool/.gitignore b/tools/objtool/.gitignore
index a0b3128bb31f..d3102c865a95 100644
--- a/tools/objtool/.gitignore
+++ b/tools/objtool/.gitignore
@@ -1,2 +1,3 @@
1arch/x86/insn/inat-tables.c 1arch/x86/insn/inat-tables.c
2objtool 2objtool
3fixdep
diff --git a/tools/objtool/Build b/tools/objtool/Build
index 0e89258a3541..d6cdece5e58b 100644
--- a/tools/objtool/Build
+++ b/tools/objtool/Build
@@ -1,13 +1,18 @@
1objtool-y += arch/$(ARCH)/ 1objtool-y += arch/$(SRCARCH)/
2objtool-y += builtin-check.o 2objtool-y += builtin-check.o
3objtool-y += elf.o 3objtool-y += elf.o
4objtool-y += special.o 4objtool-y += special.o
5objtool-y += objtool.o 5objtool-y += objtool.o
6 6
7objtool-y += libstring.o 7objtool-y += libstring.o
8objtool-y += str_error_r.o
8 9
9CFLAGS += -I$(srctree)/tools/lib 10CFLAGS += -I$(srctree)/tools/lib
10 11
11$(OUTPUT)libstring.o: ../lib/string.c FORCE 12$(OUTPUT)libstring.o: ../lib/string.c FORCE
12 $(call rule_mkdir) 13 $(call rule_mkdir)
13 $(call if_changed_dep,cc_o_c) 14 $(call if_changed_dep,cc_o_c)
15
16$(OUTPUT)str_error_r.o: ../lib/str_error_r.c FORCE
17 $(call rule_mkdir)
18 $(call if_changed_dep,cc_o_c)
diff --git a/tools/objtool/Makefile b/tools/objtool/Makefile
index f094f3c4ed84..041b493ad3ab 100644
--- a/tools/objtool/Makefile
+++ b/tools/objtool/Makefile
@@ -1,11 +1,9 @@
1include ../scripts/Makefile.include 1include ../scripts/Makefile.include
2include ../scripts/Makefile.arch
2 3
3ifndef ($(ARCH))
4ARCH ?= $(shell uname -m)
5ifeq ($(ARCH),x86_64) 4ifeq ($(ARCH),x86_64)
6ARCH := x86 5ARCH := x86
7endif 6endif
8endif
9 7
10# always use the host compiler 8# always use the host compiler
11CC = gcc 9CC = gcc
@@ -26,7 +24,7 @@ OBJTOOL_IN := $(OBJTOOL)-in.o
26 24
27all: $(OBJTOOL) 25all: $(OBJTOOL)
28 26
29INCLUDES := -I$(srctree)/tools/include 27INCLUDES := -I$(srctree)/tools/include -I$(srctree)/tools/arch/$(HOSTARCH)/include/uapi
30CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES) 28CFLAGS += -Wall -Werror $(EXTRA_WARNINGS) -fomit-frame-pointer -O2 -g $(INCLUDES)
31LDFLAGS += -lelf $(LIBSUBCMD) 29LDFLAGS += -lelf $(LIBSUBCMD)
32 30
@@ -35,14 +33,17 @@ elfshdr := $(shell echo '\#include <libelf.h>' | $(CC) $(CFLAGS) -x c -E - | gre
35CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED) 33CFLAGS += $(if $(elfshdr),,-DLIBELF_USE_DEPRECATED)
36 34
37AWK = awk 35AWK = awk
38export srctree OUTPUT CFLAGS ARCH AWK 36export srctree OUTPUT CFLAGS SRCARCH AWK
39include $(srctree)/tools/build/Makefile.include 37include $(srctree)/tools/build/Makefile.include
40 38
41$(OBJTOOL_IN): fixdep FORCE 39$(OBJTOOL_IN): fixdep FORCE
42 @$(MAKE) $(build)=objtool 40 @$(MAKE) $(build)=objtool
43 41
42# Busybox's diff doesn't have -I, avoid warning in that case
43#
44$(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN) 44$(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN)
45 @(test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \ 45 @(diff -I 2>&1 | grep -q 'option requires an argument' && \
46 test -d ../../kernel -a -d ../../tools -a -d ../objtool && (( \
46 diff -I'^#include' arch/x86/insn/insn.c ../../arch/x86/lib/insn.c >/dev/null && \ 47 diff -I'^#include' arch/x86/insn/insn.c ../../arch/x86/lib/insn.c >/dev/null && \
47 diff -I'^#include' arch/x86/insn/inat.c ../../arch/x86/lib/inat.c >/dev/null && \ 48 diff -I'^#include' arch/x86/insn/inat.c ../../arch/x86/lib/inat.c >/dev/null && \
48 diff arch/x86/insn/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \ 49 diff arch/x86/insn/x86-opcode-map.txt ../../arch/x86/lib/x86-opcode-map.txt >/dev/null && \
@@ -50,7 +51,7 @@ $(OBJTOOL): $(LIBSUBCMD) $(OBJTOOL_IN)
50 diff -I'^#include' arch/x86/insn/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \ 51 diff -I'^#include' arch/x86/insn/insn.h ../../arch/x86/include/asm/insn.h >/dev/null && \
51 diff -I'^#include' arch/x86/insn/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \ 52 diff -I'^#include' arch/x86/insn/inat.h ../../arch/x86/include/asm/inat.h >/dev/null && \
52 diff -I'^#include' arch/x86/insn/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \ 53 diff -I'^#include' arch/x86/insn/inat_types.h ../../arch/x86/include/asm/inat_types.h >/dev/null) \
53 || echo "Warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true 54 || echo "warning: objtool: x86 instruction decoder differs from kernel" >&2 )) || true
54 $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@ 55 $(QUIET_LINK)$(CC) $(OBJTOOL_IN) $(LDFLAGS) -o $@
55 56
56 57
diff --git a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk b/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
index 093a892026f9..a3d2c62fd805 100644
--- a/tools/objtool/arch/x86/insn/gen-insn-attr-x86.awk
+++ b/tools/objtool/arch/x86/insn/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/objtool/arch/x86/insn/inat.h b/tools/objtool/arch/x86/insn/inat.h
index 611645e903a8..125ecd2a300d 100644
--- a/tools/objtool/arch/x86/insn/inat.h
+++ b/tools/objtool/arch/x86/insn/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/objtool/arch/x86/insn/insn.c b/tools/objtool/arch/x86/insn/insn.c
index 9f26eae6c9f0..ca983e2bea8b 100644
--- a/tools/objtool/arch/x86/insn/insn.c
+++ b/tools/objtool/arch/x86/insn/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/objtool/arch/x86/insn/insn.h b/tools/objtool/arch/x86/insn/insn.h
index dd12da0f4593..e23578c7b1be 100644
--- a/tools/objtool/arch/x86/insn/insn.h
+++ b/tools/objtool/arch/x86/insn/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/objtool/arch/x86/insn/x86-opcode-map.txt b/tools/objtool/arch/x86/insn/x86-opcode-map.txt
index d388de72eaca..767be7c76034 100644
--- a/tools/objtool/arch/x86/insn/x86-opcode-map.txt
+++ b/tools/objtool/arch/x86/insn/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/objtool/builtin-check.c b/tools/objtool/builtin-check.c
index e8a1e69eb92c..143b6cdd7f06 100644
--- a/tools/objtool/builtin-check.c
+++ b/tools/objtool/builtin-check.c
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28#include <string.h> 28#include <string.h>
29#include <stdlib.h>
29#include <subcmd/parse-options.h> 30#include <subcmd/parse-options.h>
30 31
31#include "builtin.h" 32#include "builtin.h"
@@ -106,6 +107,12 @@ static struct instruction *next_insn_same_sec(struct objtool_file *file,
106 insn->offset < func->offset + func->len; \ 107 insn->offset < func->offset + func->len; \
107 insn = list_next_entry(insn, list)) 108 insn = list_next_entry(insn, list))
108 109
110#define func_for_each_insn_continue_reverse(file, func, insn) \
111 for (insn = list_prev_entry(insn, list); \
112 &insn->list != &file->insn_list && \
113 insn->sec == func->sec && insn->offset >= func->offset; \
114 insn = list_prev_entry(insn, list))
115
109#define sec_for_each_insn_from(file, insn) \ 116#define sec_for_each_insn_from(file, insn) \
110 for (; insn; insn = next_insn_same_sec(file, insn)) 117 for (; insn; insn = next_insn_same_sec(file, insn))
111 118
@@ -122,10 +129,14 @@ static bool ignore_func(struct objtool_file *file, struct symbol *func)
122 129
123 /* check for STACK_FRAME_NON_STANDARD */ 130 /* check for STACK_FRAME_NON_STANDARD */
124 if (file->whitelist && file->whitelist->rela) 131 if (file->whitelist && file->whitelist->rela)
125 list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) 132 list_for_each_entry(rela, &file->whitelist->rela->rela_list, list) {
126 if (rela->sym->sec == func->sec && 133 if (rela->sym->type == STT_SECTION &&
134 rela->sym->sec == func->sec &&
127 rela->addend == func->offset) 135 rela->addend == func->offset)
128 return true; 136 return true;
137 if (rela->sym->type == STT_FUNC && rela->sym == func)
138 return true;
139 }
129 140
130 /* check if it has a context switching instruction */ 141 /* check if it has a context switching instruction */
131 func_for_each_insn(file, func, insn) 142 func_for_each_insn(file, func, insn)
@@ -164,6 +175,7 @@ static int __dead_end_function(struct objtool_file *file, struct symbol *func,
164 "__stack_chk_fail", 175 "__stack_chk_fail",
165 "panic", 176 "panic",
166 "do_exit", 177 "do_exit",
178 "do_task_dead",
167 "__module_put_and_exit", 179 "__module_put_and_exit",
168 "complete_and_exit", 180 "complete_and_exit",
169 "kvm_spurious_fault", 181 "kvm_spurious_fault",
@@ -659,65 +671,95 @@ static int add_switch_table(struct objtool_file *file, struct symbol *func,
659 return 0; 671 return 0;
660} 672}
661 673
662static int add_func_switch_tables(struct objtool_file *file, 674/*
663 struct symbol *func) 675 * find_switch_table() - Given a dynamic jump, find the switch jump table in
676 * .rodata associated with it.
677 *
678 * There are 3 basic patterns:
679 *
680 * 1. jmpq *[rodata addr](,%reg,8)
681 *
682 * This is the most common case by far. It jumps to an address in a simple
683 * jump table which is stored in .rodata.
684 *
685 * 2. jmpq *[rodata addr](%rip)
686 *
687 * This is caused by a rare GCC quirk, currently only seen in three driver
688 * functions in the kernel, only with certain obscure non-distro configs.
689 *
690 * As part of an optimization, GCC makes a copy of an existing switch jump
691 * table, modifies it, and then hard-codes the jump (albeit with an indirect
692 * jump) to use a single entry in the table. The rest of the jump table and
693 * some of its jump targets remain as dead code.
694 *
695 * In such a case we can just crudely ignore all unreachable instruction
696 * warnings for the entire object file. Ideally we would just ignore them
697 * for the function, but that would require redesigning the code quite a
698 * bit. And honestly that's just not worth doing: unreachable instruction
699 * warnings are of questionable value anyway, and this is such a rare issue.
700 *
701 * 3. mov [rodata addr],%reg1
702 * ... some instructions ...
703 * jmpq *(%reg1,%reg2,8)
704 *
705 * This is a fairly uncommon pattern which is new for GCC 6. As of this
706 * writing, there are 11 occurrences of it in the allmodconfig kernel.
707 *
708 * TODO: Once we have DWARF CFI and smarter instruction decoding logic,
709 * ensure the same register is used in the mov and jump instructions.
710 */
711static struct rela *find_switch_table(struct objtool_file *file,
712 struct symbol *func,
713 struct instruction *insn)
664{ 714{
665 struct instruction *insn, *prev_jump; 715 struct rela *text_rela, *rodata_rela;
666 struct rela *text_rela, *rodata_rela, *prev_rela;
667 int ret;
668 716
669 prev_jump = NULL; 717 text_rela = find_rela_by_dest_range(insn->sec, insn->offset, insn->len);
718 if (text_rela && text_rela->sym == file->rodata->sym) {
719 /* case 1 */
720 rodata_rela = find_rela_by_dest(file->rodata,
721 text_rela->addend);
722 if (rodata_rela)
723 return rodata_rela;
670 724
671 func_for_each_insn(file, func, insn) { 725 /* case 2 */
672 if (insn->type != INSN_JUMP_DYNAMIC) 726 rodata_rela = find_rela_by_dest(file->rodata,
673 continue; 727 text_rela->addend + 4);
728 if (!rodata_rela)
729 return NULL;
730 file->ignore_unreachables = true;
731 return rodata_rela;
732 }
733
734 /* case 3 */
735 func_for_each_insn_continue_reverse(file, func, insn) {
736 if (insn->type == INSN_JUMP_UNCONDITIONAL ||
737 insn->type == INSN_JUMP_DYNAMIC)
738 break;
674 739
675 text_rela = find_rela_by_dest_range(insn->sec, insn->offset, 740 text_rela = find_rela_by_dest_range(insn->sec, insn->offset,
676 insn->len); 741 insn->len);
677 if (!text_rela || text_rela->sym != file->rodata->sym) 742 if (text_rela && text_rela->sym == file->rodata->sym)
678 continue; 743 return find_rela_by_dest(file->rodata,
744 text_rela->addend);
745 }
679 746
680 /* common case: jmpq *[addr](,%rax,8) */ 747 return NULL;
681 rodata_rela = find_rela_by_dest(file->rodata, 748}
682 text_rela->addend);
683 749
684 /* 750static int add_func_switch_tables(struct objtool_file *file,
685 * rare case: jmpq *[addr](%rip) 751 struct symbol *func)
686 * 752{
687 * This check is for a rare gcc quirk, currently only seen in 753 struct instruction *insn, *prev_jump = NULL;
688 * three driver functions in the kernel, only with certain 754 struct rela *rela, *prev_rela = NULL;
689 * obscure non-distro configs. 755 int ret;
690 *
691 * As part of an optimization, gcc makes a copy of an existing
692 * switch jump table, modifies it, and then hard-codes the jump
693 * (albeit with an indirect jump) to use a single entry in the
694 * table. The rest of the jump table and some of its jump
695 * targets remain as dead code.
696 *
697 * In such a case we can just crudely ignore all unreachable
698 * instruction warnings for the entire object file. Ideally we
699 * would just ignore them for the function, but that would
700 * require redesigning the code quite a bit. And honestly
701 * that's just not worth doing: unreachable instruction
702 * warnings are of questionable value anyway, and this is such
703 * a rare issue.
704 *
705 * kbuild reports:
706 * - https://lkml.kernel.org/r/201603231906.LWcVUpxm%25fengguang.wu@intel.com
707 * - https://lkml.kernel.org/r/201603271114.K9i45biy%25fengguang.wu@intel.com
708 * - https://lkml.kernel.org/r/201603291058.zuJ6ben1%25fengguang.wu@intel.com
709 *
710 * gcc bug:
711 * - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70604
712 */
713 if (!rodata_rela) {
714 rodata_rela = find_rela_by_dest(file->rodata,
715 text_rela->addend + 4);
716 if (rodata_rela)
717 file->ignore_unreachables = true;
718 }
719 756
720 if (!rodata_rela) 757 func_for_each_insn(file, func, insn) {
758 if (insn->type != INSN_JUMP_DYNAMIC)
759 continue;
760
761 rela = find_switch_table(file, func, insn);
762 if (!rela)
721 continue; 763 continue;
722 764
723 /* 765 /*
@@ -727,13 +769,13 @@ static int add_func_switch_tables(struct objtool_file *file,
727 */ 769 */
728 if (prev_jump) { 770 if (prev_jump) {
729 ret = add_switch_table(file, func, prev_jump, prev_rela, 771 ret = add_switch_table(file, func, prev_jump, prev_rela,
730 rodata_rela); 772 rela);
731 if (ret) 773 if (ret)
732 return ret; 774 return ret;
733 } 775 }
734 776
735 prev_jump = insn; 777 prev_jump = insn;
736 prev_rela = rodata_rela; 778 prev_rela = rela;
737 } 779 }
738 780
739 if (prev_jump) { 781 if (prev_jump) {
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index e11f6b69cce6..0d7983ac63ef 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -30,6 +30,13 @@
30#include "elf.h" 30#include "elf.h"
31#include "warn.h" 31#include "warn.h"
32 32
33/*
34 * Fallback for systems without this "read, mmaping if possible" cmd.
35 */
36#ifndef ELF_C_READ_MMAP
37#define ELF_C_READ_MMAP ELF_C_READ
38#endif
39
33struct section *find_section_by_name(struct elf *elf, const char *name) 40struct section *find_section_by_name(struct elf *elf, const char *name)
34{ 41{
35 struct section *sec; 42 struct section *sec;
diff --git a/tools/pcmcia/.gitignore b/tools/pcmcia/.gitignore
new file mode 100644
index 000000000000..53d081336757
--- /dev/null
+++ b/tools/pcmcia/.gitignore
@@ -0,0 +1 @@
crc32hash
diff --git a/tools/pcmcia/Makefile b/tools/pcmcia/Makefile
new file mode 100644
index 000000000000..81a7498c5cd9
--- /dev/null
+++ b/tools/pcmcia/Makefile
@@ -0,0 +1,9 @@
1CC := $(CROSS_COMPILE)gcc
2CFLAGS := -I../../usr/include
3
4PROGS := crc32hash
5
6all: $(PROGS)
7
8clean:
9 rm -fr $(PROGS)
diff --git a/tools/pcmcia/crc32hash.c b/tools/pcmcia/crc32hash.c
new file mode 100644
index 000000000000..44f8beea7260
--- /dev/null
+++ b/tools/pcmcia/crc32hash.c
@@ -0,0 +1,32 @@
1/* crc32hash.c - derived from linux/lib/crc32.c, GNU GPL v2 */
2/* Usage example:
3$ ./crc32hash "Dual Speed"
4*/
5
6#include <string.h>
7#include <stdio.h>
8#include <ctype.h>
9#include <stdlib.h>
10
11static unsigned int crc32(unsigned char const *p, unsigned int len)
12{
13 int i;
14 unsigned int crc = 0;
15 while (len--) {
16 crc ^= *p++;
17 for (i = 0; i < 8; i++)
18 crc = (crc >> 1) ^ ((crc & 1) ? 0xedb88320 : 0);
19 }
20 return crc;
21}
22
23int main(int argc, char **argv) {
24 unsigned int result;
25 if (argc != 2) {
26 printf("no string passed as argument\n");
27 return -1;
28 }
29 result = crc32((unsigned char const *)argv[1], strlen(argv[1]));
30 printf("0x%x\n", result);
31 return 0;
32}
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/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;
diff --git a/tools/power/acpi/Makefile.config b/tools/power/acpi/Makefile.config
index 552af68d5414..a538ff44b108 100644
--- a/tools/power/acpi/Makefile.config
+++ b/tools/power/acpi/Makefile.config
@@ -54,9 +54,10 @@ INSTALL_SCRIPT = ${INSTALL_PROGRAM}
54# to something more interesting, like "arm-linux-". If you want 54# to something more interesting, like "arm-linux-". If you want
55# to compile vs uClibc, that can be done here as well. 55# to compile vs uClibc, that can be done here as well.
56CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc- 56CROSS = #/usr/i386-linux-uclibc/usr/bin/i386-uclibc-
57CC = $(CROSS)gcc 57CROSS_COMPILE ?= $(CROSS)
58LD = $(CROSS)gcc 58CC = $(CROSS_COMPILE)gcc
59STRIP = $(CROSS)strip 59LD = $(CROSS_COMPILE)gcc
60STRIP = $(CROSS_COMPILE)strip
60HOSTCC = gcc 61HOSTCC = gcc
61 62
62# check if compiler option is supported 63# check if compiler option is supported
diff --git a/tools/power/acpi/common/cmfsize.c b/tools/power/acpi/common/cmfsize.c
index e73a79fce015..bc82596d7354 100644
--- a/tools/power/acpi/common/cmfsize.c
+++ b/tools/power/acpi/common/cmfsize.c
@@ -44,7 +44,6 @@
44#include <acpi/acpi.h> 44#include <acpi/acpi.h>
45#include "accommon.h" 45#include "accommon.h"
46#include "acapps.h" 46#include "acapps.h"
47#include <stdio.h>
48 47
49#define _COMPONENT ACPI_TOOLS 48#define _COMPONENT ACPI_TOOLS
50ACPI_MODULE_NAME("cmfsize") 49ACPI_MODULE_NAME("cmfsize")
@@ -69,24 +68,24 @@ u32 cm_get_file_size(ACPI_FILE file)
69 68
70 /* Save the current file pointer, seek to EOF to obtain file size */ 69 /* Save the current file pointer, seek to EOF to obtain file size */
71 70
72 current_offset = acpi_os_get_file_offset(file); 71 current_offset = ftell(file);
73 if (current_offset < 0) { 72 if (current_offset < 0) {
74 goto offset_error; 73 goto offset_error;
75 } 74 }
76 75
77 status = acpi_os_set_file_offset(file, 0, ACPI_FILE_END); 76 status = fseek(file, 0, SEEK_END);
78 if (ACPI_FAILURE(status)) { 77 if (ACPI_FAILURE(status)) {
79 goto seek_error; 78 goto seek_error;
80 } 79 }
81 80
82 file_size = acpi_os_get_file_offset(file); 81 file_size = ftell(file);
83 if (file_size < 0) { 82 if (file_size < 0) {
84 goto offset_error; 83 goto offset_error;
85 } 84 }
86 85
87 /* Restore original file pointer */ 86 /* Restore original file pointer */
88 87
89 status = acpi_os_set_file_offset(file, current_offset, ACPI_FILE_BEGIN); 88 status = fseek(file, current_offset, SEEK_SET);
90 if (ACPI_FAILURE(status)) { 89 if (ACPI_FAILURE(status)) {
91 goto seek_error; 90 goto seek_error;
92 } 91 }
@@ -94,10 +93,10 @@ u32 cm_get_file_size(ACPI_FILE file)
94 return ((u32)file_size); 93 return ((u32)file_size);
95 94
96offset_error: 95offset_error:
97 acpi_log_error("Could not get file offset"); 96 fprintf(stderr, "Could not get file offset\n");
98 return (ACPI_UINT32_MAX); 97 return (ACPI_UINT32_MAX);
99 98
100seek_error: 99seek_error:
101 acpi_log_error("Could not set file offset"); 100 fprintf(stderr, "Could not set file offset\n");
102 return (ACPI_UINT32_MAX); 101 return (ACPI_UINT32_MAX);
103} 102}
diff --git a/tools/power/acpi/common/getopt.c b/tools/power/acpi/common/getopt.c
index 0bd343f136a4..3919970f5aea 100644
--- a/tools/power/acpi/common/getopt.c
+++ b/tools/power/acpi/common/getopt.c
@@ -57,7 +57,7 @@
57#include "acapps.h" 57#include "acapps.h"
58 58
59#define ACPI_OPTION_ERROR(msg, badchar) \ 59#define ACPI_OPTION_ERROR(msg, badchar) \
60 if (acpi_gbl_opterr) {acpi_log_error ("%s%c\n", msg, badchar);} 60 if (acpi_gbl_opterr) {fprintf (stderr, "%s%c\n", msg, badchar);}
61 61
62int acpi_gbl_opterr = 1; 62int acpi_gbl_opterr = 1;
63int acpi_gbl_optind = 1; 63int acpi_gbl_optind = 1;
@@ -94,7 +94,7 @@ int acpi_getopt_argument(int argc, char **argv)
94 acpi_gbl_optarg = 94 acpi_gbl_optarg =
95 &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)]; 95 &argv[acpi_gbl_optind++][(int)(current_char_ptr + 1)];
96 } else if (++acpi_gbl_optind >= argc) { 96 } else if (++acpi_gbl_optind >= argc) {
97 ACPI_OPTION_ERROR("Option requires an argument: -", 'v'); 97 ACPI_OPTION_ERROR("\nOption requires an argument", 0);
98 98
99 current_char_ptr = 1; 99 current_char_ptr = 1;
100 return (-1); 100 return (-1);
diff --git a/tools/power/acpi/os_specific/service_layers/oslibcfs.c b/tools/power/acpi/os_specific/service_layers/oslibcfs.c
deleted file mode 100644
index 11f4aba55aab..000000000000
--- a/tools/power/acpi/os_specific/service_layers/oslibcfs.c
+++ /dev/null
@@ -1,217 +0,0 @@
1/******************************************************************************
2 *
3 * Module Name: oslibcfs - C library OSL for file I/O
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2016, Intel Corp.
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include <acpi/acpi.h>
45#include <stdio.h>
46#include <stdarg.h>
47
48#define _COMPONENT ACPI_OS_SERVICES
49ACPI_MODULE_NAME("oslibcfs")
50
51/*******************************************************************************
52 *
53 * FUNCTION: acpi_os_open_file
54 *
55 * PARAMETERS: path - File path
56 * modes - File operation type
57 *
58 * RETURN: File descriptor.
59 *
60 * DESCRIPTION: Open a file for reading (ACPI_FILE_READING) or/and writing
61 * (ACPI_FILE_WRITING).
62 *
63 ******************************************************************************/
64ACPI_FILE acpi_os_open_file(const char *path, u8 modes)
65{
66 ACPI_FILE file;
67 u32 i = 0;
68 char modes_str[4];
69
70 if (modes & ACPI_FILE_READING) {
71 modes_str[i++] = 'r';
72 }
73 if (modes & ACPI_FILE_WRITING) {
74 modes_str[i++] = 'w';
75 }
76
77 if (modes & ACPI_FILE_BINARY) {
78 modes_str[i++] = 'b';
79 }
80
81 modes_str[i++] = '\0';
82
83 file = fopen(path, modes_str);
84 if (!file) {
85 perror("Could not open file");
86 }
87
88 return (file);
89}
90
91/*******************************************************************************
92 *
93 * FUNCTION: acpi_os_close_file
94 *
95 * PARAMETERS: file - An open file descriptor
96 *
97 * RETURN: None.
98 *
99 * DESCRIPTION: Close a file opened via acpi_os_open_file.
100 *
101 ******************************************************************************/
102
103void acpi_os_close_file(ACPI_FILE file)
104{
105
106 fclose(file);
107}
108
109/*******************************************************************************
110 *
111 * FUNCTION: acpi_os_read_file
112 *
113 * PARAMETERS: file - An open file descriptor
114 * buffer - Data buffer
115 * size - Data block size
116 * count - Number of data blocks
117 *
118 * RETURN: Number of bytes actually read.
119 *
120 * DESCRIPTION: Read from a file.
121 *
122 ******************************************************************************/
123
124int
125acpi_os_read_file(ACPI_FILE file, void *buffer, acpi_size size, acpi_size count)
126{
127 int length;
128
129 length = fread(buffer, size, count, file);
130 if (length < 0) {
131 perror("Error reading file");
132 }
133
134 return (length);
135}
136
137/*******************************************************************************
138 *
139 * FUNCTION: acpi_os_write_file
140 *
141 * PARAMETERS: file - An open file descriptor
142 * buffer - Data buffer
143 * size - Data block size
144 * count - Number of data blocks
145 *
146 * RETURN: Number of bytes actually written.
147 *
148 * DESCRIPTION: Write to a file.
149 *
150 ******************************************************************************/
151
152int
153acpi_os_write_file(ACPI_FILE file,
154 void *buffer, acpi_size size, acpi_size count)
155{
156 int length;
157
158 length = fwrite(buffer, size, count, file);
159 if (length < 0) {
160 perror("Error writing file");
161 }
162
163 return (length);
164}
165
166/*******************************************************************************
167 *
168 * FUNCTION: acpi_os_get_file_offset
169 *
170 * PARAMETERS: file - An open file descriptor
171 *
172 * RETURN: Current file pointer position.
173 *
174 * DESCRIPTION: Get current file offset.
175 *
176 ******************************************************************************/
177
178long acpi_os_get_file_offset(ACPI_FILE file)
179{
180 long offset;
181
182 offset = ftell(file);
183 return (offset);
184}
185
186/*******************************************************************************
187 *
188 * FUNCTION: acpi_os_set_file_offset
189 *
190 * PARAMETERS: file - An open file descriptor
191 * offset - New file offset
192 * from - From begin/end of file
193 *
194 * RETURN: Status
195 *
196 * DESCRIPTION: Set current file offset.
197 *
198 ******************************************************************************/
199
200acpi_status acpi_os_set_file_offset(ACPI_FILE file, long offset, u8 from)
201{
202 int ret = 0;
203
204 if (from == ACPI_FILE_BEGIN) {
205 ret = fseek(file, offset, SEEK_SET);
206 }
207
208 if (from == ACPI_FILE_END) {
209 ret = fseek(file, offset, SEEK_END);
210 }
211
212 if (ret < 0) {
213 return (AE_ERROR);
214 } else {
215 return (AE_OK);
216 }
217}
diff --git a/tools/power/acpi/os_specific/service_layers/osunixxf.c b/tools/power/acpi/os_specific/service_layers/osunixxf.c
index 88aa66ef4ad5..8d8003c919d4 100644
--- a/tools/power/acpi/os_specific/service_layers/osunixxf.c
+++ b/tools/power/acpi/os_specific/service_layers/osunixxf.c
@@ -63,10 +63,7 @@
63#define _COMPONENT ACPI_OS_SERVICES 63#define _COMPONENT ACPI_OS_SERVICES
64ACPI_MODULE_NAME("osunixxf") 64ACPI_MODULE_NAME("osunixxf")
65 65
66u8 acpi_gbl_debug_timeout = FALSE;
67
68/* Upcalls to acpi_exec */ 66/* Upcalls to acpi_exec */
69
70void 67void
71ae_table_override(struct acpi_table_header *existing_table, 68ae_table_override(struct acpi_table_header *existing_table,
72 struct acpi_table_header **new_table); 69 struct acpi_table_header **new_table);
diff --git a/tools/power/acpi/tools/acpidump/Makefile b/tools/power/acpi/tools/acpidump/Makefile
index 2942cdced2ad..04b5db7c7c0b 100644
--- a/tools/power/acpi/tools/acpidump/Makefile
+++ b/tools/power/acpi/tools/acpidump/Makefile
@@ -36,12 +36,13 @@ TOOL_OBJS = \
36 utdebug.o\ 36 utdebug.o\
37 utexcep.o\ 37 utexcep.o\
38 utglobal.o\ 38 utglobal.o\
39 uthex.o\
39 utmath.o\ 40 utmath.o\
40 utnonansi.o\ 41 utnonansi.o\
41 utprint.o\ 42 utprint.o\
42 utstring.o\ 43 utstring.o\
44 utstrtoul64.o\
43 utxferror.o\ 45 utxferror.o\
44 oslibcfs.o\
45 oslinuxtbl.o\ 46 oslinuxtbl.o\
46 cmfsize.o\ 47 cmfsize.o\
47 getopt.o 48 getopt.o
diff --git a/tools/power/acpi/tools/acpidump/acpidump.h b/tools/power/acpi/tools/acpidump/acpidump.h
index 025c232e920d..00423fc45e7c 100644
--- a/tools/power/acpi/tools/acpidump/acpidump.h
+++ b/tools/power/acpi/tools/acpidump/acpidump.h
@@ -55,11 +55,7 @@
55#include <acpi/acpi.h> 55#include <acpi/acpi.h>
56#include "accommon.h" 56#include "accommon.h"
57#include "actables.h" 57#include "actables.h"
58 58#include "acapps.h"
59#include <stdio.h>
60#include <fcntl.h>
61#include <errno.h>
62#include <sys/stat.h>
63 59
64/* Globals */ 60/* Globals */
65 61
@@ -72,12 +68,6 @@ EXTERN ACPI_FILE INIT_GLOBAL(gbl_output_file, NULL);
72EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL); 68EXTERN char INIT_GLOBAL(*gbl_output_filename, NULL);
73EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0); 69EXTERN u64 INIT_GLOBAL(gbl_rsdp_base, 0);
74 70
75/* Globals required for use with ACPICA modules */
76
77#ifdef _DECLARE_GLOBALS
78u8 acpi_gbl_integer_byte_width = 8;
79#endif
80
81/* Action table used to defer requested options */ 71/* Action table used to defer requested options */
82 72
83struct ap_dump_action { 73struct ap_dump_action {
diff --git a/tools/power/acpi/tools/acpidump/apdump.c b/tools/power/acpi/tools/acpidump/apdump.c
index fb8f1d9e3b1b..9031be1afe63 100644
--- a/tools/power/acpi/tools/acpidump/apdump.c
+++ b/tools/power/acpi/tools/acpidump/apdump.c
@@ -69,16 +69,17 @@ u8 ap_is_valid_header(struct acpi_table_header *table)
69 /* Make sure signature is all ASCII and a valid ACPI name */ 69 /* Make sure signature is all ASCII and a valid ACPI name */
70 70
71 if (!acpi_ut_valid_nameseg(table->signature)) { 71 if (!acpi_ut_valid_nameseg(table->signature)) {
72 acpi_log_error("Table signature (0x%8.8X) is invalid\n", 72 fprintf(stderr,
73 *(u32 *)table->signature); 73 "Table signature (0x%8.8X) is invalid\n",
74 *(u32 *)table->signature);
74 return (FALSE); 75 return (FALSE);
75 } 76 }
76 77
77 /* Check for minimum table length */ 78 /* Check for minimum table length */
78 79
79 if (table->length < sizeof(struct acpi_table_header)) { 80 if (table->length < sizeof(struct acpi_table_header)) {
80 acpi_log_error("Table length (0x%8.8X) is invalid\n", 81 fprintf(stderr, "Table length (0x%8.8X) is invalid\n",
81 table->length); 82 table->length);
82 return (FALSE); 83 return (FALSE);
83 } 84 }
84 } 85 }
@@ -115,8 +116,8 @@ u8 ap_is_valid_checksum(struct acpi_table_header *table)
115 } 116 }
116 117
117 if (ACPI_FAILURE(status)) { 118 if (ACPI_FAILURE(status)) {
118 acpi_log_error("%4.4s: Warning: wrong checksum in table\n", 119 fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n",
119 table->signature); 120 table->signature);
120 } 121 }
121 122
122 return (AE_OK); 123 return (AE_OK);
@@ -195,13 +196,13 @@ ap_dump_table_buffer(struct acpi_table_header *table,
195 * Note: simplest to just always emit a 64-bit address. acpi_xtract 196 * Note: simplest to just always emit a 64-bit address. acpi_xtract
196 * utility can handle this. 197 * utility can handle this.
197 */ 198 */
198 acpi_ut_file_printf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n", 199 fprintf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n",
199 table->signature, ACPI_FORMAT_UINT64(address)); 200 table->signature, ACPI_FORMAT_UINT64(address));
200 201
201 acpi_ut_dump_buffer_to_file(gbl_output_file, 202 acpi_ut_dump_buffer_to_file(gbl_output_file,
202 ACPI_CAST_PTR(u8, table), table_length, 203 ACPI_CAST_PTR(u8, table), table_length,
203 DB_BYTE_DISPLAY, 0); 204 DB_BYTE_DISPLAY, 0);
204 acpi_ut_file_printf(gbl_output_file, "\n"); 205 fprintf(gbl_output_file, "\n");
205 return (0); 206 return (0);
206} 207}
207 208
@@ -239,14 +240,14 @@ int ap_dump_all_tables(void)
239 if (status == AE_LIMIT) { 240 if (status == AE_LIMIT) {
240 return (0); 241 return (0);
241 } else if (i == 0) { 242 } else if (i == 0) {
242 acpi_log_error 243 fprintf(stderr,
243 ("Could not get ACPI tables, %s\n", 244 "Could not get ACPI tables, %s\n",
244 acpi_format_exception(status)); 245 acpi_format_exception(status));
245 return (-1); 246 return (-1);
246 } else { 247 } else {
247 acpi_log_error 248 fprintf(stderr,
248 ("Could not get ACPI table at index %u, %s\n", 249 "Could not get ACPI table at index %u, %s\n",
249 i, acpi_format_exception(status)); 250 i, acpi_format_exception(status));
250 continue; 251 continue;
251 } 252 }
252 } 253 }
@@ -286,20 +287,20 @@ int ap_dump_table_by_address(char *ascii_address)
286 287
287 /* Convert argument to an integer physical address */ 288 /* Convert argument to an integer physical address */
288 289
289 status = acpi_ut_strtoul64(ascii_address, ACPI_ANY_BASE, 290 status = acpi_ut_strtoul64(ascii_address, ACPI_STRTOUL_64BIT,
290 ACPI_MAX64_BYTE_WIDTH, &long_address); 291 &long_address);
291 if (ACPI_FAILURE(status)) { 292 if (ACPI_FAILURE(status)) {
292 acpi_log_error("%s: Could not convert to a physical address\n", 293 fprintf(stderr, "%s: Could not convert to a physical address\n",
293 ascii_address); 294 ascii_address);
294 return (-1); 295 return (-1);
295 } 296 }
296 297
297 address = (acpi_physical_address)long_address; 298 address = (acpi_physical_address)long_address;
298 status = acpi_os_get_table_by_address(address, &table); 299 status = acpi_os_get_table_by_address(address, &table);
299 if (ACPI_FAILURE(status)) { 300 if (ACPI_FAILURE(status)) {
300 acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n", 301 fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n",
301 ACPI_FORMAT_UINT64(address), 302 ACPI_FORMAT_UINT64(address),
302 acpi_format_exception(status)); 303 acpi_format_exception(status));
303 return (-1); 304 return (-1);
304 } 305 }
305 306
@@ -331,9 +332,9 @@ int ap_dump_table_by_name(char *signature)
331 int table_status; 332 int table_status;
332 333
333 if (strlen(signature) != ACPI_NAME_SIZE) { 334 if (strlen(signature) != ACPI_NAME_SIZE) {
334 acpi_log_error 335 fprintf(stderr,
335 ("Invalid table signature [%s]: must be exactly 4 characters\n", 336 "Invalid table signature [%s]: must be exactly 4 characters\n",
336 signature); 337 signature);
337 return (-1); 338 return (-1);
338 } 339 }
339 340
@@ -363,9 +364,9 @@ int ap_dump_table_by_name(char *signature)
363 return (0); 364 return (0);
364 } 365 }
365 366
366 acpi_log_error 367 fprintf(stderr,
367 ("Could not get ACPI table with signature [%s], %s\n", 368 "Could not get ACPI table with signature [%s], %s\n",
368 local_signature, acpi_format_exception(status)); 369 local_signature, acpi_format_exception(status));
369 return (-1); 370 return (-1);
370 } 371 }
371 372
@@ -408,24 +409,24 @@ int ap_dump_table_from_file(char *pathname)
408 } 409 }
409 410
410 if (!acpi_ut_valid_nameseg(table->signature)) { 411 if (!acpi_ut_valid_nameseg(table->signature)) {
411 acpi_log_error 412 fprintf(stderr,
412 ("No valid ACPI signature was found in input file %s\n", 413 "No valid ACPI signature was found in input file %s\n",
413 pathname); 414 pathname);
414 } 415 }
415 416
416 /* File must be at least as long as the table length */ 417 /* File must be at least as long as the table length */
417 418
418 if (table->length > file_size) { 419 if (table->length > file_size) {
419 acpi_log_error 420 fprintf(stderr,
420 ("Table length (0x%X) is too large for input file (0x%X) %s\n", 421 "Table length (0x%X) is too large for input file (0x%X) %s\n",
421 table->length, file_size, pathname); 422 table->length, file_size, pathname);
422 goto exit; 423 goto exit;
423 } 424 }
424 425
425 if (gbl_verbose_mode) { 426 if (gbl_verbose_mode) {
426 acpi_log_error 427 fprintf(stderr,
427 ("Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n", 428 "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n",
428 pathname, table->signature, file_size, file_size); 429 pathname, table->signature, file_size, file_size);
429 } 430 }
430 431
431 table_status = ap_dump_table_buffer(table, 0, 0); 432 table_status = ap_dump_table_buffer(table, 0, 0);
diff --git a/tools/power/acpi/tools/acpidump/apfiles.c b/tools/power/acpi/tools/acpidump/apfiles.c
index 5fcd9700ac18..dd5b861dc4a8 100644
--- a/tools/power/acpi/tools/acpidump/apfiles.c
+++ b/tools/power/acpi/tools/acpidump/apfiles.c
@@ -42,7 +42,6 @@
42 */ 42 */
43 43
44#include "acpidump.h" 44#include "acpidump.h"
45#include "acapps.h"
46 45
47/* Local prototypes */ 46/* Local prototypes */
48 47
@@ -66,7 +65,8 @@ static int ap_is_existing_file(char *pathname)
66 struct stat stat_info; 65 struct stat stat_info;
67 66
68 if (!stat(pathname, &stat_info)) { 67 if (!stat(pathname, &stat_info)) {
69 acpi_log_error("Target path already exists, overwrite? [y|n] "); 68 fprintf(stderr,
69 "Target path already exists, overwrite? [y|n] ");
70 70
71 if (getchar() != 'y') { 71 if (getchar() != 'y') {
72 return (-1); 72 return (-1);
@@ -102,9 +102,9 @@ int ap_open_output_file(char *pathname)
102 102
103 /* Point stdout to the file */ 103 /* Point stdout to the file */
104 104
105 file = acpi_os_open_file(pathname, ACPI_FILE_WRITING); 105 file = fopen(pathname, "w");
106 if (!file) { 106 if (!file) {
107 acpi_log_error("Could not open output file: %s\n", pathname); 107 fprintf(stderr, "Could not open output file: %s\n", pathname);
108 return (-1); 108 return (-1);
109 } 109 }
110 110
@@ -134,7 +134,7 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
134 char filename[ACPI_NAME_SIZE + 16]; 134 char filename[ACPI_NAME_SIZE + 16];
135 char instance_str[16]; 135 char instance_str[16];
136 ACPI_FILE file; 136 ACPI_FILE file;
137 size_t actual; 137 acpi_size actual;
138 u32 table_length; 138 u32 table_length;
139 139
140 /* Obtain table length */ 140 /* Obtain table length */
@@ -158,37 +158,36 @@ int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance)
158 /* Handle multiple SSDts - create different filenames for each */ 158 /* Handle multiple SSDts - create different filenames for each */
159 159
160 if (instance > 0) { 160 if (instance > 0) {
161 acpi_ut_snprintf(instance_str, sizeof(instance_str), "%u", 161 snprintf(instance_str, sizeof(instance_str), "%u", instance);
162 instance);
163 strcat(filename, instance_str); 162 strcat(filename, instance_str);
164 } 163 }
165 164
166 strcat(filename, FILE_SUFFIX_BINARY_TABLE); 165 strcat(filename, FILE_SUFFIX_BINARY_TABLE);
167 166
168 if (gbl_verbose_mode) { 167 if (gbl_verbose_mode) {
169 acpi_log_error 168 fprintf(stderr,
170 ("Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n", 169 "Writing [%4.4s] to binary file: %s 0x%X (%u) bytes\n",
171 table->signature, filename, table->length, table->length); 170 table->signature, filename, table->length,
171 table->length);
172 } 172 }
173 173
174 /* Open the file and dump the entire table in binary mode */ 174 /* Open the file and dump the entire table in binary mode */
175 175
176 file = acpi_os_open_file(filename, 176 file = fopen(filename, "wb");
177 ACPI_FILE_WRITING | ACPI_FILE_BINARY);
178 if (!file) { 177 if (!file) {
179 acpi_log_error("Could not open output file: %s\n", filename); 178 fprintf(stderr, "Could not open output file: %s\n", filename);
180 return (-1); 179 return (-1);
181 } 180 }
182 181
183 actual = acpi_os_write_file(file, table, 1, table_length); 182 actual = fwrite(table, 1, table_length, file);
184 if (actual != table_length) { 183 if (actual != table_length) {
185 acpi_log_error("Error writing binary output file: %s\n", 184 fprintf(stderr, "Error writing binary output file: %s\n",
186 filename); 185 filename);
187 acpi_os_close_file(file); 186 fclose(file);
188 return (-1); 187 return (-1);
189 } 188 }
190 189
191 acpi_os_close_file(file); 190 fclose(file);
192 return (0); 191 return (0);
193} 192}
194 193
@@ -211,14 +210,13 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
211 struct acpi_table_header *buffer = NULL; 210 struct acpi_table_header *buffer = NULL;
212 ACPI_FILE file; 211 ACPI_FILE file;
213 u32 file_size; 212 u32 file_size;
214 size_t actual; 213 acpi_size actual;
215 214
216 /* Must use binary mode */ 215 /* Must use binary mode */
217 216
218 file = 217 file = fopen(pathname, "rb");
219 acpi_os_open_file(pathname, ACPI_FILE_READING | ACPI_FILE_BINARY);
220 if (!file) { 218 if (!file) {
221 acpi_log_error("Could not open input file: %s\n", pathname); 219 fprintf(stderr, "Could not open input file: %s\n", pathname);
222 return (NULL); 220 return (NULL);
223 } 221 }
224 222
@@ -226,7 +224,8 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
226 224
227 file_size = cm_get_file_size(file); 225 file_size = cm_get_file_size(file);
228 if (file_size == ACPI_UINT32_MAX) { 226 if (file_size == ACPI_UINT32_MAX) {
229 acpi_log_error("Could not get input file size: %s\n", pathname); 227 fprintf(stderr,
228 "Could not get input file size: %s\n", pathname);
230 goto cleanup; 229 goto cleanup;
231 } 230 }
232 231
@@ -234,16 +233,17 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
234 233
235 buffer = ACPI_ALLOCATE_ZEROED(file_size); 234 buffer = ACPI_ALLOCATE_ZEROED(file_size);
236 if (!buffer) { 235 if (!buffer) {
237 acpi_log_error("Could not allocate file buffer of size: %u\n", 236 fprintf(stderr,
238 file_size); 237 "Could not allocate file buffer of size: %u\n",
238 file_size);
239 goto cleanup; 239 goto cleanup;
240 } 240 }
241 241
242 /* Read the entire file */ 242 /* Read the entire file */
243 243
244 actual = acpi_os_read_file(file, buffer, 1, file_size); 244 actual = fread(buffer, 1, file_size, file);
245 if (actual != file_size) { 245 if (actual != file_size) {
246 acpi_log_error("Could not read input file: %s\n", pathname); 246 fprintf(stderr, "Could not read input file: %s\n", pathname);
247 ACPI_FREE(buffer); 247 ACPI_FREE(buffer);
248 buffer = NULL; 248 buffer = NULL;
249 goto cleanup; 249 goto cleanup;
@@ -252,6 +252,6 @@ struct acpi_table_header *ap_get_table_from_file(char *pathname,
252 *out_file_size = file_size; 252 *out_file_size = file_size;
253 253
254cleanup: 254cleanup:
255 acpi_os_close_file(file); 255 fclose(file);
256 return (buffer); 256 return (buffer);
257} 257}
diff --git a/tools/power/acpi/tools/acpidump/apmain.c b/tools/power/acpi/tools/acpidump/apmain.c
index 7692e6b887e1..7ff46be908f0 100644
--- a/tools/power/acpi/tools/acpidump/apmain.c
+++ b/tools/power/acpi/tools/acpidump/apmain.c
@@ -43,7 +43,6 @@
43 43
44#define _DECLARE_GLOBALS 44#define _DECLARE_GLOBALS
45#include "acpidump.h" 45#include "acpidump.h"
46#include "acapps.h"
47 46
48/* 47/*
49 * acpidump - A portable utility for obtaining system ACPI tables and dumping 48 * acpidump - A portable utility for obtaining system ACPI tables and dumping
@@ -140,8 +139,8 @@ static int ap_insert_action(char *argument, u32 to_be_done)
140 139
141 current_action++; 140 current_action++;
142 if (current_action > AP_MAX_ACTIONS) { 141 if (current_action > AP_MAX_ACTIONS) {
143 acpi_log_error("Too many table options (max %u)\n", 142 fprintf(stderr, "Too many table options (max %u)\n",
144 AP_MAX_ACTIONS); 143 AP_MAX_ACTIONS);
145 return (-1); 144 return (-1);
146 } 145 }
147 146
@@ -186,9 +185,9 @@ static int ap_do_options(int argc, char **argv)
186 } else if (!strcmp(acpi_gbl_optarg, "off")) { 185 } else if (!strcmp(acpi_gbl_optarg, "off")) {
187 gbl_dump_customized_tables = FALSE; 186 gbl_dump_customized_tables = FALSE;
188 } else { 187 } else {
189 acpi_log_error 188 fprintf(stderr,
190 ("%s: Cannot handle this switch, please use on|off\n", 189 "%s: Cannot handle this switch, please use on|off\n",
191 acpi_gbl_optarg); 190 acpi_gbl_optarg);
192 return (-1); 191 return (-1);
193 } 192 }
194 continue; 193 continue;
@@ -209,13 +208,13 @@ static int ap_do_options(int argc, char **argv)
209 case 'r': /* Dump tables from specified RSDP */ 208 case 'r': /* Dump tables from specified RSDP */
210 209
211 status = 210 status =
212 acpi_ut_strtoul64(acpi_gbl_optarg, ACPI_ANY_BASE, 211 acpi_ut_strtoul64(acpi_gbl_optarg,
213 ACPI_MAX64_BYTE_WIDTH, 212 ACPI_STRTOUL_64BIT,
214 &gbl_rsdp_base); 213 &gbl_rsdp_base);
215 if (ACPI_FAILURE(status)) { 214 if (ACPI_FAILURE(status)) {
216 acpi_log_error 215 fprintf(stderr,
217 ("%s: Could not convert to a physical address\n", 216 "%s: Could not convert to a physical address\n",
218 acpi_gbl_optarg); 217 acpi_gbl_optarg);
219 return (-1); 218 return (-1);
220 } 219 }
221 continue; 220 continue;
@@ -242,7 +241,7 @@ static int ap_do_options(int argc, char **argv)
242 case 'z': /* Verbose mode */ 241 case 'z': /* Verbose mode */
243 242
244 gbl_verbose_mode = TRUE; 243 gbl_verbose_mode = TRUE;
245 acpi_log_error(ACPI_COMMON_SIGNON(AP_UTILITY_NAME)); 244 fprintf(stderr, ACPI_COMMON_SIGNON(AP_UTILITY_NAME));
246 continue; 245 continue;
247 246
248 /* 247 /*
@@ -315,6 +314,7 @@ int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
315 ACPI_DEBUG_INITIALIZE(); /* For debug version only */ 314 ACPI_DEBUG_INITIALIZE(); /* For debug version only */
316 acpi_os_initialize(); 315 acpi_os_initialize();
317 gbl_output_file = ACPI_FILE_OUT; 316 gbl_output_file = ACPI_FILE_OUT;
317 acpi_gbl_integer_byte_width = 8;
318 318
319 /* Process command line options */ 319 /* Process command line options */
320 320
@@ -353,8 +353,9 @@ int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
353 353
354 default: 354 default:
355 355
356 acpi_log_error("Internal error, invalid action: 0x%X\n", 356 fprintf(stderr,
357 action->to_be_done); 357 "Internal error, invalid action: 0x%X\n",
358 action->to_be_done);
358 return (-1); 359 return (-1);
359 } 360 }
360 361
@@ -369,12 +370,12 @@ int ACPI_SYSTEM_XFACE acpi_main(int argc, char *argv[])
369 /* Summary for the output file */ 370 /* Summary for the output file */
370 371
371 file_size = cm_get_file_size(gbl_output_file); 372 file_size = cm_get_file_size(gbl_output_file);
372 acpi_log_error 373 fprintf(stderr,
373 ("Output file %s contains 0x%X (%u) bytes\n\n", 374 "Output file %s contains 0x%X (%u) bytes\n\n",
374 gbl_output_filename, file_size, file_size); 375 gbl_output_filename, file_size, file_size);
375 } 376 }
376 377
377 acpi_os_close_file(gbl_output_file); 378 fclose(gbl_output_file);
378 } 379 }
379 380
380 return (status); 381 return (status);
diff --git a/tools/power/x86/turbostat/Makefile b/tools/power/x86/turbostat/Makefile
index e367b1a85d70..8561e7ddca59 100644
--- a/tools/power/x86/turbostat/Makefile
+++ b/tools/power/x86/turbostat/Makefile
@@ -1,7 +1,7 @@
1CC = $(CROSS_COMPILE)gcc 1CC = $(CROSS_COMPILE)gcc
2BUILD_OUTPUT := $(CURDIR) 2BUILD_OUTPUT := $(CURDIR)
3PREFIX := /usr 3PREFIX ?= /usr
4DESTDIR := 4DESTDIR ?=
5 5
6ifeq ("$(origin O)", "command line") 6ifeq ("$(origin O)", "command line")
7 BUILD_OUTPUT := $(O) 7 BUILD_OUTPUT := $(O)
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 89a55d5e32f3..492e84fbebfa 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -123,7 +123,7 @@ cpu0: MSR_NHM_PLATFORM_INFO: 0x80838f3012300
12335 * 100 = 3500 MHz TSC frequency 12335 * 100 = 3500 MHz TSC frequency
124cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled) 124cpu0: MSR_IA32_POWER_CTL: 0x0004005d (C1E auto-promotion: DISabled)
125cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0) 125cpu0: MSR_NHM_SNB_PKG_CST_CFG_CTL: 0x1e000400 (UNdemote-C3, UNdemote-C1, demote-C3, demote-C1, UNlocked: pkg-cstate-limit=0: pc0)
126cpu0: MSR_NHM_TURBO_RATIO_LIMIT: 0x25262727 126cpu0: MSR_TURBO_RATIO_LIMIT: 0x25262727
12737 * 100 = 3700 MHz max turbo 4 active cores 12737 * 100 = 3700 MHz max turbo 4 active cores
12838 * 100 = 3800 MHz max turbo 3 active cores 12838 * 100 = 3800 MHz max turbo 3 active cores
12939 * 100 = 3900 MHz max turbo 2 active cores 12939 * 100 = 3900 MHz max turbo 2 active cores
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index acbf7ff2ee6e..3e199b508a96 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -1480,7 +1480,7 @@ dump_knl_turbo_ratio_limits(void)
1480 unsigned int cores[buckets_no]; 1480 unsigned int cores[buckets_no];
1481 unsigned int ratio[buckets_no]; 1481 unsigned int ratio[buckets_no];
1482 1482
1483 get_msr(base_cpu, MSR_NHM_TURBO_RATIO_LIMIT, &msr); 1483 get_msr(base_cpu, MSR_TURBO_RATIO_LIMIT, &msr);
1484 1484
1485 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n", 1485 fprintf(outf, "cpu%d: MSR_TURBO_RATIO_LIMIT: 0x%08llx\n",
1486 base_cpu, msr); 1486 base_cpu, msr);
diff --git a/tools/scripts/Makefile.arch b/tools/scripts/Makefile.arch
index e11fbd6fae78..ad85b921a607 100644
--- a/tools/scripts/Makefile.arch
+++ b/tools/scripts/Makefile.arch
@@ -1,8 +1,4 @@
1ifndef ARCH 1HOSTARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
2ARCH := $(shell uname -m 2>/dev/null || echo not)
3endif
4
5ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
6 -e s/sun4u/sparc/ -e s/sparc64/sparc/ \ 2 -e s/sun4u/sparc/ -e s/sparc64/sparc/ \
7 -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \ 3 -e /arm64/!s/arm.*/arm/ -e s/sa110/arm/ \
8 -e s/s390x/s390/ -e s/parisc64/parisc/ \ 4 -e s/s390x/s390/ -e s/parisc64/parisc/ \
@@ -10,6 +6,41 @@ ARCH := $(shell echo $(ARCH) | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
10 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \ 6 -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
11 -e s/tile.*/tile/ ) 7 -e s/tile.*/tile/ )
12 8
9ifndef ARCH
10ARCH := $(HOSTARCH)
11endif
12
13SRCARCH := $(ARCH)
14
15# Additional ARCH settings for x86
16ifeq ($(ARCH),i386)
17 SRCARCH := x86
18endif
19ifeq ($(ARCH),x86_64)
20 SRCARCH := x86
21endif
22
23# Additional ARCH settings for sparc
24ifeq ($(ARCH),sparc32)
25 SRCARCH := sparc
26endif
27ifeq ($(ARCH),sparc64)
28 SRCARCH := sparc
29endif
30
31# Additional ARCH settings for sh
32ifeq ($(ARCH),sh64)
33 SRCARCH := sh
34endif
35
36# Additional ARCH settings for tile
37ifeq ($(ARCH),tilepro)
38 SRCARCH := tile
39endif
40ifeq ($(ARCH),tilegx)
41 SRCARCH := tile
42endif
43
13LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1) 44LP64 := $(shell echo __LP64__ | ${CC} ${CFLAGS} -E -x c - | tail -n 1)
14ifeq ($(LP64), 1) 45ifeq ($(LP64), 1)
15 IS_64_BIT := 1 46 IS_64_BIT := 1
diff --git a/tools/spi/Makefile b/tools/spi/Makefile
index cd0db62e4d9d..3815b18ba070 100644
--- a/tools/spi/Makefile
+++ b/tools/spi/Makefile
@@ -1,3 +1,5 @@
1CC = $(CROSS_COMPILE)gcc
2
1all: spidev_test spidev_fdx 3all: spidev_test spidev_fdx
2 4
3clean: 5clean:
diff --git a/tools/spi/spidev_test.c b/tools/spi/spidev_test.c
index 8a73d8185316..f046b77cfefe 100644
--- a/tools/spi/spidev_test.c
+++ b/tools/spi/spidev_test.c
@@ -19,6 +19,7 @@
19#include <getopt.h> 19#include <getopt.h>
20#include <fcntl.h> 20#include <fcntl.h>
21#include <sys/ioctl.h> 21#include <sys/ioctl.h>
22#include <linux/ioctl.h>
22#include <sys/stat.h> 23#include <sys/stat.h>
23#include <linux/types.h> 24#include <linux/types.h>
24#include <linux/spi/spidev.h> 25#include <linux/spi/spidev.h>
@@ -284,7 +285,7 @@ static void parse_opts(int argc, char *argv[])
284 285
285static void transfer_escaped_string(int fd, char *str) 286static void transfer_escaped_string(int fd, char *str)
286{ 287{
287 size_t size = strlen(str + 1); 288 size_t size = strlen(str);
288 uint8_t *tx; 289 uint8_t *tx;
289 uint8_t *rx; 290 uint8_t *rx;
290 291
diff --git a/tools/testing/nvdimm/Kbuild b/tools/testing/nvdimm/Kbuild
index 785985677159..582db95127ed 100644
--- a/tools/testing/nvdimm/Kbuild
+++ b/tools/testing/nvdimm/Kbuild
@@ -11,12 +11,15 @@ ldflags-y += --wrap=__devm_release_region
11ldflags-y += --wrap=__request_region 11ldflags-y += --wrap=__request_region
12ldflags-y += --wrap=__release_region 12ldflags-y += --wrap=__release_region
13ldflags-y += --wrap=devm_memremap_pages 13ldflags-y += --wrap=devm_memremap_pages
14ldflags-y += --wrap=phys_to_pfn_t 14ldflags-y += --wrap=insert_resource
15ldflags-y += --wrap=remove_resource
16ldflags-y += --wrap=acpi_evaluate_object
15 17
16DRIVERS := ../../../drivers 18DRIVERS := ../../../drivers
17NVDIMM_SRC := $(DRIVERS)/nvdimm 19NVDIMM_SRC := $(DRIVERS)/nvdimm
18ACPI_SRC := $(DRIVERS)/acpi 20ACPI_SRC := $(DRIVERS)/acpi/nfit
19DAX_SRC := $(DRIVERS)/dax 21DAX_SRC := $(DRIVERS)/dax
22ccflags-y := -I$(src)/$(NVDIMM_SRC)/
20 23
21obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o 24obj-$(CONFIG_LIBNVDIMM) += libnvdimm.o
22obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o 25obj-$(CONFIG_BLK_DEV_PMEM) += nd_pmem.o
@@ -27,10 +30,12 @@ obj-$(CONFIG_ACPI_NFIT) += nfit.o
27obj-$(CONFIG_DEV_DAX) += dax.o 30obj-$(CONFIG_DEV_DAX) += dax.o
28obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o 31obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
29 32
30nfit-y := $(ACPI_SRC)/nfit.o 33nfit-y := $(ACPI_SRC)/core.o
34nfit-$(CONFIG_X86_MCE) += $(ACPI_SRC)/mce.o
31nfit-y += config_check.o 35nfit-y += config_check.o
32 36
33nd_pmem-y := $(NVDIMM_SRC)/pmem.o 37nd_pmem-y := $(NVDIMM_SRC)/pmem.o
38nd_pmem-y += pmem-dax.o
34nd_pmem-y += config_check.o 39nd_pmem-y += config_check.o
35 40
36nd_btt-y := $(NVDIMM_SRC)/btt.o 41nd_btt-y := $(NVDIMM_SRC)/btt.o
diff --git a/tools/testing/nvdimm/config_check.c b/tools/testing/nvdimm/config_check.c
index adf18bfeca00..7dc5a0af9b54 100644
--- a/tools/testing/nvdimm/config_check.c
+++ b/tools/testing/nvdimm/config_check.c
@@ -1,4 +1,3 @@
1#include <linux/kconfig.h>
2#include <linux/bug.h> 1#include <linux/bug.h>
3 2
4void check(void) 3void check(void)
@@ -10,6 +9,7 @@ void check(void)
10 BUILD_BUG_ON(!IS_MODULE(CONFIG_LIBNVDIMM)); 9 BUILD_BUG_ON(!IS_MODULE(CONFIG_LIBNVDIMM));
11 BUILD_BUG_ON(!IS_MODULE(CONFIG_BLK_DEV_PMEM)); 10 BUILD_BUG_ON(!IS_MODULE(CONFIG_BLK_DEV_PMEM));
12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT)); 11 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BTT));
12 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_PFN));
13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK)); 13 BUILD_BUG_ON(!IS_MODULE(CONFIG_ND_BLK));
14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT)); 14 BUILD_BUG_ON(!IS_MODULE(CONFIG_ACPI_NFIT));
15 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX)); 15 BUILD_BUG_ON(!IS_MODULE(CONFIG_DEV_DAX));
diff --git a/tools/testing/nvdimm/pmem-dax.c b/tools/testing/nvdimm/pmem-dax.c
new file mode 100644
index 000000000000..c9b8c48f85fc
--- /dev/null
+++ b/tools/testing/nvdimm/pmem-dax.c
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) 2014-2016, Intel Corporation.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13#include "test/nfit_test.h"
14#include <linux/blkdev.h>
15#include <pmem.h>
16#include <nd.h>
17
18long pmem_direct_access(struct block_device *bdev, sector_t sector,
19 void **kaddr, pfn_t *pfn, long size)
20{
21 struct pmem_device *pmem = bdev->bd_queue->queuedata;
22 resource_size_t offset = sector * 512 + pmem->data_offset;
23
24 if (unlikely(is_bad_pmem(&pmem->bb, sector, size)))
25 return -EIO;
26
27 /*
28 * Limit dax to a single page at a time given vmalloc()-backed
29 * in the nfit_test case.
30 */
31 if (get_nfit_res(pmem->phys_addr + offset)) {
32 struct page *page;
33
34 *kaddr = pmem->virt_addr + offset;
35 page = vmalloc_to_page(pmem->virt_addr + offset);
36 *pfn = page_to_pfn_t(page);
37 dev_dbg_ratelimited(disk_to_dev(bdev->bd_disk)->parent,
38 "%s: sector: %#llx pfn: %#lx\n", __func__,
39 (unsigned long long) sector, page_to_pfn(page));
40
41 return PAGE_SIZE;
42 }
43
44 *kaddr = pmem->virt_addr + offset;
45 *pfn = phys_to_pfn_t(pmem->phys_addr + offset, pmem->pfn_flags);
46
47 /*
48 * If badblocks are present, limit known good range to the
49 * requested range.
50 */
51 if (unlikely(pmem->bb.count))
52 return size;
53 return pmem->size - pmem->pfn_pad - offset;
54}
diff --git a/tools/testing/nvdimm/test/Kbuild b/tools/testing/nvdimm/test/Kbuild
index 9241064970fe..d32f25bba42a 100644
--- a/tools/testing/nvdimm/test/Kbuild
+++ b/tools/testing/nvdimm/test/Kbuild
@@ -1,5 +1,5 @@
1ccflags-y := -I$(src)/../../../../drivers/nvdimm/ 1ccflags-y := -I$(src)/../../../../drivers/nvdimm/
2ccflags-y += -I$(src)/../../../../drivers/acpi/ 2ccflags-y += -I$(src)/../../../../drivers/acpi/nfit/
3 3
4obj-m += nfit_test.o 4obj-m += nfit_test.o
5obj-m += nfit_test_iomap.o 5obj-m += nfit_test_iomap.o
diff --git a/tools/testing/nvdimm/test/iomap.c b/tools/testing/nvdimm/test/iomap.c
index c842095f2801..3ccef732fce9 100644
--- a/tools/testing/nvdimm/test/iomap.c
+++ b/tools/testing/nvdimm/test/iomap.c
@@ -10,11 +10,14 @@
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details. 11 * General Public License for more details.
12 */ 12 */
13#include <linux/memremap.h>
13#include <linux/rculist.h> 14#include <linux/rculist.h>
14#include <linux/export.h> 15#include <linux/export.h>
15#include <linux/ioport.h> 16#include <linux/ioport.h>
16#include <linux/module.h> 17#include <linux/module.h>
17#include <linux/types.h> 18#include <linux/types.h>
19#include <linux/pfn_t.h>
20#include <linux/acpi.h>
18#include <linux/io.h> 21#include <linux/io.h>
19#include <linux/mm.h> 22#include <linux/mm.h>
20#include "nfit_test.h" 23#include "nfit_test.h"
@@ -52,7 +55,7 @@ static struct nfit_test_resource *__get_nfit_res(resource_size_t resource)
52 return NULL; 55 return NULL;
53} 56}
54 57
55static struct nfit_test_resource *get_nfit_res(resource_size_t resource) 58struct nfit_test_resource *get_nfit_res(resource_size_t resource)
56{ 59{
57 struct nfit_test_resource *res; 60 struct nfit_test_resource *res;
58 61
@@ -62,6 +65,7 @@ static struct nfit_test_resource *get_nfit_res(resource_size_t resource)
62 65
63 return res; 66 return res;
64} 67}
68EXPORT_SYMBOL(get_nfit_res);
65 69
66void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size, 70void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
67 void __iomem *(*fallback_fn)(resource_size_t, unsigned long)) 71 void __iomem *(*fallback_fn)(resource_size_t, unsigned long))
@@ -70,7 +74,7 @@ void __iomem *__nfit_test_ioremap(resource_size_t offset, unsigned long size,
70 74
71 if (nfit_res) 75 if (nfit_res)
72 return (void __iomem *) nfit_res->buf + offset 76 return (void __iomem *) nfit_res->buf + offset
73 - nfit_res->res->start; 77 - nfit_res->res.start;
74 return fallback_fn(offset, size); 78 return fallback_fn(offset, size);
75} 79}
76 80
@@ -81,7 +85,7 @@ void __iomem *__wrap_devm_ioremap_nocache(struct device *dev,
81 85
82 if (nfit_res) 86 if (nfit_res)
83 return (void __iomem *) nfit_res->buf + offset 87 return (void __iomem *) nfit_res->buf + offset
84 - nfit_res->res->start; 88 - nfit_res->res.start;
85 return devm_ioremap_nocache(dev, offset, size); 89 return devm_ioremap_nocache(dev, offset, size);
86} 90}
87EXPORT_SYMBOL(__wrap_devm_ioremap_nocache); 91EXPORT_SYMBOL(__wrap_devm_ioremap_nocache);
@@ -92,15 +96,11 @@ void *__wrap_devm_memremap(struct device *dev, resource_size_t offset,
92 struct nfit_test_resource *nfit_res = get_nfit_res(offset); 96 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
93 97
94 if (nfit_res) 98 if (nfit_res)
95 return nfit_res->buf + offset - nfit_res->res->start; 99 return nfit_res->buf + offset - nfit_res->res.start;
96 return devm_memremap(dev, offset, size, flags); 100 return devm_memremap(dev, offset, size, flags);
97} 101}
98EXPORT_SYMBOL(__wrap_devm_memremap); 102EXPORT_SYMBOL(__wrap_devm_memremap);
99 103
100#ifdef __HAVE_ARCH_PTE_DEVMAP
101#include <linux/memremap.h>
102#include <linux/pfn_t.h>
103
104void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res, 104void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
105 struct percpu_ref *ref, struct vmem_altmap *altmap) 105 struct percpu_ref *ref, struct vmem_altmap *altmap)
106{ 106{
@@ -108,7 +108,7 @@ void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res,
108 struct nfit_test_resource *nfit_res = get_nfit_res(offset); 108 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
109 109
110 if (nfit_res) 110 if (nfit_res)
111 return nfit_res->buf + offset - nfit_res->res->start; 111 return nfit_res->buf + offset - nfit_res->res.start;
112 return devm_memremap_pages(dev, res, ref, altmap); 112 return devm_memremap_pages(dev, res, ref, altmap);
113} 113}
114EXPORT_SYMBOL(__wrap_devm_memremap_pages); 114EXPORT_SYMBOL(__wrap_devm_memremap_pages);
@@ -122,19 +122,6 @@ pfn_t __wrap_phys_to_pfn_t(phys_addr_t addr, unsigned long flags)
122 return phys_to_pfn_t(addr, flags); 122 return phys_to_pfn_t(addr, flags);
123} 123}
124EXPORT_SYMBOL(__wrap_phys_to_pfn_t); 124EXPORT_SYMBOL(__wrap_phys_to_pfn_t);
125#else
126/* to be removed post 4.5-rc1 */
127void *__wrap_devm_memremap_pages(struct device *dev, struct resource *res)
128{
129 resource_size_t offset = res->start;
130 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
131
132 if (nfit_res)
133 return nfit_res->buf + offset - nfit_res->res->start;
134 return devm_memremap_pages(dev, res);
135}
136EXPORT_SYMBOL(__wrap_devm_memremap_pages);
137#endif
138 125
139void *__wrap_memremap(resource_size_t offset, size_t size, 126void *__wrap_memremap(resource_size_t offset, size_t size,
140 unsigned long flags) 127 unsigned long flags)
@@ -142,7 +129,7 @@ void *__wrap_memremap(resource_size_t offset, size_t size,
142 struct nfit_test_resource *nfit_res = get_nfit_res(offset); 129 struct nfit_test_resource *nfit_res = get_nfit_res(offset);
143 130
144 if (nfit_res) 131 if (nfit_res)
145 return nfit_res->buf + offset - nfit_res->res->start; 132 return nfit_res->buf + offset - nfit_res->res.start;
146 return memremap(offset, size, flags); 133 return memremap(offset, size, flags);
147} 134}
148EXPORT_SYMBOL(__wrap_memremap); 135EXPORT_SYMBOL(__wrap_memremap);
@@ -188,6 +175,63 @@ void __wrap_memunmap(void *addr)
188} 175}
189EXPORT_SYMBOL(__wrap_memunmap); 176EXPORT_SYMBOL(__wrap_memunmap);
190 177
178static bool nfit_test_release_region(struct device *dev,
179 struct resource *parent, resource_size_t start,
180 resource_size_t n);
181
182static void nfit_devres_release(struct device *dev, void *data)
183{
184 struct resource *res = *((struct resource **) data);
185
186 WARN_ON(!nfit_test_release_region(NULL, &iomem_resource, res->start,
187 resource_size(res)));
188}
189
190static int match(struct device *dev, void *__res, void *match_data)
191{
192 struct resource *res = *((struct resource **) __res);
193 resource_size_t start = *((resource_size_t *) match_data);
194
195 return res->start == start;
196}
197
198static bool nfit_test_release_region(struct device *dev,
199 struct resource *parent, resource_size_t start,
200 resource_size_t n)
201{
202 if (parent == &iomem_resource) {
203 struct nfit_test_resource *nfit_res = get_nfit_res(start);
204
205 if (nfit_res) {
206 struct nfit_test_request *req;
207 struct resource *res = NULL;
208
209 if (dev) {
210 devres_release(dev, nfit_devres_release, match,
211 &start);
212 return true;
213 }
214
215 spin_lock(&nfit_res->lock);
216 list_for_each_entry(req, &nfit_res->requests, list)
217 if (req->res.start == start) {
218 res = &req->res;
219 list_del(&req->list);
220 break;
221 }
222 spin_unlock(&nfit_res->lock);
223
224 WARN(!res || resource_size(res) != n,
225 "%s: start: %llx n: %llx mismatch: %pr\n",
226 __func__, start, n, res);
227 if (res)
228 kfree(req);
229 return true;
230 }
231 }
232 return false;
233}
234
191static struct resource *nfit_test_request_region(struct device *dev, 235static struct resource *nfit_test_request_region(struct device *dev,
192 struct resource *parent, resource_size_t start, 236 struct resource *parent, resource_size_t start,
193 resource_size_t n, const char *name, int flags) 237 resource_size_t n, const char *name, int flags)
@@ -197,21 +241,57 @@ static struct resource *nfit_test_request_region(struct device *dev,
197 if (parent == &iomem_resource) { 241 if (parent == &iomem_resource) {
198 nfit_res = get_nfit_res(start); 242 nfit_res = get_nfit_res(start);
199 if (nfit_res) { 243 if (nfit_res) {
200 struct resource *res = nfit_res->res + 1; 244 struct nfit_test_request *req;
245 struct resource *res = NULL;
201 246
202 if (start + n > nfit_res->res->start 247 if (start + n > nfit_res->res.start
203 + resource_size(nfit_res->res)) { 248 + resource_size(&nfit_res->res)) {
204 pr_debug("%s: start: %llx n: %llx overflow: %pr\n", 249 pr_debug("%s: start: %llx n: %llx overflow: %pr\n",
205 __func__, start, n, 250 __func__, start, n,
206 nfit_res->res); 251 &nfit_res->res);
207 return NULL; 252 return NULL;
208 } 253 }
209 254
255 spin_lock(&nfit_res->lock);
256 list_for_each_entry(req, &nfit_res->requests, list)
257 if (start == req->res.start) {
258 res = &req->res;
259 break;
260 }
261 spin_unlock(&nfit_res->lock);
262
263 if (res) {
264 WARN(1, "%pr already busy\n", res);
265 return NULL;
266 }
267
268 req = kzalloc(sizeof(*req), GFP_KERNEL);
269 if (!req)
270 return NULL;
271 INIT_LIST_HEAD(&req->list);
272 res = &req->res;
273
210 res->start = start; 274 res->start = start;
211 res->end = start + n - 1; 275 res->end = start + n - 1;
212 res->name = name; 276 res->name = name;
213 res->flags = resource_type(parent); 277 res->flags = resource_type(parent);
214 res->flags |= IORESOURCE_BUSY | flags; 278 res->flags |= IORESOURCE_BUSY | flags;
279 spin_lock(&nfit_res->lock);
280 list_add(&req->list, &nfit_res->requests);
281 spin_unlock(&nfit_res->lock);
282
283 if (dev) {
284 struct resource **d;
285
286 d = devres_alloc(nfit_devres_release,
287 sizeof(struct resource *),
288 GFP_KERNEL);
289 if (!d)
290 return NULL;
291 *d = res;
292 devres_add(dev, d);
293 }
294
215 pr_debug("%s: %pr\n", __func__, res); 295 pr_debug("%s: %pr\n", __func__, res);
216 return res; 296 return res;
217 } 297 }
@@ -229,6 +309,22 @@ struct resource *__wrap___request_region(struct resource *parent,
229} 309}
230EXPORT_SYMBOL(__wrap___request_region); 310EXPORT_SYMBOL(__wrap___request_region);
231 311
312int __wrap_insert_resource(struct resource *parent, struct resource *res)
313{
314 if (get_nfit_res(res->start))
315 return 0;
316 return insert_resource(parent, res);
317}
318EXPORT_SYMBOL(__wrap_insert_resource);
319
320int __wrap_remove_resource(struct resource *res)
321{
322 if (get_nfit_res(res->start))
323 return 0;
324 return remove_resource(res);
325}
326EXPORT_SYMBOL(__wrap_remove_resource);
327
232struct resource *__wrap___devm_request_region(struct device *dev, 328struct resource *__wrap___devm_request_region(struct device *dev,
233 struct resource *parent, resource_size_t start, 329 struct resource *parent, resource_size_t start,
234 resource_size_t n, const char *name) 330 resource_size_t n, const char *name)
@@ -239,29 +335,10 @@ struct resource *__wrap___devm_request_region(struct device *dev,
239} 335}
240EXPORT_SYMBOL(__wrap___devm_request_region); 336EXPORT_SYMBOL(__wrap___devm_request_region);
241 337
242static bool nfit_test_release_region(struct resource *parent,
243 resource_size_t start, resource_size_t n)
244{
245 if (parent == &iomem_resource) {
246 struct nfit_test_resource *nfit_res = get_nfit_res(start);
247 if (nfit_res) {
248 struct resource *res = nfit_res->res + 1;
249
250 if (start != res->start || resource_size(res) != n)
251 pr_info("%s: start: %llx n: %llx mismatch: %pr\n",
252 __func__, start, n, res);
253 else
254 memset(res, 0, sizeof(*res));
255 return true;
256 }
257 }
258 return false;
259}
260
261void __wrap___release_region(struct resource *parent, resource_size_t start, 338void __wrap___release_region(struct resource *parent, resource_size_t start,
262 resource_size_t n) 339 resource_size_t n)
263{ 340{
264 if (!nfit_test_release_region(parent, start, n)) 341 if (!nfit_test_release_region(NULL, parent, start, n))
265 __release_region(parent, start, n); 342 __release_region(parent, start, n);
266} 343}
267EXPORT_SYMBOL(__wrap___release_region); 344EXPORT_SYMBOL(__wrap___release_region);
@@ -269,9 +346,25 @@ EXPORT_SYMBOL(__wrap___release_region);
269void __wrap___devm_release_region(struct device *dev, struct resource *parent, 346void __wrap___devm_release_region(struct device *dev, struct resource *parent,
270 resource_size_t start, resource_size_t n) 347 resource_size_t start, resource_size_t n)
271{ 348{
272 if (!nfit_test_release_region(parent, start, n)) 349 if (!nfit_test_release_region(dev, parent, start, n))
273 __devm_release_region(dev, parent, start, n); 350 __devm_release_region(dev, parent, start, n);
274} 351}
275EXPORT_SYMBOL(__wrap___devm_release_region); 352EXPORT_SYMBOL(__wrap___devm_release_region);
276 353
354acpi_status __wrap_acpi_evaluate_object(acpi_handle handle, acpi_string path,
355 struct acpi_object_list *p, struct acpi_buffer *buf)
356{
357 struct nfit_test_resource *nfit_res = get_nfit_res((long) handle);
358 union acpi_object **obj;
359
360 if (!nfit_res || strcmp(path, "_FIT") || !buf)
361 return acpi_evaluate_object(handle, path, p, buf);
362
363 obj = nfit_res->buf;
364 buf->length = sizeof(union acpi_object);
365 buf->pointer = *obj;
366 return AE_OK;
367}
368EXPORT_SYMBOL(__wrap_acpi_evaluate_object);
369
277MODULE_LICENSE("GPL v2"); 370MODULE_LICENSE("GPL v2");
diff --git a/tools/testing/nvdimm/test/nfit.c b/tools/testing/nvdimm/test/nfit.c
index c919866853a0..c9a6458cb63e 100644
--- a/tools/testing/nvdimm/test/nfit.c
+++ b/tools/testing/nvdimm/test/nfit.c
@@ -13,6 +13,7 @@
13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14#include <linux/platform_device.h> 14#include <linux/platform_device.h>
15#include <linux/dma-mapping.h> 15#include <linux/dma-mapping.h>
16#include <linux/workqueue.h>
16#include <linux/libnvdimm.h> 17#include <linux/libnvdimm.h>
17#include <linux/vmalloc.h> 18#include <linux/vmalloc.h>
18#include <linux/device.h> 19#include <linux/device.h>
@@ -98,11 +99,13 @@
98enum { 99enum {
99 NUM_PM = 3, 100 NUM_PM = 3,
100 NUM_DCR = 5, 101 NUM_DCR = 5,
102 NUM_HINTS = 8,
101 NUM_BDW = NUM_DCR, 103 NUM_BDW = NUM_DCR,
102 NUM_SPA = NUM_PM + NUM_DCR + NUM_BDW, 104 NUM_SPA = NUM_PM + NUM_DCR + NUM_BDW,
103 NUM_MEM = NUM_DCR + NUM_BDW + 2 /* spa0 iset */ + 4 /* spa1 iset */, 105 NUM_MEM = NUM_DCR + NUM_BDW + 2 /* spa0 iset */ + 4 /* spa1 iset */,
104 DIMM_SIZE = SZ_32M, 106 DIMM_SIZE = SZ_32M,
105 LABEL_SIZE = SZ_128K, 107 LABEL_SIZE = SZ_128K,
108 SPA_VCD_SIZE = SZ_4M,
106 SPA0_SIZE = DIMM_SIZE, 109 SPA0_SIZE = DIMM_SIZE,
107 SPA1_SIZE = DIMM_SIZE*2, 110 SPA1_SIZE = DIMM_SIZE*2,
108 SPA2_SIZE = DIMM_SIZE, 111 SPA2_SIZE = DIMM_SIZE,
@@ -129,6 +132,8 @@ static u32 handle[NUM_DCR] = {
129 [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0), 132 [4] = NFIT_DIMM_HANDLE(0, 1, 0, 0, 0),
130}; 133};
131 134
135static unsigned long dimm_fail_cmd_flags[NUM_DCR];
136
132struct nfit_test { 137struct nfit_test {
133 struct acpi_nfit_desc acpi_desc; 138 struct acpi_nfit_desc acpi_desc;
134 struct platform_device pdev; 139 struct platform_device pdev;
@@ -151,11 +156,14 @@ struct nfit_test {
151 int (*alloc)(struct nfit_test *t); 156 int (*alloc)(struct nfit_test *t);
152 void (*setup)(struct nfit_test *t); 157 void (*setup)(struct nfit_test *t);
153 int setup_hotplug; 158 int setup_hotplug;
159 union acpi_object **_fit;
160 dma_addr_t _fit_dma;
154 struct ars_state { 161 struct ars_state {
155 struct nd_cmd_ars_status *ars_status; 162 struct nd_cmd_ars_status *ars_status;
156 unsigned long deadline; 163 unsigned long deadline;
157 spinlock_t lock; 164 spinlock_t lock;
158 } ars_state; 165 } ars_state;
166 struct device *dimm_dev[NUM_DCR];
159}; 167};
160 168
161static struct nfit_test *to_nfit_test(struct device *dev) 169static struct nfit_test *to_nfit_test(struct device *dev)
@@ -408,6 +416,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
408 if (i >= ARRAY_SIZE(handle)) 416 if (i >= ARRAY_SIZE(handle))
409 return -ENXIO; 417 return -ENXIO;
410 418
419 if ((1 << func) & dimm_fail_cmd_flags[i])
420 return -EIO;
421
411 switch (func) { 422 switch (func) {
412 case ND_CMD_GET_CONFIG_SIZE: 423 case ND_CMD_GET_CONFIG_SIZE:
413 rc = nfit_test_cmd_get_config_size(buf, buf_len); 424 rc = nfit_test_cmd_get_config_size(buf, buf_len);
@@ -425,6 +436,9 @@ static int nfit_test_ctl(struct nvdimm_bus_descriptor *nd_desc,
425 break; 436 break;
426 case ND_CMD_SMART_THRESHOLD: 437 case ND_CMD_SMART_THRESHOLD:
427 rc = nfit_test_cmd_smart_threshold(buf, buf_len); 438 rc = nfit_test_cmd_smart_threshold(buf, buf_len);
439 device_lock(&t->pdev.dev);
440 __acpi_nvdimm_notify(t->dimm_dev[i], 0x81);
441 device_unlock(&t->pdev.dev);
428 break; 442 break;
429 default: 443 default:
430 return -ENOTTY; 444 return -ENOTTY;
@@ -464,18 +478,12 @@ static struct nfit_test *instances[NUM_NFITS];
464static void release_nfit_res(void *data) 478static void release_nfit_res(void *data)
465{ 479{
466 struct nfit_test_resource *nfit_res = data; 480 struct nfit_test_resource *nfit_res = data;
467 struct resource *res = nfit_res->res;
468 481
469 spin_lock(&nfit_test_lock); 482 spin_lock(&nfit_test_lock);
470 list_del(&nfit_res->list); 483 list_del(&nfit_res->list);
471 spin_unlock(&nfit_test_lock); 484 spin_unlock(&nfit_test_lock);
472 485
473 if (is_vmalloc_addr(nfit_res->buf)) 486 vfree(nfit_res->buf);
474 vfree(nfit_res->buf);
475 else
476 dma_free_coherent(nfit_res->dev, resource_size(res),
477 nfit_res->buf, res->start);
478 kfree(res);
479 kfree(nfit_res); 487 kfree(nfit_res);
480} 488}
481 489
@@ -483,12 +491,11 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma,
483 void *buf) 491 void *buf)
484{ 492{
485 struct device *dev = &t->pdev.dev; 493 struct device *dev = &t->pdev.dev;
486 struct resource *res = kzalloc(sizeof(*res) * 2, GFP_KERNEL);
487 struct nfit_test_resource *nfit_res = kzalloc(sizeof(*nfit_res), 494 struct nfit_test_resource *nfit_res = kzalloc(sizeof(*nfit_res),
488 GFP_KERNEL); 495 GFP_KERNEL);
489 int rc; 496 int rc;
490 497
491 if (!res || !buf || !nfit_res) 498 if (!buf || !nfit_res)
492 goto err; 499 goto err;
493 rc = devm_add_action(dev, release_nfit_res, nfit_res); 500 rc = devm_add_action(dev, release_nfit_res, nfit_res);
494 if (rc) 501 if (rc)
@@ -497,21 +504,19 @@ static void *__test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma,
497 memset(buf, 0, size); 504 memset(buf, 0, size);
498 nfit_res->dev = dev; 505 nfit_res->dev = dev;
499 nfit_res->buf = buf; 506 nfit_res->buf = buf;
500 nfit_res->res = res; 507 nfit_res->res.start = *dma;
501 res->start = *dma; 508 nfit_res->res.end = *dma + size - 1;
502 res->end = *dma + size - 1; 509 nfit_res->res.name = "NFIT";
503 res->name = "NFIT"; 510 spin_lock_init(&nfit_res->lock);
511 INIT_LIST_HEAD(&nfit_res->requests);
504 spin_lock(&nfit_test_lock); 512 spin_lock(&nfit_test_lock);
505 list_add(&nfit_res->list, &t->resources); 513 list_add(&nfit_res->list, &t->resources);
506 spin_unlock(&nfit_test_lock); 514 spin_unlock(&nfit_test_lock);
507 515
508 return nfit_res->buf; 516 return nfit_res->buf;
509 err: 517 err:
510 if (buf && !is_vmalloc_addr(buf)) 518 if (buf)
511 dma_free_coherent(dev, size, buf, *dma);
512 else if (buf)
513 vfree(buf); 519 vfree(buf);
514 kfree(res);
515 kfree(nfit_res); 520 kfree(nfit_res);
516 return NULL; 521 return NULL;
517} 522}
@@ -524,15 +529,6 @@ static void *test_alloc(struct nfit_test *t, size_t size, dma_addr_t *dma)
524 return __test_alloc(t, size, dma, buf); 529 return __test_alloc(t, size, dma, buf);
525} 530}
526 531
527static void *test_alloc_coherent(struct nfit_test *t, size_t size,
528 dma_addr_t *dma)
529{
530 struct device *dev = &t->pdev.dev;
531 void *buf = dma_alloc_coherent(dev, size, dma, GFP_KERNEL);
532
533 return __test_alloc(t, size, dma, buf);
534}
535
536static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr) 532static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr)
537{ 533{
538 int i; 534 int i;
@@ -545,13 +541,13 @@ static struct nfit_test_resource *nfit_test_lookup(resource_size_t addr)
545 continue; 541 continue;
546 spin_lock(&nfit_test_lock); 542 spin_lock(&nfit_test_lock);
547 list_for_each_entry(n, &t->resources, list) { 543 list_for_each_entry(n, &t->resources, list) {
548 if (addr >= n->res->start && (addr < n->res->start 544 if (addr >= n->res.start && (addr < n->res.start
549 + resource_size(n->res))) { 545 + resource_size(&n->res))) {
550 nfit_res = n; 546 nfit_res = n;
551 break; 547 break;
552 } else if (addr >= (unsigned long) n->buf 548 } else if (addr >= (unsigned long) n->buf
553 && (addr < (unsigned long) n->buf 549 && (addr < (unsigned long) n->buf
554 + resource_size(n->res))) { 550 + resource_size(&n->res))) {
555 nfit_res = n; 551 nfit_res = n;
556 break; 552 break;
557 } 553 }
@@ -576,6 +572,86 @@ static int ars_state_init(struct device *dev, struct ars_state *ars_state)
576 return 0; 572 return 0;
577} 573}
578 574
575static void put_dimms(void *data)
576{
577 struct device **dimm_dev = data;
578 int i;
579
580 for (i = 0; i < NUM_DCR; i++)
581 if (dimm_dev[i])
582 device_unregister(dimm_dev[i]);
583}
584
585static struct class *nfit_test_dimm;
586
587static int dimm_name_to_id(struct device *dev)
588{
589 int dimm;
590
591 if (sscanf(dev_name(dev), "test_dimm%d", &dimm) != 1
592 || dimm >= NUM_DCR || dimm < 0)
593 return -ENXIO;
594 return dimm;
595}
596
597
598static ssize_t handle_show(struct device *dev, struct device_attribute *attr,
599 char *buf)
600{
601 int dimm = dimm_name_to_id(dev);
602
603 if (dimm < 0)
604 return dimm;
605
606 return sprintf(buf, "%#x", handle[dimm]);
607}
608DEVICE_ATTR_RO(handle);
609
610static ssize_t fail_cmd_show(struct device *dev, struct device_attribute *attr,
611 char *buf)
612{
613 int dimm = dimm_name_to_id(dev);
614
615 if (dimm < 0)
616 return dimm;
617
618 return sprintf(buf, "%#lx\n", dimm_fail_cmd_flags[dimm]);
619}
620
621static ssize_t fail_cmd_store(struct device *dev, struct device_attribute *attr,
622 const char *buf, size_t size)
623{
624 int dimm = dimm_name_to_id(dev);
625 unsigned long val;
626 ssize_t rc;
627
628 if (dimm < 0)
629 return dimm;
630
631 rc = kstrtol(buf, 0, &val);
632 if (rc)
633 return rc;
634
635 dimm_fail_cmd_flags[dimm] = val;
636 return size;
637}
638static DEVICE_ATTR_RW(fail_cmd);
639
640static struct attribute *nfit_test_dimm_attributes[] = {
641 &dev_attr_fail_cmd.attr,
642 &dev_attr_handle.attr,
643 NULL,
644};
645
646static struct attribute_group nfit_test_dimm_attribute_group = {
647 .attrs = nfit_test_dimm_attributes,
648};
649
650static const struct attribute_group *nfit_test_dimm_attribute_groups[] = {
651 &nfit_test_dimm_attribute_group,
652 NULL,
653};
654
579static int nfit_test0_alloc(struct nfit_test *t) 655static int nfit_test0_alloc(struct nfit_test *t)
580{ 656{
581 size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA 657 size_t nfit_size = sizeof(struct acpi_nfit_system_address) * NUM_SPA
@@ -584,7 +660,8 @@ static int nfit_test0_alloc(struct nfit_test *t)
584 + offsetof(struct acpi_nfit_control_region, 660 + offsetof(struct acpi_nfit_control_region,
585 window_size) * NUM_DCR 661 window_size) * NUM_DCR
586 + sizeof(struct acpi_nfit_data_region) * NUM_BDW 662 + sizeof(struct acpi_nfit_data_region) * NUM_BDW
587 + sizeof(struct acpi_nfit_flush_address) * NUM_DCR; 663 + (sizeof(struct acpi_nfit_flush_address)
664 + sizeof(u64) * NUM_HINTS) * NUM_DCR;
588 int i; 665 int i;
589 666
590 t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma); 667 t->nfit_buf = test_alloc(t, nfit_size, &t->nfit_dma);
@@ -592,15 +669,15 @@ static int nfit_test0_alloc(struct nfit_test *t)
592 return -ENOMEM; 669 return -ENOMEM;
593 t->nfit_size = nfit_size; 670 t->nfit_size = nfit_size;
594 671
595 t->spa_set[0] = test_alloc_coherent(t, SPA0_SIZE, &t->spa_set_dma[0]); 672 t->spa_set[0] = test_alloc(t, SPA0_SIZE, &t->spa_set_dma[0]);
596 if (!t->spa_set[0]) 673 if (!t->spa_set[0])
597 return -ENOMEM; 674 return -ENOMEM;
598 675
599 t->spa_set[1] = test_alloc_coherent(t, SPA1_SIZE, &t->spa_set_dma[1]); 676 t->spa_set[1] = test_alloc(t, SPA1_SIZE, &t->spa_set_dma[1]);
600 if (!t->spa_set[1]) 677 if (!t->spa_set[1])
601 return -ENOMEM; 678 return -ENOMEM;
602 679
603 t->spa_set[2] = test_alloc_coherent(t, SPA0_SIZE, &t->spa_set_dma[2]); 680 t->spa_set[2] = test_alloc(t, SPA0_SIZE, &t->spa_set_dma[2]);
604 if (!t->spa_set[2]) 681 if (!t->spa_set[2])
605 return -ENOMEM; 682 return -ENOMEM;
606 683
@@ -614,7 +691,9 @@ static int nfit_test0_alloc(struct nfit_test *t)
614 return -ENOMEM; 691 return -ENOMEM;
615 sprintf(t->label[i], "label%d", i); 692 sprintf(t->label[i], "label%d", i);
616 693
617 t->flush[i] = test_alloc(t, 8, &t->flush_dma[i]); 694 t->flush[i] = test_alloc(t, max(PAGE_SIZE,
695 sizeof(u64) * NUM_HINTS),
696 &t->flush_dma[i]);
618 if (!t->flush[i]) 697 if (!t->flush[i])
619 return -ENOMEM; 698 return -ENOMEM;
620 } 699 }
@@ -625,12 +704,27 @@ static int nfit_test0_alloc(struct nfit_test *t)
625 return -ENOMEM; 704 return -ENOMEM;
626 } 705 }
627 706
707 t->_fit = test_alloc(t, sizeof(union acpi_object **), &t->_fit_dma);
708 if (!t->_fit)
709 return -ENOMEM;
710
711 if (devm_add_action_or_reset(&t->pdev.dev, put_dimms, t->dimm_dev))
712 return -ENOMEM;
713 for (i = 0; i < NUM_DCR; i++) {
714 t->dimm_dev[i] = device_create_with_groups(nfit_test_dimm,
715 &t->pdev.dev, 0, NULL,
716 nfit_test_dimm_attribute_groups,
717 "test_dimm%d", i);
718 if (!t->dimm_dev[i])
719 return -ENOMEM;
720 }
721
628 return ars_state_init(&t->pdev.dev, &t->ars_state); 722 return ars_state_init(&t->pdev.dev, &t->ars_state);
629} 723}
630 724
631static int nfit_test1_alloc(struct nfit_test *t) 725static int nfit_test1_alloc(struct nfit_test *t)
632{ 726{
633 size_t nfit_size = sizeof(struct acpi_nfit_system_address) 727 size_t nfit_size = sizeof(struct acpi_nfit_system_address) * 2
634 + sizeof(struct acpi_nfit_memory_map) 728 + sizeof(struct acpi_nfit_memory_map)
635 + offsetof(struct acpi_nfit_control_region, window_size); 729 + offsetof(struct acpi_nfit_control_region, window_size);
636 730
@@ -639,15 +733,31 @@ static int nfit_test1_alloc(struct nfit_test *t)
639 return -ENOMEM; 733 return -ENOMEM;
640 t->nfit_size = nfit_size; 734 t->nfit_size = nfit_size;
641 735
642 t->spa_set[0] = test_alloc_coherent(t, SPA2_SIZE, &t->spa_set_dma[0]); 736 t->spa_set[0] = test_alloc(t, SPA2_SIZE, &t->spa_set_dma[0]);
643 if (!t->spa_set[0]) 737 if (!t->spa_set[0])
644 return -ENOMEM; 738 return -ENOMEM;
645 739
740 t->spa_set[1] = test_alloc(t, SPA_VCD_SIZE, &t->spa_set_dma[1]);
741 if (!t->spa_set[1])
742 return -ENOMEM;
743
646 return ars_state_init(&t->pdev.dev, &t->ars_state); 744 return ars_state_init(&t->pdev.dev, &t->ars_state);
647} 745}
648 746
747static void dcr_common_init(struct acpi_nfit_control_region *dcr)
748{
749 dcr->vendor_id = 0xabcd;
750 dcr->device_id = 0;
751 dcr->revision_id = 1;
752 dcr->valid_fields = 1;
753 dcr->manufacturing_location = 0xa;
754 dcr->manufacturing_date = cpu_to_be16(2016);
755}
756
649static void nfit_test0_setup(struct nfit_test *t) 757static void nfit_test0_setup(struct nfit_test *t)
650{ 758{
759 const int flush_hint_size = sizeof(struct acpi_nfit_flush_address)
760 + (sizeof(u64) * NUM_HINTS);
651 struct acpi_nfit_desc *acpi_desc; 761 struct acpi_nfit_desc *acpi_desc;
652 struct acpi_nfit_memory_map *memdev; 762 struct acpi_nfit_memory_map *memdev;
653 void *nfit_buf = t->nfit_buf; 763 void *nfit_buf = t->nfit_buf;
@@ -655,7 +765,7 @@ static void nfit_test0_setup(struct nfit_test *t)
655 struct acpi_nfit_control_region *dcr; 765 struct acpi_nfit_control_region *dcr;
656 struct acpi_nfit_data_region *bdw; 766 struct acpi_nfit_data_region *bdw;
657 struct acpi_nfit_flush_address *flush; 767 struct acpi_nfit_flush_address *flush;
658 unsigned int offset; 768 unsigned int offset, i;
659 769
660 /* 770 /*
661 * spa0 (interleave first half of dimm0 and dimm1, note storage 771 * spa0 (interleave first half of dimm0 and dimm1, note storage
@@ -972,9 +1082,7 @@ static void nfit_test0_setup(struct nfit_test *t)
972 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1082 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
973 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1083 dcr->header.length = sizeof(struct acpi_nfit_control_region);
974 dcr->region_index = 0+1; 1084 dcr->region_index = 0+1;
975 dcr->vendor_id = 0xabcd; 1085 dcr_common_init(dcr);
976 dcr->device_id = 0;
977 dcr->revision_id = 1;
978 dcr->serial_number = ~handle[0]; 1086 dcr->serial_number = ~handle[0];
979 dcr->code = NFIT_FIC_BLK; 1087 dcr->code = NFIT_FIC_BLK;
980 dcr->windows = 1; 1088 dcr->windows = 1;
@@ -989,9 +1097,7 @@ static void nfit_test0_setup(struct nfit_test *t)
989 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1097 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
990 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1098 dcr->header.length = sizeof(struct acpi_nfit_control_region);
991 dcr->region_index = 1+1; 1099 dcr->region_index = 1+1;
992 dcr->vendor_id = 0xabcd; 1100 dcr_common_init(dcr);
993 dcr->device_id = 0;
994 dcr->revision_id = 1;
995 dcr->serial_number = ~handle[1]; 1101 dcr->serial_number = ~handle[1];
996 dcr->code = NFIT_FIC_BLK; 1102 dcr->code = NFIT_FIC_BLK;
997 dcr->windows = 1; 1103 dcr->windows = 1;
@@ -1006,9 +1112,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1006 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1112 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1007 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1113 dcr->header.length = sizeof(struct acpi_nfit_control_region);
1008 dcr->region_index = 2+1; 1114 dcr->region_index = 2+1;
1009 dcr->vendor_id = 0xabcd; 1115 dcr_common_init(dcr);
1010 dcr->device_id = 0;
1011 dcr->revision_id = 1;
1012 dcr->serial_number = ~handle[2]; 1116 dcr->serial_number = ~handle[2];
1013 dcr->code = NFIT_FIC_BLK; 1117 dcr->code = NFIT_FIC_BLK;
1014 dcr->windows = 1; 1118 dcr->windows = 1;
@@ -1023,9 +1127,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1023 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1127 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1024 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1128 dcr->header.length = sizeof(struct acpi_nfit_control_region);
1025 dcr->region_index = 3+1; 1129 dcr->region_index = 3+1;
1026 dcr->vendor_id = 0xabcd; 1130 dcr_common_init(dcr);
1027 dcr->device_id = 0;
1028 dcr->revision_id = 1;
1029 dcr->serial_number = ~handle[3]; 1131 dcr->serial_number = ~handle[3];
1030 dcr->code = NFIT_FIC_BLK; 1132 dcr->code = NFIT_FIC_BLK;
1031 dcr->windows = 1; 1133 dcr->windows = 1;
@@ -1042,9 +1144,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1042 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1144 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1043 window_size); 1145 window_size);
1044 dcr->region_index = 4+1; 1146 dcr->region_index = 4+1;
1045 dcr->vendor_id = 0xabcd; 1147 dcr_common_init(dcr);
1046 dcr->device_id = 0;
1047 dcr->revision_id = 1;
1048 dcr->serial_number = ~handle[0]; 1148 dcr->serial_number = ~handle[0];
1049 dcr->code = NFIT_FIC_BYTEN; 1149 dcr->code = NFIT_FIC_BYTEN;
1050 dcr->windows = 0; 1150 dcr->windows = 0;
@@ -1056,9 +1156,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1056 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1156 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1057 window_size); 1157 window_size);
1058 dcr->region_index = 5+1; 1158 dcr->region_index = 5+1;
1059 dcr->vendor_id = 0xabcd; 1159 dcr_common_init(dcr);
1060 dcr->device_id = 0;
1061 dcr->revision_id = 1;
1062 dcr->serial_number = ~handle[1]; 1160 dcr->serial_number = ~handle[1];
1063 dcr->code = NFIT_FIC_BYTEN; 1161 dcr->code = NFIT_FIC_BYTEN;
1064 dcr->windows = 0; 1162 dcr->windows = 0;
@@ -1070,9 +1168,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1070 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1168 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1071 window_size); 1169 window_size);
1072 dcr->region_index = 6+1; 1170 dcr->region_index = 6+1;
1073 dcr->vendor_id = 0xabcd; 1171 dcr_common_init(dcr);
1074 dcr->device_id = 0;
1075 dcr->revision_id = 1;
1076 dcr->serial_number = ~handle[2]; 1172 dcr->serial_number = ~handle[2];
1077 dcr->code = NFIT_FIC_BYTEN; 1173 dcr->code = NFIT_FIC_BYTEN;
1078 dcr->windows = 0; 1174 dcr->windows = 0;
@@ -1084,9 +1180,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1084 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1180 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1085 window_size); 1181 window_size);
1086 dcr->region_index = 7+1; 1182 dcr->region_index = 7+1;
1087 dcr->vendor_id = 0xabcd; 1183 dcr_common_init(dcr);
1088 dcr->device_id = 0;
1089 dcr->revision_id = 1;
1090 dcr->serial_number = ~handle[3]; 1184 dcr->serial_number = ~handle[3];
1091 dcr->code = NFIT_FIC_BYTEN; 1185 dcr->code = NFIT_FIC_BYTEN;
1092 dcr->windows = 0; 1186 dcr->windows = 0;
@@ -1141,45 +1235,47 @@ static void nfit_test0_setup(struct nfit_test *t)
1141 /* flush0 (dimm0) */ 1235 /* flush0 (dimm0) */
1142 flush = nfit_buf + offset; 1236 flush = nfit_buf + offset;
1143 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1237 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1144 flush->header.length = sizeof(struct acpi_nfit_flush_address); 1238 flush->header.length = flush_hint_size;
1145 flush->device_handle = handle[0]; 1239 flush->device_handle = handle[0];
1146 flush->hint_count = 1; 1240 flush->hint_count = NUM_HINTS;
1147 flush->hint_address[0] = t->flush_dma[0]; 1241 for (i = 0; i < NUM_HINTS; i++)
1242 flush->hint_address[i] = t->flush_dma[0] + i * sizeof(u64);
1148 1243
1149 /* flush1 (dimm1) */ 1244 /* flush1 (dimm1) */
1150 flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 1; 1245 flush = nfit_buf + offset + flush_hint_size * 1;
1151 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1246 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1152 flush->header.length = sizeof(struct acpi_nfit_flush_address); 1247 flush->header.length = flush_hint_size;
1153 flush->device_handle = handle[1]; 1248 flush->device_handle = handle[1];
1154 flush->hint_count = 1; 1249 flush->hint_count = NUM_HINTS;
1155 flush->hint_address[0] = t->flush_dma[1]; 1250 for (i = 0; i < NUM_HINTS; i++)
1251 flush->hint_address[i] = t->flush_dma[1] + i * sizeof(u64);
1156 1252
1157 /* flush2 (dimm2) */ 1253 /* flush2 (dimm2) */
1158 flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 2; 1254 flush = nfit_buf + offset + flush_hint_size * 2;
1159 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1255 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1160 flush->header.length = sizeof(struct acpi_nfit_flush_address); 1256 flush->header.length = flush_hint_size;
1161 flush->device_handle = handle[2]; 1257 flush->device_handle = handle[2];
1162 flush->hint_count = 1; 1258 flush->hint_count = NUM_HINTS;
1163 flush->hint_address[0] = t->flush_dma[2]; 1259 for (i = 0; i < NUM_HINTS; i++)
1260 flush->hint_address[i] = t->flush_dma[2] + i * sizeof(u64);
1164 1261
1165 /* flush3 (dimm3) */ 1262 /* flush3 (dimm3) */
1166 flush = nfit_buf + offset + sizeof(struct acpi_nfit_flush_address) * 3; 1263 flush = nfit_buf + offset + flush_hint_size * 3;
1167 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1264 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1168 flush->header.length = sizeof(struct acpi_nfit_flush_address); 1265 flush->header.length = flush_hint_size;
1169 flush->device_handle = handle[3]; 1266 flush->device_handle = handle[3];
1170 flush->hint_count = 1; 1267 flush->hint_count = NUM_HINTS;
1171 flush->hint_address[0] = t->flush_dma[3]; 1268 for (i = 0; i < NUM_HINTS; i++)
1269 flush->hint_address[i] = t->flush_dma[3] + i * sizeof(u64);
1172 1270
1173 if (t->setup_hotplug) { 1271 if (t->setup_hotplug) {
1174 offset = offset + sizeof(struct acpi_nfit_flush_address) * 4; 1272 offset = offset + flush_hint_size * 4;
1175 /* dcr-descriptor4: blk */ 1273 /* dcr-descriptor4: blk */
1176 dcr = nfit_buf + offset; 1274 dcr = nfit_buf + offset;
1177 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION; 1275 dcr->header.type = ACPI_NFIT_TYPE_CONTROL_REGION;
1178 dcr->header.length = sizeof(struct acpi_nfit_control_region); 1276 dcr->header.length = sizeof(struct acpi_nfit_control_region);
1179 dcr->region_index = 8+1; 1277 dcr->region_index = 8+1;
1180 dcr->vendor_id = 0xabcd; 1278 dcr_common_init(dcr);
1181 dcr->device_id = 0;
1182 dcr->revision_id = 1;
1183 dcr->serial_number = ~handle[4]; 1279 dcr->serial_number = ~handle[4];
1184 dcr->code = NFIT_FIC_BLK; 1280 dcr->code = NFIT_FIC_BLK;
1185 dcr->windows = 1; 1281 dcr->windows = 1;
@@ -1196,9 +1292,7 @@ static void nfit_test0_setup(struct nfit_test *t)
1196 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1292 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1197 window_size); 1293 window_size);
1198 dcr->region_index = 9+1; 1294 dcr->region_index = 9+1;
1199 dcr->vendor_id = 0xabcd; 1295 dcr_common_init(dcr);
1200 dcr->device_id = 0;
1201 dcr->revision_id = 1;
1202 dcr->serial_number = ~handle[4]; 1296 dcr->serial_number = ~handle[4];
1203 dcr->code = NFIT_FIC_BYTEN; 1297 dcr->code = NFIT_FIC_BYTEN;
1204 dcr->windows = 0; 1298 dcr->windows = 0;
@@ -1300,10 +1394,12 @@ static void nfit_test0_setup(struct nfit_test *t)
1300 /* flush3 (dimm4) */ 1394 /* flush3 (dimm4) */
1301 flush = nfit_buf + offset; 1395 flush = nfit_buf + offset;
1302 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS; 1396 flush->header.type = ACPI_NFIT_TYPE_FLUSH_ADDRESS;
1303 flush->header.length = sizeof(struct acpi_nfit_flush_address); 1397 flush->header.length = flush_hint_size;
1304 flush->device_handle = handle[4]; 1398 flush->device_handle = handle[4];
1305 flush->hint_count = 1; 1399 flush->hint_count = NUM_HINTS;
1306 flush->hint_address[0] = t->flush_dma[4]; 1400 for (i = 0; i < NUM_HINTS; i++)
1401 flush->hint_address[i] = t->flush_dma[4]
1402 + i * sizeof(u64);
1307 } 1403 }
1308 1404
1309 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE); 1405 post_ars_status(&t->ars_state, t->spa_set_dma[0], SPA0_SIZE);
@@ -1339,7 +1435,16 @@ static void nfit_test1_setup(struct nfit_test *t)
1339 spa->address = t->spa_set_dma[0]; 1435 spa->address = t->spa_set_dma[0];
1340 spa->length = SPA2_SIZE; 1436 spa->length = SPA2_SIZE;
1341 1437
1342 offset += sizeof(*spa); 1438 /* virtual cd region */
1439 spa = nfit_buf + sizeof(*spa);
1440 spa->header.type = ACPI_NFIT_TYPE_SYSTEM_ADDRESS;
1441 spa->header.length = sizeof(*spa);
1442 memcpy(spa->range_guid, to_nfit_uuid(NFIT_SPA_VCD), 16);
1443 spa->range_index = 0;
1444 spa->address = t->spa_set_dma[1];
1445 spa->length = SPA_VCD_SIZE;
1446
1447 offset += sizeof(*spa) * 2;
1343 /* mem-region0 (spa0, dimm0) */ 1448 /* mem-region0 (spa0, dimm0) */
1344 memdev = nfit_buf + offset; 1449 memdev = nfit_buf + offset;
1345 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP; 1450 memdev->header.type = ACPI_NFIT_TYPE_MEMORY_MAP;
@@ -1365,9 +1470,7 @@ static void nfit_test1_setup(struct nfit_test *t)
1365 dcr->header.length = offsetof(struct acpi_nfit_control_region, 1470 dcr->header.length = offsetof(struct acpi_nfit_control_region,
1366 window_size); 1471 window_size);
1367 dcr->region_index = 0+1; 1472 dcr->region_index = 0+1;
1368 dcr->vendor_id = 0xabcd; 1473 dcr_common_init(dcr);
1369 dcr->device_id = 0;
1370 dcr->revision_id = 1;
1371 dcr->serial_number = ~0; 1474 dcr->serial_number = ~0;
1372 dcr->code = NFIT_FIC_BYTE; 1475 dcr->code = NFIT_FIC_BYTE;
1373 dcr->windows = 0; 1476 dcr->windows = 0;
@@ -1409,6 +1512,8 @@ static int nfit_test_probe(struct platform_device *pdev)
1409 struct acpi_nfit_desc *acpi_desc; 1512 struct acpi_nfit_desc *acpi_desc;
1410 struct device *dev = &pdev->dev; 1513 struct device *dev = &pdev->dev;
1411 struct nfit_test *nfit_test; 1514 struct nfit_test *nfit_test;
1515 struct nfit_mem *nfit_mem;
1516 union acpi_object *obj;
1412 int rc; 1517 int rc;
1413 1518
1414 nfit_test = to_nfit_test(&pdev->dev); 1519 nfit_test = to_nfit_test(&pdev->dev);
@@ -1462,20 +1567,16 @@ static int nfit_test_probe(struct platform_device *pdev)
1462 nfit_test->setup(nfit_test); 1567 nfit_test->setup(nfit_test);
1463 acpi_desc = &nfit_test->acpi_desc; 1568 acpi_desc = &nfit_test->acpi_desc;
1464 acpi_nfit_desc_init(acpi_desc, &pdev->dev); 1569 acpi_nfit_desc_init(acpi_desc, &pdev->dev);
1465 acpi_desc->nfit = nfit_test->nfit_buf;
1466 acpi_desc->blk_do_io = nfit_test_blk_do_io; 1570 acpi_desc->blk_do_io = nfit_test_blk_do_io;
1467 nd_desc = &acpi_desc->nd_desc; 1571 nd_desc = &acpi_desc->nd_desc;
1468 nd_desc->provider_name = NULL; 1572 nd_desc->provider_name = NULL;
1573 nd_desc->module = THIS_MODULE;
1469 nd_desc->ndctl = nfit_test_ctl; 1574 nd_desc->ndctl = nfit_test_ctl;
1470 acpi_desc->nvdimm_bus = nvdimm_bus_register(&pdev->dev, nd_desc);
1471 if (!acpi_desc->nvdimm_bus)
1472 return -ENXIO;
1473 1575
1474 rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_size); 1576 rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_buf,
1475 if (rc) { 1577 nfit_test->nfit_size);
1476 nvdimm_bus_unregister(acpi_desc->nvdimm_bus); 1578 if (rc)
1477 return rc; 1579 return rc;
1478 }
1479 1580
1480 if (nfit_test->setup != nfit_test0_setup) 1581 if (nfit_test->setup != nfit_test0_setup)
1481 return 0; 1582 return 0;
@@ -1483,22 +1584,33 @@ static int nfit_test_probe(struct platform_device *pdev)
1483 nfit_test->setup_hotplug = 1; 1584 nfit_test->setup_hotplug = 1;
1484 nfit_test->setup(nfit_test); 1585 nfit_test->setup(nfit_test);
1485 1586
1486 rc = acpi_nfit_init(acpi_desc, nfit_test->nfit_size); 1587 obj = kzalloc(sizeof(*obj), GFP_KERNEL);
1487 if (rc) { 1588 if (!obj)
1488 nvdimm_bus_unregister(acpi_desc->nvdimm_bus); 1589 return -ENOMEM;
1489 return rc; 1590 obj->type = ACPI_TYPE_BUFFER;
1591 obj->buffer.length = nfit_test->nfit_size;
1592 obj->buffer.pointer = nfit_test->nfit_buf;
1593 *(nfit_test->_fit) = obj;
1594 __acpi_nfit_notify(&pdev->dev, nfit_test, 0x80);
1595
1596 /* associate dimm devices with nfit_mem data for notification testing */
1597 mutex_lock(&acpi_desc->init_mutex);
1598 list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
1599 u32 nfit_handle = __to_nfit_memdev(nfit_mem)->device_handle;
1600 int i;
1601
1602 for (i = 0; i < NUM_DCR; i++)
1603 if (nfit_handle == handle[i])
1604 dev_set_drvdata(nfit_test->dimm_dev[i],
1605 nfit_mem);
1490 } 1606 }
1607 mutex_unlock(&acpi_desc->init_mutex);
1491 1608
1492 return 0; 1609 return 0;
1493} 1610}
1494 1611
1495static int nfit_test_remove(struct platform_device *pdev) 1612static int nfit_test_remove(struct platform_device *pdev)
1496{ 1613{
1497 struct nfit_test *nfit_test = to_nfit_test(&pdev->dev);
1498 struct acpi_nfit_desc *acpi_desc = &nfit_test->acpi_desc;
1499
1500 nvdimm_bus_unregister(acpi_desc->nvdimm_bus);
1501
1502 return 0; 1614 return 0;
1503} 1615}
1504 1616
@@ -1523,22 +1635,19 @@ static struct platform_driver nfit_test_driver = {
1523 .id_table = nfit_test_id, 1635 .id_table = nfit_test_id,
1524}; 1636};
1525 1637
1526#ifdef CONFIG_CMA_SIZE_MBYTES
1527#define CMA_SIZE_MBYTES CONFIG_CMA_SIZE_MBYTES
1528#else
1529#define CMA_SIZE_MBYTES 0
1530#endif
1531
1532static __init int nfit_test_init(void) 1638static __init int nfit_test_init(void)
1533{ 1639{
1534 int rc, i; 1640 int rc, i;
1535 1641
1642 nfit_test_dimm = class_create(THIS_MODULE, "nfit_test_dimm");
1643 if (IS_ERR(nfit_test_dimm))
1644 return PTR_ERR(nfit_test_dimm);
1645
1536 nfit_test_setup(nfit_test_lookup); 1646 nfit_test_setup(nfit_test_lookup);
1537 1647
1538 for (i = 0; i < NUM_NFITS; i++) { 1648 for (i = 0; i < NUM_NFITS; i++) {
1539 struct nfit_test *nfit_test; 1649 struct nfit_test *nfit_test;
1540 struct platform_device *pdev; 1650 struct platform_device *pdev;
1541 static int once;
1542 1651
1543 nfit_test = kzalloc(sizeof(*nfit_test), GFP_KERNEL); 1652 nfit_test = kzalloc(sizeof(*nfit_test), GFP_KERNEL);
1544 if (!nfit_test) { 1653 if (!nfit_test) {
@@ -1577,20 +1686,6 @@ static __init int nfit_test_init(void)
1577 goto err_register; 1686 goto err_register;
1578 1687
1579 instances[i] = nfit_test; 1688 instances[i] = nfit_test;
1580
1581 if (!once++) {
1582 dma_addr_t dma;
1583 void *buf;
1584
1585 buf = dma_alloc_coherent(&pdev->dev, SZ_128M, &dma,
1586 GFP_KERNEL);
1587 if (!buf) {
1588 rc = -ENOMEM;
1589 dev_warn(&pdev->dev, "need 128M of free cma\n");
1590 goto err_register;
1591 }
1592 dma_free_coherent(&pdev->dev, SZ_128M, buf, dma);
1593 }
1594 } 1689 }
1595 1690
1596 rc = platform_driver_register(&nfit_test_driver); 1691 rc = platform_driver_register(&nfit_test_driver);
@@ -1614,6 +1709,7 @@ static __exit void nfit_test_exit(void)
1614 for (i = 0; i < NUM_NFITS; i++) 1709 for (i = 0; i < NUM_NFITS; i++)
1615 platform_device_unregister(&instances[i]->pdev); 1710 platform_device_unregister(&instances[i]->pdev);
1616 nfit_test_teardown(); 1711 nfit_test_teardown();
1712 class_destroy(nfit_test_dimm);
1617} 1713}
1618 1714
1619module_init(nfit_test_init); 1715module_init(nfit_test_init);
diff --git a/tools/testing/nvdimm/test/nfit_test.h b/tools/testing/nvdimm/test/nfit_test.h
index 96c5e16d7db9..c281dd2e5e2d 100644
--- a/tools/testing/nvdimm/test/nfit_test.h
+++ b/tools/testing/nvdimm/test/nfit_test.h
@@ -12,11 +12,22 @@
12 */ 12 */
13#ifndef __NFIT_TEST_H__ 13#ifndef __NFIT_TEST_H__
14#define __NFIT_TEST_H__ 14#define __NFIT_TEST_H__
15#include <linux/list.h>
16#include <linux/ioport.h>
17#include <linux/spinlock_types.h>
18
19struct nfit_test_request {
20 struct list_head list;
21 struct resource res;
22};
15 23
16struct nfit_test_resource { 24struct nfit_test_resource {
25 struct list_head requests;
17 struct list_head list; 26 struct list_head list;
18 struct resource *res; 27 struct resource res;
19 struct device *dev; 28 struct device *dev;
29 spinlock_t lock;
30 int req_count;
20 void *buf; 31 void *buf;
21}; 32};
22 33
@@ -26,4 +37,5 @@ void __iomem *__wrap_ioremap_nocache(resource_size_t offset,
26void __wrap_iounmap(volatile void __iomem *addr); 37void __wrap_iounmap(volatile void __iomem *addr);
27void nfit_test_setup(nfit_test_lookup_fn lookup); 38void nfit_test_setup(nfit_test_lookup_fn lookup);
28void nfit_test_teardown(void); 39void nfit_test_teardown(void);
40struct nfit_test_resource *get_nfit_res(resource_size_t resource);
29#endif 41#endif
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile
index 3b530467148e..f2e07f2fd4b4 100644
--- a/tools/testing/radix-tree/Makefile
+++ b/tools/testing/radix-tree/Makefile
@@ -1,9 +1,10 @@
1 1
2CFLAGS += -I. -g -Wall -D_LGPL_SOURCE 2CFLAGS += -I. -g -O2 -Wall -D_LGPL_SOURCE
3LDFLAGS += -lpthread -lurcu 3LDFLAGS += -lpthread -lurcu
4TARGETS = main 4TARGETS = main
5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \ 5OFILES = main.o radix-tree.o linux.o test.o tag_check.o find_next_bit.o \
6 regression1.o regression2.o regression3.o multiorder.o 6 regression1.o regression2.o regression3.o multiorder.o \
7 iteration_check.o
7 8
8targets: $(TARGETS) 9targets: $(TARGETS)
9 10
diff --git a/tools/testing/radix-tree/iteration_check.c b/tools/testing/radix-tree/iteration_check.c
new file mode 100644
index 000000000000..9adb8e7415a6
--- /dev/null
+++ b/tools/testing/radix-tree/iteration_check.c
@@ -0,0 +1,180 @@
1/*
2 * iteration_check.c: test races having to do with radix tree iteration
3 * Copyright (c) 2016 Intel Corporation
4 * Author: Ross Zwisler <ross.zwisler@linux.intel.com>
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 */
15#include <linux/radix-tree.h>
16#include <pthread.h>
17#include "test.h"
18
19#define NUM_THREADS 4
20#define TAG 0
21static pthread_mutex_t tree_lock = PTHREAD_MUTEX_INITIALIZER;
22static pthread_t threads[NUM_THREADS];
23RADIX_TREE(tree, GFP_KERNEL);
24bool test_complete;
25
26/* relentlessly fill the tree with tagged entries */
27static void *add_entries_fn(void *arg)
28{
29 int pgoff;
30
31 while (!test_complete) {
32 for (pgoff = 0; pgoff < 100; pgoff++) {
33 pthread_mutex_lock(&tree_lock);
34 if (item_insert(&tree, pgoff) == 0)
35 item_tag_set(&tree, pgoff, TAG);
36 pthread_mutex_unlock(&tree_lock);
37 }
38 }
39
40 return NULL;
41}
42
43/*
44 * Iterate over the tagged entries, doing a radix_tree_iter_retry() as we find
45 * things that have been removed and randomly resetting our iteration to the
46 * next chunk with radix_tree_iter_next(). Both radix_tree_iter_retry() and
47 * radix_tree_iter_next() cause radix_tree_next_slot() to be called with a
48 * NULL 'slot' variable.
49 */
50static void *tagged_iteration_fn(void *arg)
51{
52 struct radix_tree_iter iter;
53 void **slot;
54
55 while (!test_complete) {
56 rcu_read_lock();
57 radix_tree_for_each_tagged(slot, &tree, &iter, 0, TAG) {
58 void *entry;
59 int i;
60
61 /* busy wait to let removals happen */
62 for (i = 0; i < 1000000; i++)
63 ;
64
65 entry = radix_tree_deref_slot(slot);
66 if (unlikely(!entry))
67 continue;
68
69 if (radix_tree_deref_retry(entry)) {
70 slot = radix_tree_iter_retry(&iter);
71 continue;
72 }
73
74 if (rand() % 50 == 0)
75 slot = radix_tree_iter_next(&iter);
76 }
77 rcu_read_unlock();
78 }
79
80 return NULL;
81}
82
83/*
84 * Iterate over the entries, doing a radix_tree_iter_retry() as we find things
85 * that have been removed and randomly resetting our iteration to the next
86 * chunk with radix_tree_iter_next(). Both radix_tree_iter_retry() and
87 * radix_tree_iter_next() cause radix_tree_next_slot() to be called with a
88 * NULL 'slot' variable.
89 */
90static void *untagged_iteration_fn(void *arg)
91{
92 struct radix_tree_iter iter;
93 void **slot;
94
95 while (!test_complete) {
96 rcu_read_lock();
97 radix_tree_for_each_slot(slot, &tree, &iter, 0) {
98 void *entry;
99 int i;
100
101 /* busy wait to let removals happen */
102 for (i = 0; i < 1000000; i++)
103 ;
104
105 entry = radix_tree_deref_slot(slot);
106 if (unlikely(!entry))
107 continue;
108
109 if (radix_tree_deref_retry(entry)) {
110 slot = radix_tree_iter_retry(&iter);
111 continue;
112 }
113
114 if (rand() % 50 == 0)
115 slot = radix_tree_iter_next(&iter);
116 }
117 rcu_read_unlock();
118 }
119
120 return NULL;
121}
122
123/*
124 * Randomly remove entries to help induce radix_tree_iter_retry() calls in the
125 * two iteration functions.
126 */
127static void *remove_entries_fn(void *arg)
128{
129 while (!test_complete) {
130 int pgoff;
131
132 pgoff = rand() % 100;
133
134 pthread_mutex_lock(&tree_lock);
135 item_delete(&tree, pgoff);
136 pthread_mutex_unlock(&tree_lock);
137 }
138
139 return NULL;
140}
141
142/* This is a unit test for a bug found by the syzkaller tester */
143void iteration_test(void)
144{
145 int i;
146
147 printf("Running iteration tests for 10 seconds\n");
148
149 srand(time(0));
150 test_complete = false;
151
152 if (pthread_create(&threads[0], NULL, tagged_iteration_fn, NULL)) {
153 perror("pthread_create");
154 exit(1);
155 }
156 if (pthread_create(&threads[1], NULL, untagged_iteration_fn, NULL)) {
157 perror("pthread_create");
158 exit(1);
159 }
160 if (pthread_create(&threads[2], NULL, add_entries_fn, NULL)) {
161 perror("pthread_create");
162 exit(1);
163 }
164 if (pthread_create(&threads[3], NULL, remove_entries_fn, NULL)) {
165 perror("pthread_create");
166 exit(1);
167 }
168
169 sleep(10);
170 test_complete = true;
171
172 for (i = 0; i < NUM_THREADS; i++) {
173 if (pthread_join(threads[i], NULL)) {
174 perror("pthread_join");
175 exit(1);
176 }
177 }
178
179 item_kill_tree(&tree);
180}
diff --git a/tools/testing/radix-tree/linux/cpu.h b/tools/testing/radix-tree/linux/cpu.h
index 60a40459f269..7cf412103205 100644
--- a/tools/testing/radix-tree/linux/cpu.h
+++ b/tools/testing/radix-tree/linux/cpu.h
@@ -7,19 +7,8 @@
7#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */ 7#define CPU_DOWN_PREPARE 0x0005 /* CPU (unsigned)v going down */
8#define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */ 8#define CPU_DOWN_FAILED 0x0006 /* CPU (unsigned)v NOT going down */
9#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */ 9#define CPU_DEAD 0x0007 /* CPU (unsigned)v dead */
10#define CPU_DYING 0x0008 /* CPU (unsigned)v not running any task,
11 * not handling interrupts, soon dead.
12 * Called on the dying cpu, interrupts
13 * are already disabled. Must not
14 * sleep, must not fail */
15#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug 10#define CPU_POST_DEAD 0x0009 /* CPU (unsigned)v dead, cpu_hotplug
16 * lock is dropped */ 11 * lock is dropped */
17#define CPU_STARTING 0x000A /* CPU (unsigned)v soon running.
18 * Called on the new cpu, just before
19 * enabling interrupts. Must not sleep,
20 * must not fail */
21#define CPU_DYING_IDLE 0x000B /* CPU (unsigned)v dying, reached
22 * idle loop. */
23#define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly, 12#define CPU_BROKEN 0x000C /* CPU (unsigned)v did not die properly,
24 * perhaps due to preemption. */ 13 * perhaps due to preemption. */
25#define CPU_TASKS_FROZEN 0x0010 14#define CPU_TASKS_FROZEN 0x0010
@@ -30,5 +19,3 @@
30#define CPU_DOWN_PREPARE_FROZEN (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN) 19#define CPU_DOWN_PREPARE_FROZEN (CPU_DOWN_PREPARE | CPU_TASKS_FROZEN)
31#define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN) 20#define CPU_DOWN_FAILED_FROZEN (CPU_DOWN_FAILED | CPU_TASKS_FROZEN)
32#define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN) 21#define CPU_DEAD_FROZEN (CPU_DEAD | CPU_TASKS_FROZEN)
33#define CPU_DYING_FROZEN (CPU_DYING | CPU_TASKS_FROZEN)
34#define CPU_STARTING_FROZEN (CPU_STARTING | CPU_TASKS_FROZEN)
diff --git a/tools/testing/radix-tree/linux/gfp.h b/tools/testing/radix-tree/linux/gfp.h
index 0e37f7a760eb..5201b915f631 100644
--- a/tools/testing/radix-tree/linux/gfp.h
+++ b/tools/testing/radix-tree/linux/gfp.h
@@ -1,7 +1,7 @@
1#ifndef _GFP_H 1#ifndef _GFP_H
2#define _GFP_H 2#define _GFP_H
3 3
4#define __GFP_BITS_SHIFT 22 4#define __GFP_BITS_SHIFT 26
5#define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) 5#define __GFP_BITS_MASK ((gfp_t)((1 << __GFP_BITS_SHIFT) - 1))
6#define __GFP_WAIT 1 6#define __GFP_WAIT 1
7#define __GFP_ACCOUNT 0 7#define __GFP_ACCOUNT 0
diff --git a/tools/testing/radix-tree/main.c b/tools/testing/radix-tree/main.c
index b7619ff3b552..daa9010693e8 100644
--- a/tools/testing/radix-tree/main.c
+++ b/tools/testing/radix-tree/main.c
@@ -332,6 +332,7 @@ int main(int argc, char **argv)
332 regression1_test(); 332 regression1_test();
333 regression2_test(); 333 regression2_test();
334 regression3_test(); 334 regression3_test();
335 iteration_test();
335 single_thread_tests(long_run); 336 single_thread_tests(long_run);
336 337
337 sleep(1); 338 sleep(1);
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c
index 39d9b9568fe2..05d7bc488971 100644
--- a/tools/testing/radix-tree/multiorder.c
+++ b/tools/testing/radix-tree/multiorder.c
@@ -124,6 +124,8 @@ static void multiorder_check(unsigned long index, int order)
124 unsigned long i; 124 unsigned long i;
125 unsigned long min = index & ~((1UL << order) - 1); 125 unsigned long min = index & ~((1UL << order) - 1);
126 unsigned long max = min + (1UL << order); 126 unsigned long max = min + (1UL << order);
127 void **slot;
128 struct item *item2 = item_create(min);
127 RADIX_TREE(tree, GFP_KERNEL); 129 RADIX_TREE(tree, GFP_KERNEL);
128 130
129 printf("Multiorder index %ld, order %d\n", index, order); 131 printf("Multiorder index %ld, order %d\n", index, order);
@@ -139,13 +141,19 @@ static void multiorder_check(unsigned long index, int order)
139 item_check_absent(&tree, i); 141 item_check_absent(&tree, i);
140 for (i = max; i < 2*max; i++) 142 for (i = max; i < 2*max; i++)
141 item_check_absent(&tree, i); 143 item_check_absent(&tree, i);
144 for (i = min; i < max; i++)
145 assert(radix_tree_insert(&tree, i, item2) == -EEXIST);
146
147 slot = radix_tree_lookup_slot(&tree, index);
148 free(*slot);
149 radix_tree_replace_slot(slot, item2);
142 for (i = min; i < max; i++) { 150 for (i = min; i < max; i++) {
143 static void *entry = (void *) 151 struct item *item = item_lookup(&tree, i);
144 (0xA0 | RADIX_TREE_EXCEPTIONAL_ENTRY); 152 assert(item != 0);
145 assert(radix_tree_insert(&tree, i, entry) == -EEXIST); 153 assert(item->index == min);
146 } 154 }
147 155
148 assert(item_delete(&tree, index) != 0); 156 assert(item_delete(&tree, min) != 0);
149 157
150 for (i = 0; i < 2*max; i++) 158 for (i = 0; i < 2*max; i++)
151 item_check_absent(&tree, i); 159 item_check_absent(&tree, i);
diff --git a/tools/testing/radix-tree/regression1.c b/tools/testing/radix-tree/regression1.c
index 2d03a63bb79c..0d6813a61b37 100644
--- a/tools/testing/radix-tree/regression1.c
+++ b/tools/testing/radix-tree/regression1.c
@@ -43,7 +43,7 @@
43#include "regression.h" 43#include "regression.h"
44 44
45static RADIX_TREE(mt_tree, GFP_KERNEL); 45static RADIX_TREE(mt_tree, GFP_KERNEL);
46static pthread_mutex_t mt_lock; 46static pthread_mutex_t mt_lock = PTHREAD_MUTEX_INITIALIZER;
47 47
48struct page { 48struct page {
49 pthread_mutex_t lock; 49 pthread_mutex_t lock;
diff --git a/tools/testing/radix-tree/tag_check.c b/tools/testing/radix-tree/tag_check.c
index b7447ceb75e9..b0ac05741750 100644
--- a/tools/testing/radix-tree/tag_check.c
+++ b/tools/testing/radix-tree/tag_check.c
@@ -122,7 +122,7 @@ enum {
122 NODE_TAGGED = 2, 122 NODE_TAGGED = 2,
123}; 123};
124 124
125#define THRASH_SIZE 1000 * 1000 125#define THRASH_SIZE (1000 * 1000)
126#define N 127 126#define N 127
127#define BATCH 33 127#define BATCH 33
128 128
diff --git a/tools/testing/radix-tree/test.h b/tools/testing/radix-tree/test.h
index e85131369723..217fb2403f09 100644
--- a/tools/testing/radix-tree/test.h
+++ b/tools/testing/radix-tree/test.h
@@ -27,6 +27,7 @@ void item_kill_tree(struct radix_tree_root *root);
27 27
28void tag_check(void); 28void tag_check(void);
29void multiorder_checks(void); 29void multiorder_checks(void);
30void iteration_test(void);
30 31
31struct item * 32struct item *
32item_tag_set(struct radix_tree_root *root, unsigned long index, int tag); 33item_tag_set(struct radix_tree_root *root, unsigned long index, int tag);
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index ff9e5f20a5a7..f770dba2a6f6 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -15,6 +15,7 @@ TARGETS += memory-hotplug
15TARGETS += mount 15TARGETS += mount
16TARGETS += mqueue 16TARGETS += mqueue
17TARGETS += net 17TARGETS += net
18TARGETS += nsfs
18TARGETS += powerpc 19TARGETS += powerpc
19TARGETS += pstore 20TARGETS += pstore
20TARGETS += ptrace 21TARGETS += ptrace
diff --git a/tools/testing/selftests/exec/Makefile b/tools/testing/selftests/exec/Makefile
index 4e400eb83657..d4300602bf37 100644
--- a/tools/testing/selftests/exec/Makefile
+++ b/tools/testing/selftests/exec/Makefile
@@ -18,7 +18,8 @@ execveat.denatured: execveat
18 $(CC) $(CFLAGS) -o $@ $^ 18 $(CC) $(CFLAGS) -o $@ $^
19 19
20TEST_PROGS := execveat 20TEST_PROGS := execveat
21TEST_FILES := $(DEPS) 21# Makefile is a run-time dependency, since it's accessed by the execveat test
22TEST_FILES := $(DEPS) Makefile
22 23
23include ../lib.mk 24include ../lib.mk
24 25
diff --git a/tools/testing/selftests/filesystems/.gitignore b/tools/testing/selftests/filesystems/.gitignore
new file mode 100644
index 000000000000..31d6e426b6d4
--- /dev/null
+++ b/tools/testing/selftests/filesystems/.gitignore
@@ -0,0 +1 @@
dnotify_test
diff --git a/tools/testing/selftests/filesystems/Makefile b/tools/testing/selftests/filesystems/Makefile
new file mode 100644
index 000000000000..0ab11307b414
--- /dev/null
+++ b/tools/testing/selftests/filesystems/Makefile
@@ -0,0 +1,7 @@
1TEST_PROGS := dnotify_test
2all: $(TEST_PROGS)
3
4include ../lib.mk
5
6clean:
7 rm -fr $(TEST_PROGS)
diff --git a/tools/testing/selftests/filesystems/dnotify_test.c b/tools/testing/selftests/filesystems/dnotify_test.c
new file mode 100644
index 000000000000..8b37b4a1e18d
--- /dev/null
+++ b/tools/testing/selftests/filesystems/dnotify_test.c
@@ -0,0 +1,34 @@
1#define _GNU_SOURCE /* needed to get the defines */
2#include <fcntl.h> /* in glibc 2.2 this has the needed
3 values defined */
4#include <signal.h>
5#include <stdio.h>
6#include <unistd.h>
7
8static volatile int event_fd;
9
10static void handler(int sig, siginfo_t *si, void *data)
11{
12 event_fd = si->si_fd;
13}
14
15int main(void)
16{
17 struct sigaction act;
18 int fd;
19
20 act.sa_sigaction = handler;
21 sigemptyset(&act.sa_mask);
22 act.sa_flags = SA_SIGINFO;
23 sigaction(SIGRTMIN + 1, &act, NULL);
24
25 fd = open(".", O_RDONLY);
26 fcntl(fd, F_SETSIG, SIGRTMIN + 1);
27 fcntl(fd, F_NOTIFY, DN_MODIFY|DN_CREATE|DN_MULTISHOT);
28 /* we will now be notified if any of the files
29 in "." is modified or new files are created */
30 while (1) {
31 pause();
32 printf("Got event on fd=%d\n", event_fd);
33 }
34}
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
index c2b61c4fda11..0bf5085281f3 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist-mod.tc
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then
23 exit_unsupported 23 exit_unsupported
24fi 24fi
25 25
26reset_tracer 26if [ ! -f events/sched/sched_process_fork/hist ]; then
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported" 27 echo "hist trigger is not supported"
32 exit_unsupported 28 exit_unsupported
33fi 29fi
34 30
31reset_tracer
32do_reset
33
35echo "Test histogram with execname modifier" 34echo "Test histogram with execname modifier"
36 35
37echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger 36echo 'hist:keys=common_pid.execname' > events/sched/sched_process_fork/trigger
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
index b2902d42a537..a00184cd9c95 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-hist.tc
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then
23 exit_unsupported 23 exit_unsupported
24fi 24fi
25 25
26reset_tracer 26if [ ! -f events/sched/sched_process_fork/hist ]; then
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported" 27 echo "hist trigger is not supported"
32 exit_unsupported 28 exit_unsupported
33fi 29fi
34 30
31reset_tracer
32do_reset
33
35echo "Test histogram basic tigger" 34echo "Test histogram basic tigger"
36 35
37echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger 36echo 'hist:keys=parent_pid:vals=child_pid' > events/sched/sched_process_fork/trigger
diff --git a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
index 03c4a46561fc..3478b00ead57 100644
--- a/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
+++ b/tools/testing/selftests/ftrace/test.d/trigger/trigger-multihist.tc
@@ -23,15 +23,14 @@ if [ ! -f events/sched/sched_process_fork/trigger ]; then
23 exit_unsupported 23 exit_unsupported
24fi 24fi
25 25
26reset_tracer 26if [ ! -f events/sched/sched_process_fork/hist ]; then
27do_reset
28
29FEATURE=`grep hist events/sched/sched_process_fork/trigger`
30if [ -z "$FEATURE" ]; then
31 echo "hist trigger is not supported" 27 echo "hist trigger is not supported"
32 exit_unsupported 28 exit_unsupported
33fi 29fi
34 30
31reset_tracer
32do_reset
33
35reset_trigger 34reset_trigger
36 35
37echo "Test histogram multiple tiggers" 36echo "Test histogram multiple tiggers"
diff --git a/tools/testing/selftests/futex/functional/run.sh b/tools/testing/selftests/futex/functional/run.sh
index e87dbe2a0b0d..7ff002eed624 100755
--- a/tools/testing/selftests/futex/functional/run.sh
+++ b/tools/testing/selftests/futex/functional/run.sh
@@ -24,7 +24,7 @@
24 24
25# Test for a color capable console 25# Test for a color capable console
26if [ -z "$USE_COLOR" ]; then 26if [ -z "$USE_COLOR" ]; then
27 tput setf 7 27 tput setf 7 || tput setaf 7
28 if [ $? -eq 0 ]; then 28 if [ $? -eq 0 ]; then
29 USE_COLOR=1 29 USE_COLOR=1
30 tput sgr0 30 tput sgr0
diff --git a/tools/testing/selftests/futex/run.sh b/tools/testing/selftests/futex/run.sh
index 4126312ad64e..88bcb1767362 100755
--- a/tools/testing/selftests/futex/run.sh
+++ b/tools/testing/selftests/futex/run.sh
@@ -23,7 +23,7 @@
23 23
24# Test for a color capable shell and pass the result to the subdir scripts 24# Test for a color capable shell and pass the result to the subdir scripts
25USE_COLOR=0 25USE_COLOR=0
26tput setf 7 26tput setf 7 || tput setaf 7
27if [ $? -eq 0 ]; then 27if [ $? -eq 0 ]; then
28 USE_COLOR=1 28 USE_COLOR=1
29 tput sgr0 29 tput sgr0
diff --git a/tools/testing/selftests/ia64/.gitignore b/tools/testing/selftests/ia64/.gitignore
new file mode 100644
index 000000000000..ab806edc8732
--- /dev/null
+++ b/tools/testing/selftests/ia64/.gitignore
@@ -0,0 +1 @@
aliasing-test
diff --git a/tools/testing/selftests/ia64/Makefile b/tools/testing/selftests/ia64/Makefile
new file mode 100644
index 000000000000..2b3de2d3e945
--- /dev/null
+++ b/tools/testing/selftests/ia64/Makefile
@@ -0,0 +1,8 @@
1TEST_PROGS := aliasing-test
2
3all: $(TEST_PROGS)
4
5include ../lib.mk
6
7clean:
8 rm -fr $(TEST_PROGS)
diff --git a/tools/testing/selftests/ia64/aliasing-test.c b/tools/testing/selftests/ia64/aliasing-test.c
new file mode 100644
index 000000000000..62a190d45f38
--- /dev/null
+++ b/tools/testing/selftests/ia64/aliasing-test.c
@@ -0,0 +1,263 @@
1/*
2 * Exercise /dev/mem mmap cases that have been troublesome in the past
3 *
4 * (c) Copyright 2007 Hewlett-Packard Development Company, L.P.
5 * Bjorn Helgaas <bjorn.helgaas@hp.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12#include <stdlib.h>
13#include <stdio.h>
14#include <sys/types.h>
15#include <dirent.h>
16#include <fcntl.h>
17#include <fnmatch.h>
18#include <string.h>
19#include <sys/ioctl.h>
20#include <sys/mman.h>
21#include <sys/stat.h>
22#include <unistd.h>
23#include <linux/pci.h>
24
25int sum;
26
27static int map_mem(char *path, off_t offset, size_t length, int touch)
28{
29 int fd, rc;
30 void *addr;
31 int *c;
32
33 fd = open(path, O_RDWR);
34 if (fd == -1) {
35 perror(path);
36 return -1;
37 }
38
39 if (fnmatch("/proc/bus/pci/*", path, 0) == 0) {
40 rc = ioctl(fd, PCIIOC_MMAP_IS_MEM);
41 if (rc == -1)
42 perror("PCIIOC_MMAP_IS_MEM ioctl");
43 }
44
45 addr = mmap(NULL, length, PROT_READ|PROT_WRITE, MAP_SHARED, fd, offset);
46 if (addr == MAP_FAILED)
47 return 1;
48
49 if (touch) {
50 c = (int *) addr;
51 while (c < (int *) (addr + length))
52 sum += *c++;
53 }
54
55 rc = munmap(addr, length);
56 if (rc == -1) {
57 perror("munmap");
58 return -1;
59 }
60
61 close(fd);
62 return 0;
63}
64
65static int scan_tree(char *path, char *file, off_t offset, size_t length, int touch)
66{
67 struct dirent **namelist;
68 char *name, *path2;
69 int i, n, r, rc = 0, result = 0;
70 struct stat buf;
71
72 n = scandir(path, &namelist, 0, alphasort);
73 if (n < 0) {
74 perror("scandir");
75 return -1;
76 }
77
78 for (i = 0; i < n; i++) {
79 name = namelist[i]->d_name;
80
81 if (fnmatch(".", name, 0) == 0)
82 goto skip;
83 if (fnmatch("..", name, 0) == 0)
84 goto skip;
85
86 path2 = malloc(strlen(path) + strlen(name) + 3);
87 strcpy(path2, path);
88 strcat(path2, "/");
89 strcat(path2, name);
90
91 if (fnmatch(file, name, 0) == 0) {
92 rc = map_mem(path2, offset, length, touch);
93 if (rc == 0)
94 fprintf(stderr, "PASS: %s 0x%lx-0x%lx is %s\n", path2, offset, offset + length, touch ? "readable" : "mappable");
95 else if (rc > 0)
96 fprintf(stderr, "PASS: %s 0x%lx-0x%lx not mappable\n", path2, offset, offset + length);
97 else {
98 fprintf(stderr, "FAIL: %s 0x%lx-0x%lx not accessible\n", path2, offset, offset + length);
99 return rc;
100 }
101 } else {
102 r = lstat(path2, &buf);
103 if (r == 0 && S_ISDIR(buf.st_mode)) {
104 rc = scan_tree(path2, file, offset, length, touch);
105 if (rc < 0)
106 return rc;
107 }
108 }
109
110 result |= rc;
111 free(path2);
112
113skip:
114 free(namelist[i]);
115 }
116 free(namelist);
117 return result;
118}
119
120char buf[1024];
121
122static int read_rom(char *path)
123{
124 int fd, rc;
125 size_t size = 0;
126
127 fd = open(path, O_RDWR);
128 if (fd == -1) {
129 perror(path);
130 return -1;
131 }
132
133 rc = write(fd, "1", 2);
134 if (rc <= 0) {
135 close(fd);
136 perror("write");
137 return -1;
138 }
139
140 do {
141 rc = read(fd, buf, sizeof(buf));
142 if (rc > 0)
143 size += rc;
144 } while (rc > 0);
145
146 close(fd);
147 return size;
148}
149
150static int scan_rom(char *path, char *file)
151{
152 struct dirent **namelist;
153 char *name, *path2;
154 int i, n, r, rc = 0, result = 0;
155 struct stat buf;
156
157 n = scandir(path, &namelist, 0, alphasort);
158 if (n < 0) {
159 perror("scandir");
160 return -1;
161 }
162
163 for (i = 0; i < n; i++) {
164 name = namelist[i]->d_name;
165
166 if (fnmatch(".", name, 0) == 0)
167 goto skip;
168 if (fnmatch("..", name, 0) == 0)
169 goto skip;
170
171 path2 = malloc(strlen(path) + strlen(name) + 3);
172 strcpy(path2, path);
173 strcat(path2, "/");
174 strcat(path2, name);
175
176 if (fnmatch(file, name, 0) == 0) {
177 rc = read_rom(path2);
178
179 /*
180 * It's OK if the ROM is unreadable. Maybe there
181 * is no ROM, or some other error occurred. The
182 * important thing is that no MCA happened.
183 */
184 if (rc > 0)
185 fprintf(stderr, "PASS: %s read %d bytes\n", path2, rc);
186 else {
187 fprintf(stderr, "PASS: %s not readable\n", path2);
188 return rc;
189 }
190 } else {
191 r = lstat(path2, &buf);
192 if (r == 0 && S_ISDIR(buf.st_mode)) {
193 rc = scan_rom(path2, file);
194 if (rc < 0)
195 return rc;
196 }
197 }
198
199 result |= rc;
200 free(path2);
201
202skip:
203 free(namelist[i]);
204 }
205 free(namelist);
206 return result;
207}
208
209int main(void)
210{
211 int rc;
212
213 if (map_mem("/dev/mem", 0, 0xA0000, 1) == 0)
214 fprintf(stderr, "PASS: /dev/mem 0x0-0xa0000 is readable\n");
215 else
216 fprintf(stderr, "FAIL: /dev/mem 0x0-0xa0000 not accessible\n");
217
218 /*
219 * It's not safe to blindly read the VGA frame buffer. If you know
220 * how to poke the card the right way, it should respond, but it's
221 * not safe in general. Many machines, e.g., Intel chipsets, cover
222 * up a non-responding card by just returning -1, but others will
223 * report the failure as a machine check.
224 */
225 if (map_mem("/dev/mem", 0xA0000, 0x20000, 0) == 0)
226 fprintf(stderr, "PASS: /dev/mem 0xa0000-0xc0000 is mappable\n");
227 else
228 fprintf(stderr, "FAIL: /dev/mem 0xa0000-0xc0000 not accessible\n");
229
230 if (map_mem("/dev/mem", 0xC0000, 0x40000, 1) == 0)
231 fprintf(stderr, "PASS: /dev/mem 0xc0000-0x100000 is readable\n");
232 else
233 fprintf(stderr, "FAIL: /dev/mem 0xc0000-0x100000 not accessible\n");
234
235 /*
236 * Often you can map all the individual pieces above (0-0xA0000,
237 * 0xA0000-0xC0000, and 0xC0000-0x100000), but can't map the whole
238 * thing at once. This is because the individual pieces use different
239 * attributes, and there's no single attribute supported over the
240 * whole region.
241 */
242 rc = map_mem("/dev/mem", 0, 1024*1024, 0);
243 if (rc == 0)
244 fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 is mappable\n");
245 else if (rc > 0)
246 fprintf(stderr, "PASS: /dev/mem 0x0-0x100000 not mappable\n");
247 else
248 fprintf(stderr, "FAIL: /dev/mem 0x0-0x100000 not accessible\n");
249
250 scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 0xA0000, 1);
251 scan_tree("/sys/class/pci_bus", "legacy_mem", 0xA0000, 0x20000, 0);
252 scan_tree("/sys/class/pci_bus", "legacy_mem", 0xC0000, 0x40000, 1);
253 scan_tree("/sys/class/pci_bus", "legacy_mem", 0, 1024*1024, 0);
254
255 scan_rom("/sys/devices", "rom");
256
257 scan_tree("/proc/bus/pci", "??.?", 0, 0xA0000, 1);
258 scan_tree("/proc/bus/pci", "??.?", 0xA0000, 0x20000, 0);
259 scan_tree("/proc/bus/pci", "??.?", 0xC0000, 0x40000, 1);
260 scan_tree("/proc/bus/pci", "??.?", 0, 1024*1024, 0);
261
262 return rc;
263}
diff --git a/tools/testing/selftests/lib/printf.sh b/tools/testing/selftests/lib/printf.sh
index 4fdc70fe6980..4fdc70fe6980 100644..100755
--- a/tools/testing/selftests/lib/printf.sh
+++ b/tools/testing/selftests/lib/printf.sh
diff --git a/tools/testing/selftests/media_tests/.gitignore b/tools/testing/selftests/media_tests/.gitignore
index 1c0711708b98..8745eba39012 100644
--- a/tools/testing/selftests/media_tests/.gitignore
+++ b/tools/testing/selftests/media_tests/.gitignore
@@ -1 +1,3 @@
1media_device_test 1media_device_test
2media_device_open
3video_device_test
diff --git a/tools/testing/selftests/media_tests/Makefile b/tools/testing/selftests/media_tests/Makefile
index 7071bcc1d066..6b34a0199468 100644
--- a/tools/testing/selftests/media_tests/Makefile
+++ b/tools/testing/selftests/media_tests/Makefile
@@ -1,7 +1,7 @@
1TEST_PROGS := media_device_test 1TEST_PROGS := media_device_test media_device_open video_device_test
2all: $(TEST_PROGS) 2all: $(TEST_PROGS)
3 3
4include ../lib.mk 4include ../lib.mk
5 5
6clean: 6clean:
7 rm -fr media_device_test 7 rm -fr media_device_test media_device_open video_device_test
diff --git a/tools/testing/selftests/media_tests/bind_unbind_sample.sh b/tools/testing/selftests/media_tests/bind_unbind_sample.sh
new file mode 100755
index 000000000000..9f362f10631a
--- /dev/null
+++ b/tools/testing/selftests/media_tests/bind_unbind_sample.sh
@@ -0,0 +1,12 @@
1#!/bin/bash
2# Find device number in /sys/bus/usb/drivers/drivername
3# Edit this file to update the driver numer and name
4# Example test for uvcvideo driver
5#i=0
6# while :; do
7# i=$((i+1))
8# echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/unbind;
9# echo 1-5:1.0 > /sys/bus/usb/drivers/uvcvideo/bind;
10# clear
11# echo $i
12#done
diff --git a/tools/testing/selftests/media_tests/media_device_open.c b/tools/testing/selftests/media_tests/media_device_open.c
new file mode 100644
index 000000000000..44343c091a20
--- /dev/null
+++ b/tools/testing/selftests/media_tests/media_device_open.c
@@ -0,0 +1,81 @@
1/*
2 * media_device_open.c - Media Controller Device Open Test
3 *
4 * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
5 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
6 *
7 * This file is released under the GPLv2.
8 */
9
10/*
11 * This file adds a test for Media Controller API.
12 * This test should be run as root and should not be
13 * included in the Kselftest run. This test should be
14 * run when hardware and driver that makes use Media
15 * Controller API are present in the system.
16 *
17 * This test opens user specified Media Device and calls
18 * MEDIA_IOC_DEVICE_INFO ioctl, closes the file, and exits.
19 *
20 * Usage:
21 * sudo ./media_device_open -d /dev/mediaX
22 *
23 * Run this test is a loop and run bind/unbind on the driver.
24*/
25
26#include <stdio.h>
27#include <unistd.h>
28#include <stdlib.h>
29#include <errno.h>
30#include <string.h>
31#include <fcntl.h>
32#include <sys/ioctl.h>
33#include <sys/stat.h>
34#include <linux/media.h>
35
36int main(int argc, char **argv)
37{
38 int opt;
39 char media_device[256];
40 int count = 0;
41 struct media_device_info mdi;
42 int ret;
43 int fd;
44
45 if (argc < 2) {
46 printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]);
47 exit(-1);
48 }
49
50 /* Process arguments */
51 while ((opt = getopt(argc, argv, "d:")) != -1) {
52 switch (opt) {
53 case 'd':
54 strncpy(media_device, optarg, sizeof(media_device) - 1);
55 media_device[sizeof(media_device)-1] = '\0';
56 break;
57 default:
58 printf("Usage: %s [-d </dev/mediaX>]\n", argv[0]);
59 exit(-1);
60 }
61 }
62
63 if (getuid() != 0) {
64 printf("Please run the test as root - Exiting.\n");
65 exit(-1);
66 }
67
68 /* Open Media device and keep it open */
69 fd = open(media_device, O_RDWR);
70 if (fd == -1) {
71 printf("Media Device open errno %s\n", strerror(errno));
72 exit(-1);
73 }
74
75 ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
76 if (ret < 0)
77 printf("Media Device Info errno %s\n", strerror(errno));
78 else
79 printf("Media device model %s driver %s\n",
80 mdi.model, mdi.driver);
81}
diff --git a/tools/testing/selftests/media_tests/media_device_test.c b/tools/testing/selftests/media_tests/media_device_test.c
index cbf53a032ab5..5d49943e77d0 100644
--- a/tools/testing/selftests/media_tests/media_device_test.c
+++ b/tools/testing/selftests/media_tests/media_device_test.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * media_devkref_test.c - Media Controller Device Kref API Test 2 * media_device_test.c - Media Controller Device ioctl loop Test
3 * 3 *
4 * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com> 4 * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
5 * Copyright (c) 2016 Samsung Electronics Co., Ltd. 5 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
@@ -35,13 +35,14 @@
35#include <fcntl.h> 35#include <fcntl.h>
36#include <sys/ioctl.h> 36#include <sys/ioctl.h>
37#include <sys/stat.h> 37#include <sys/stat.h>
38#include <time.h>
38#include <linux/media.h> 39#include <linux/media.h>
39 40
40int main(int argc, char **argv) 41int main(int argc, char **argv)
41{ 42{
42 int opt; 43 int opt;
43 char media_device[256]; 44 char media_device[256];
44 int count = 0; 45 int count;
45 struct media_device_info mdi; 46 struct media_device_info mdi;
46 int ret; 47 int ret;
47 int fd; 48 int fd;
@@ -69,6 +70,10 @@ int main(int argc, char **argv)
69 exit(-1); 70 exit(-1);
70 } 71 }
71 72
73 /* Generate random number of interations */
74 srand((unsigned int) time(NULL));
75 count = rand();
76
72 /* Open Media device and keep it open */ 77 /* Open Media device and keep it open */
73 fd = open(media_device, O_RDWR); 78 fd = open(media_device, O_RDWR);
74 if (fd == -1) { 79 if (fd == -1) {
@@ -82,14 +87,16 @@ int main(int argc, char **argv)
82 "other Oops in the dmesg. Enable KaSan kernel\n" 87 "other Oops in the dmesg. Enable KaSan kernel\n"
83 "config option for use-after-free error detection.\n\n"); 88 "config option for use-after-free error detection.\n\n");
84 89
85 while (count < 100) { 90 printf("Running test for %d iternations\n", count);
91
92 while (count > 0) {
86 ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi); 93 ret = ioctl(fd, MEDIA_IOC_DEVICE_INFO, &mdi);
87 if (ret < 0) 94 if (ret < 0)
88 printf("Media Device Info errno %s\n", strerror(errno)); 95 printf("Media Device Info errno %s\n", strerror(errno));
89 else 96 else
90 printf("Media device model %s driver %s\n", 97 printf("Media device model %s driver %s - count %d\n",
91 mdi.model, mdi.driver); 98 mdi.model, mdi.driver, count);
92 sleep(10); 99 sleep(10);
93 count++; 100 count--;
94 } 101 }
95} 102}
diff --git a/tools/testing/selftests/media_tests/open_loop_test.sh b/tools/testing/selftests/media_tests/open_loop_test.sh
new file mode 100755
index 000000000000..dcd3c17efc17
--- /dev/null
+++ b/tools/testing/selftests/media_tests/open_loop_test.sh
@@ -0,0 +1,10 @@
1#!/bin/bash
2 i=0
3file=/dev/media$1
4 while :; do
5 echo $file
6 i=$((i+1))
7 R=$(./media_device_open -d $file);
8 # clear
9 echo -e "Loop $i\n$R"
10 done
diff --git a/tools/testing/selftests/media_tests/regression_test.txt b/tools/testing/selftests/media_tests/regression_test.txt
new file mode 100644
index 000000000000..2627367681f7
--- /dev/null
+++ b/tools/testing/selftests/media_tests/regression_test.txt
@@ -0,0 +1,43 @@
1Testing for regressions in Media Controller API register, ioctl, syscall,
2and unregister paths. There have a few problems that result in user-after
3free on media_device, media_devnode, and cdev pointers when the driver is
4unbound while ioctl is in progress.
5
6Test Procedure:
7
8Run bin/unbind loop while ioctls are in progress.
9Run rmmod and modprobe.
10Disconnect the device.
11
12Setup:
13
14Build media_device_test
15cd tools/testing/selftests/media_tests
16make
17
18Regressions test for cdev user-after free error on /dev/mediaX when driver
19is unbound:
20
21Start media_device_test to regression test media devnode dynamic alloc
22and cdev user-after-free fixes. This opens media dev files and sits in
23a loop running media ioctl MEDIA_IOC_DEVICE_INFO command once every 10
24seconds. The idea is when device file goes away, media devnode and cdev
25should stick around until this test exits.
26
27The test for a random number of iterations or until user kills it with a
28sleep 10 in between the ioctl calls.
29
30sudo ./media_device_test -d /dev/mediaX
31
32Regression test for media_devnode unregister race with ioctl_syscall:
33
34Start 6 open_loop_test.sh tests with different /dev/mediaX files. When
35device file goes away after unbind, device file name changes. Start the
36test with possible device names. If we start with /dev/media0 for example,
37after unbind, /dev/media1 or /dev/media2 could get created. The idea is
38keep ioctls going while bind/unbind runs.
39
40Copy bind_unbind_sample.txt and make changes to specify the driver name
41and number to run bind and unbind. Start the bind_unbind.sh
42
43Run dmesg looking for any user-after free errors or mutex lock errors.
diff --git a/tools/testing/selftests/media_tests/video_device_test.c b/tools/testing/selftests/media_tests/video_device_test.c
new file mode 100644
index 000000000000..66d419c28653
--- /dev/null
+++ b/tools/testing/selftests/media_tests/video_device_test.c
@@ -0,0 +1,100 @@
1/*
2 * video_device_test - Video Device Test
3 *
4 * Copyright (c) 2016 Shuah Khan <shuahkh@osg.samsung.com>
5 * Copyright (c) 2016 Samsung Electronics Co., Ltd.
6 *
7 * This file is released under the GPLv2.
8 */
9
10/*
11 * This file adds a test for Video Device. This test should not be included
12 * in the Kselftest run. This test should be run when hardware and driver
13 * that makes use of V4L2 API is present.
14 *
15 * This test opens user specified Video Device and calls video ioctls in a
16 * loop once every 10 seconds.
17 *
18 * Usage:
19 * sudo ./video_device_test -d /dev/videoX
20 *
21 * While test is running, remove the device or unbind the driver and
22 * ensure there are no use after free errors and other Oops in the
23 * dmesg.
24 * When possible, enable KaSan kernel config option for use-after-free
25 * error detection.
26*/
27
28#include <stdio.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <errno.h>
32#include <string.h>
33#include <fcntl.h>
34#include <sys/ioctl.h>
35#include <sys/stat.h>
36#include <time.h>
37#include <linux/videodev2.h>
38
39int main(int argc, char **argv)
40{
41 int opt;
42 char video_dev[256];
43 int count;
44 struct v4l2_tuner vtuner;
45 struct v4l2_capability vcap;
46 int ret;
47 int fd;
48
49 if (argc < 2) {
50 printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
51 exit(-1);
52 }
53
54 /* Process arguments */
55 while ((opt = getopt(argc, argv, "d:")) != -1) {
56 switch (opt) {
57 case 'd':
58 strncpy(video_dev, optarg, sizeof(video_dev) - 1);
59 video_dev[sizeof(video_dev)-1] = '\0';
60 break;
61 default:
62 printf("Usage: %s [-d </dev/videoX>]\n", argv[0]);
63 exit(-1);
64 }
65 }
66
67 /* Generate random number of interations */
68 srand((unsigned int) time(NULL));
69 count = rand();
70
71 /* Open Video device and keep it open */
72 fd = open(video_dev, O_RDWR);
73 if (fd == -1) {
74 printf("Video Device open errno %s\n", strerror(errno));
75 exit(-1);
76 }
77
78 printf("\nNote:\n"
79 "While test is running, remove the device or unbind\n"
80 "driver and ensure there are no use after free errors\n"
81 "and other Oops in the dmesg. When possible, enable KaSan\n"
82 "kernel config option for use-after-free error detection.\n\n");
83
84 while (count > 0) {
85 ret = ioctl(fd, VIDIOC_QUERYCAP, &vcap);
86 if (ret < 0)
87 printf("VIDIOC_QUERYCAP errno %s\n", strerror(errno));
88 else
89 printf("Video device driver %s\n", vcap.driver);
90
91 ret = ioctl(fd, VIDIOC_G_TUNER, &vtuner);
92 if (ret < 0)
93 printf("VIDIOC_G_TUNER, errno %s\n", strerror(errno));
94 else
95 printf("type %d rangelow %d rangehigh %d\n",
96 vtuner.type, vtuner.rangelow, vtuner.rangehigh);
97 sleep(10);
98 count--;
99 }
100}
diff --git a/tools/testing/selftests/net/reuseport_bpf.c b/tools/testing/selftests/net/reuseport_bpf.c
index 96ba386b1b7b..4a8217448f20 100644
--- a/tools/testing/selftests/net/reuseport_bpf.c
+++ b/tools/testing/selftests/net/reuseport_bpf.c
@@ -111,9 +111,9 @@ static void attach_ebpf(int fd, uint16_t mod)
111 memset(&attr, 0, sizeof(attr)); 111 memset(&attr, 0, sizeof(attr));
112 attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 112 attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
113 attr.insn_cnt = ARRAY_SIZE(prog); 113 attr.insn_cnt = ARRAY_SIZE(prog);
114 attr.insns = (uint64_t)prog; 114 attr.insns = (unsigned long) &prog;
115 attr.license = (uint64_t)bpf_license; 115 attr.license = (unsigned long) &bpf_license;
116 attr.log_buf = (uint64_t)bpf_log_buf; 116 attr.log_buf = (unsigned long) &bpf_log_buf;
117 attr.log_size = sizeof(bpf_log_buf); 117 attr.log_size = sizeof(bpf_log_buf);
118 attr.log_level = 1; 118 attr.log_level = 1;
119 attr.kern_version = 0; 119 attr.kern_version = 0;
@@ -351,8 +351,8 @@ static void test_filter_no_reuseport(const struct test_params p)
351 memset(&eprog, 0, sizeof(eprog)); 351 memset(&eprog, 0, sizeof(eprog));
352 eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER; 352 eprog.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
353 eprog.insn_cnt = ARRAY_SIZE(ecode); 353 eprog.insn_cnt = ARRAY_SIZE(ecode);
354 eprog.insns = (uint64_t)ecode; 354 eprog.insns = (unsigned long) &ecode;
355 eprog.license = (uint64_t)bpf_license; 355 eprog.license = (unsigned long) &bpf_license;
356 eprog.kern_version = 0; 356 eprog.kern_version = 0;
357 357
358 memset(&cprog, 0, sizeof(cprog)); 358 memset(&cprog, 0, sizeof(cprog));
diff --git a/tools/testing/selftests/networking/timestamping/.gitignore b/tools/testing/selftests/networking/timestamping/.gitignore
new file mode 100644
index 000000000000..9e69e982fb38
--- /dev/null
+++ b/tools/testing/selftests/networking/timestamping/.gitignore
@@ -0,0 +1,3 @@
1timestamping
2txtimestamp
3hwtstamp_config
diff --git a/tools/testing/selftests/networking/timestamping/Makefile b/tools/testing/selftests/networking/timestamping/Makefile
new file mode 100644
index 000000000000..ccbb9edbbbb9
--- /dev/null
+++ b/tools/testing/selftests/networking/timestamping/Makefile
@@ -0,0 +1,8 @@
1TEST_PROGS := hwtstamp_config timestamping txtimestamp
2
3all: $(TEST_PROGS)
4
5include ../../lib.mk
6
7clean:
8 rm -fr $(TEST_PROGS)
diff --git a/tools/testing/selftests/networking/timestamping/hwtstamp_config.c b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
new file mode 100644
index 000000000000..e8b685a7f15f
--- /dev/null
+++ b/tools/testing/selftests/networking/timestamping/hwtstamp_config.c
@@ -0,0 +1,134 @@
1/* Test program for SIOC{G,S}HWTSTAMP
2 * Copyright 2013 Solarflare Communications
3 * Author: Ben Hutchings
4 */
5
6#include <errno.h>
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10
11#include <sys/socket.h>
12#include <sys/ioctl.h>
13
14#include <linux/if.h>
15#include <linux/net_tstamp.h>
16#include <linux/sockios.h>
17
18static int
19lookup_value(const char **names, int size, const char *name)
20{
21 int value;
22
23 for (value = 0; value < size; value++)
24 if (names[value] && strcasecmp(names[value], name) == 0)
25 return value;
26
27 return -1;
28}
29
30static const char *
31lookup_name(const char **names, int size, int value)
32{
33 return (value >= 0 && value < size) ? names[value] : NULL;
34}
35
36static void list_names(FILE *f, const char **names, int size)
37{
38 int value;
39
40 for (value = 0; value < size; value++)
41 if (names[value])
42 fprintf(f, " %s\n", names[value]);
43}
44
45static const char *tx_types[] = {
46#define TX_TYPE(name) [HWTSTAMP_TX_ ## name] = #name
47 TX_TYPE(OFF),
48 TX_TYPE(ON),
49 TX_TYPE(ONESTEP_SYNC)
50#undef TX_TYPE
51};
52#define N_TX_TYPES ((int)(sizeof(tx_types) / sizeof(tx_types[0])))
53
54static const char *rx_filters[] = {
55#define RX_FILTER(name) [HWTSTAMP_FILTER_ ## name] = #name
56 RX_FILTER(NONE),
57 RX_FILTER(ALL),
58 RX_FILTER(SOME),
59 RX_FILTER(PTP_V1_L4_EVENT),
60 RX_FILTER(PTP_V1_L4_SYNC),
61 RX_FILTER(PTP_V1_L4_DELAY_REQ),
62 RX_FILTER(PTP_V2_L4_EVENT),
63 RX_FILTER(PTP_V2_L4_SYNC),
64 RX_FILTER(PTP_V2_L4_DELAY_REQ),
65 RX_FILTER(PTP_V2_L2_EVENT),
66 RX_FILTER(PTP_V2_L2_SYNC),
67 RX_FILTER(PTP_V2_L2_DELAY_REQ),
68 RX_FILTER(PTP_V2_EVENT),
69 RX_FILTER(PTP_V2_SYNC),
70 RX_FILTER(PTP_V2_DELAY_REQ),
71#undef RX_FILTER
72};
73#define N_RX_FILTERS ((int)(sizeof(rx_filters) / sizeof(rx_filters[0])))
74
75static void usage(void)
76{
77 fputs("Usage: hwtstamp_config if_name [tx_type rx_filter]\n"
78 "tx_type is any of (case-insensitive):\n",
79 stderr);
80 list_names(stderr, tx_types, N_TX_TYPES);
81 fputs("rx_filter is any of (case-insensitive):\n", stderr);
82 list_names(stderr, rx_filters, N_RX_FILTERS);
83}
84
85int main(int argc, char **argv)
86{
87 struct ifreq ifr;
88 struct hwtstamp_config config;
89 const char *name;
90 int sock;
91
92 if ((argc != 2 && argc != 4) || (strlen(argv[1]) >= IFNAMSIZ)) {
93 usage();
94 return 2;
95 }
96
97 if (argc == 4) {
98 config.flags = 0;
99 config.tx_type = lookup_value(tx_types, N_TX_TYPES, argv[2]);
100 config.rx_filter = lookup_value(rx_filters, N_RX_FILTERS, argv[3]);
101 if (config.tx_type < 0 || config.rx_filter < 0) {
102 usage();
103 return 2;
104 }
105 }
106
107 sock = socket(AF_INET, SOCK_DGRAM, 0);
108 if (sock < 0) {
109 perror("socket");
110 return 1;
111 }
112
113 strcpy(ifr.ifr_name, argv[1]);
114 ifr.ifr_data = (caddr_t)&config;
115
116 if (ioctl(sock, (argc == 2) ? SIOCGHWTSTAMP : SIOCSHWTSTAMP, &ifr)) {
117 perror("ioctl");
118 return 1;
119 }
120
121 printf("flags = %#x\n", config.flags);
122 name = lookup_name(tx_types, N_TX_TYPES, config.tx_type);
123 if (name)
124 printf("tx_type = %s\n", name);
125 else
126 printf("tx_type = %d\n", config.tx_type);
127 name = lookup_name(rx_filters, N_RX_FILTERS, config.rx_filter);
128 if (name)
129 printf("rx_filter = %s\n", name);
130 else
131 printf("rx_filter = %d\n", config.rx_filter);
132
133 return 0;
134}
diff --git a/tools/testing/selftests/networking/timestamping/timestamping.c b/tools/testing/selftests/networking/timestamping/timestamping.c
new file mode 100644
index 000000000000..5cdfd743447b
--- /dev/null
+++ b/tools/testing/selftests/networking/timestamping/timestamping.c
@@ -0,0 +1,528 @@
1/*
2 * This program demonstrates how the various time stamping features in
3 * the Linux kernel work. It emulates the behavior of a PTP
4 * implementation in stand-alone master mode by sending PTPv1 Sync
5 * multicasts once every second. It looks for similar packets, but
6 * beyond that doesn't actually implement PTP.
7 *
8 * Outgoing packets are time stamped with SO_TIMESTAMPING with or
9 * without hardware support.
10 *
11 * Incoming packets are time stamped with SO_TIMESTAMPING with or
12 * without hardware support, SIOCGSTAMP[NS] (per-socket time stamp) and
13 * SO_TIMESTAMP[NS].
14 *
15 * Copyright (C) 2009 Intel Corporation.
16 * Author: Patrick Ohly <patrick.ohly@intel.com>
17 *
18 * This program is free software; you can redistribute it and/or modify it
19 * under the terms and conditions of the GNU General Public License,
20 * version 2, as published by the Free Software Foundation.
21 *
22 * This program is distributed in the hope it will be useful, but WITHOUT
23 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
24 * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
25 * more details.
26 *
27 * You should have received a copy of the GNU General Public License along with
28 * this program; if not, write to the Free Software Foundation, Inc.,
29 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
30 */
31
32#include <stdio.h>
33#include <stdlib.h>
34#include <errno.h>
35#include <string.h>
36
37#include <sys/time.h>
38#include <sys/socket.h>
39#include <sys/select.h>
40#include <sys/ioctl.h>
41#include <arpa/inet.h>
42#include <net/if.h>
43
44#include <asm/types.h>
45#include <linux/net_tstamp.h>
46#include <linux/errqueue.h>
47
48#ifndef SO_TIMESTAMPING
49# define SO_TIMESTAMPING 37
50# define SCM_TIMESTAMPING SO_TIMESTAMPING
51#endif
52
53#ifndef SO_TIMESTAMPNS
54# define SO_TIMESTAMPNS 35
55#endif
56
57#ifndef SIOCGSTAMPNS
58# define SIOCGSTAMPNS 0x8907
59#endif
60
61#ifndef SIOCSHWTSTAMP
62# define SIOCSHWTSTAMP 0x89b0
63#endif
64
65static void usage(const char *error)
66{
67 if (error)
68 printf("invalid option: %s\n", error);
69 printf("timestamping interface option*\n\n"
70 "Options:\n"
71 " IP_MULTICAST_LOOP - looping outgoing multicasts\n"
72 " SO_TIMESTAMP - normal software time stamping, ms resolution\n"
73 " SO_TIMESTAMPNS - more accurate software time stamping\n"
74 " SOF_TIMESTAMPING_TX_HARDWARE - hardware time stamping of outgoing packets\n"
75 " SOF_TIMESTAMPING_TX_SOFTWARE - software fallback for outgoing packets\n"
76 " SOF_TIMESTAMPING_RX_HARDWARE - hardware time stamping of incoming packets\n"
77 " SOF_TIMESTAMPING_RX_SOFTWARE - software fallback for incoming packets\n"
78 " SOF_TIMESTAMPING_SOFTWARE - request reporting of software time stamps\n"
79 " SOF_TIMESTAMPING_RAW_HARDWARE - request reporting of raw HW time stamps\n"
80 " SIOCGSTAMP - check last socket time stamp\n"
81 " SIOCGSTAMPNS - more accurate socket time stamp\n");
82 exit(1);
83}
84
85static void bail(const char *error)
86{
87 printf("%s: %s\n", error, strerror(errno));
88 exit(1);
89}
90
91static const unsigned char sync[] = {
92 0x00, 0x01, 0x00, 0x01,
93 0x5f, 0x44, 0x46, 0x4c,
94 0x54, 0x00, 0x00, 0x00,
95 0x00, 0x00, 0x00, 0x00,
96 0x00, 0x00, 0x00, 0x00,
97 0x01, 0x01,
98
99 /* fake uuid */
100 0x00, 0x01,
101 0x02, 0x03, 0x04, 0x05,
102
103 0x00, 0x01, 0x00, 0x37,
104 0x00, 0x00, 0x00, 0x08,
105 0x00, 0x00, 0x00, 0x00,
106 0x49, 0x05, 0xcd, 0x01,
107 0x29, 0xb1, 0x8d, 0xb0,
108 0x00, 0x00, 0x00, 0x00,
109 0x00, 0x01,
110
111 /* fake uuid */
112 0x00, 0x01,
113 0x02, 0x03, 0x04, 0x05,
114
115 0x00, 0x00, 0x00, 0x37,
116 0x00, 0x00, 0x00, 0x04,
117 0x44, 0x46, 0x4c, 0x54,
118 0x00, 0x00, 0xf0, 0x60,
119 0x00, 0x01, 0x00, 0x00,
120 0x00, 0x00, 0x00, 0x01,
121 0x00, 0x00, 0xf0, 0x60,
122 0x00, 0x00, 0x00, 0x00,
123 0x00, 0x00, 0x00, 0x04,
124 0x44, 0x46, 0x4c, 0x54,
125 0x00, 0x01,
126
127 /* fake uuid */
128 0x00, 0x01,
129 0x02, 0x03, 0x04, 0x05,
130
131 0x00, 0x00, 0x00, 0x00,
132 0x00, 0x00, 0x00, 0x00,
133 0x00, 0x00, 0x00, 0x00,
134 0x00, 0x00, 0x00, 0x00
135};
136
137static void sendpacket(int sock, struct sockaddr *addr, socklen_t addr_len)
138{
139 struct timeval now;
140 int res;
141
142 res = sendto(sock, sync, sizeof(sync), 0,
143 addr, addr_len);
144 gettimeofday(&now, 0);
145 if (res < 0)
146 printf("%s: %s\n", "send", strerror(errno));
147 else
148 printf("%ld.%06ld: sent %d bytes\n",
149 (long)now.tv_sec, (long)now.tv_usec,
150 res);
151}
152
153static void printpacket(struct msghdr *msg, int res,
154 char *data,
155 int sock, int recvmsg_flags,
156 int siocgstamp, int siocgstampns)
157{
158 struct sockaddr_in *from_addr = (struct sockaddr_in *)msg->msg_name;
159 struct cmsghdr *cmsg;
160 struct timeval tv;
161 struct timespec ts;
162 struct timeval now;
163
164 gettimeofday(&now, 0);
165
166 printf("%ld.%06ld: received %s data, %d bytes from %s, %zu bytes control messages\n",
167 (long)now.tv_sec, (long)now.tv_usec,
168 (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
169 res,
170 inet_ntoa(from_addr->sin_addr),
171 msg->msg_controllen);
172 for (cmsg = CMSG_FIRSTHDR(msg);
173 cmsg;
174 cmsg = CMSG_NXTHDR(msg, cmsg)) {
175 printf(" cmsg len %zu: ", cmsg->cmsg_len);
176 switch (cmsg->cmsg_level) {
177 case SOL_SOCKET:
178 printf("SOL_SOCKET ");
179 switch (cmsg->cmsg_type) {
180 case SO_TIMESTAMP: {
181 struct timeval *stamp =
182 (struct timeval *)CMSG_DATA(cmsg);
183 printf("SO_TIMESTAMP %ld.%06ld",
184 (long)stamp->tv_sec,
185 (long)stamp->tv_usec);
186 break;
187 }
188 case SO_TIMESTAMPNS: {
189 struct timespec *stamp =
190 (struct timespec *)CMSG_DATA(cmsg);
191 printf("SO_TIMESTAMPNS %ld.%09ld",
192 (long)stamp->tv_sec,
193 (long)stamp->tv_nsec);
194 break;
195 }
196 case SO_TIMESTAMPING: {
197 struct timespec *stamp =
198 (struct timespec *)CMSG_DATA(cmsg);
199 printf("SO_TIMESTAMPING ");
200 printf("SW %ld.%09ld ",
201 (long)stamp->tv_sec,
202 (long)stamp->tv_nsec);
203 stamp++;
204 /* skip deprecated HW transformed */
205 stamp++;
206 printf("HW raw %ld.%09ld",
207 (long)stamp->tv_sec,
208 (long)stamp->tv_nsec);
209 break;
210 }
211 default:
212 printf("type %d", cmsg->cmsg_type);
213 break;
214 }
215 break;
216 case IPPROTO_IP:
217 printf("IPPROTO_IP ");
218 switch (cmsg->cmsg_type) {
219 case IP_RECVERR: {
220 struct sock_extended_err *err =
221 (struct sock_extended_err *)CMSG_DATA(cmsg);
222 printf("IP_RECVERR ee_errno '%s' ee_origin %d => %s",
223 strerror(err->ee_errno),
224 err->ee_origin,
225#ifdef SO_EE_ORIGIN_TIMESTAMPING
226 err->ee_origin == SO_EE_ORIGIN_TIMESTAMPING ?
227 "bounced packet" : "unexpected origin"
228#else
229 "probably SO_EE_ORIGIN_TIMESTAMPING"
230#endif
231 );
232 if (res < sizeof(sync))
233 printf(" => truncated data?!");
234 else if (!memcmp(sync, data + res - sizeof(sync),
235 sizeof(sync)))
236 printf(" => GOT OUR DATA BACK (HURRAY!)");
237 break;
238 }
239 case IP_PKTINFO: {
240 struct in_pktinfo *pktinfo =
241 (struct in_pktinfo *)CMSG_DATA(cmsg);
242 printf("IP_PKTINFO interface index %u",
243 pktinfo->ipi_ifindex);
244 break;
245 }
246 default:
247 printf("type %d", cmsg->cmsg_type);
248 break;
249 }
250 break;
251 default:
252 printf("level %d type %d",
253 cmsg->cmsg_level,
254 cmsg->cmsg_type);
255 break;
256 }
257 printf("\n");
258 }
259
260 if (siocgstamp) {
261 if (ioctl(sock, SIOCGSTAMP, &tv))
262 printf(" %s: %s\n", "SIOCGSTAMP", strerror(errno));
263 else
264 printf("SIOCGSTAMP %ld.%06ld\n",
265 (long)tv.tv_sec,
266 (long)tv.tv_usec);
267 }
268 if (siocgstampns) {
269 if (ioctl(sock, SIOCGSTAMPNS, &ts))
270 printf(" %s: %s\n", "SIOCGSTAMPNS", strerror(errno));
271 else
272 printf("SIOCGSTAMPNS %ld.%09ld\n",
273 (long)ts.tv_sec,
274 (long)ts.tv_nsec);
275 }
276}
277
278static void recvpacket(int sock, int recvmsg_flags,
279 int siocgstamp, int siocgstampns)
280{
281 char data[256];
282 struct msghdr msg;
283 struct iovec entry;
284 struct sockaddr_in from_addr;
285 struct {
286 struct cmsghdr cm;
287 char control[512];
288 } control;
289 int res;
290
291 memset(&msg, 0, sizeof(msg));
292 msg.msg_iov = &entry;
293 msg.msg_iovlen = 1;
294 entry.iov_base = data;
295 entry.iov_len = sizeof(data);
296 msg.msg_name = (caddr_t)&from_addr;
297 msg.msg_namelen = sizeof(from_addr);
298 msg.msg_control = &control;
299 msg.msg_controllen = sizeof(control);
300
301 res = recvmsg(sock, &msg, recvmsg_flags|MSG_DONTWAIT);
302 if (res < 0) {
303 printf("%s %s: %s\n",
304 "recvmsg",
305 (recvmsg_flags & MSG_ERRQUEUE) ? "error" : "regular",
306 strerror(errno));
307 } else {
308 printpacket(&msg, res, data,
309 sock, recvmsg_flags,
310 siocgstamp, siocgstampns);
311 }
312}
313
314int main(int argc, char **argv)
315{
316 int so_timestamping_flags = 0;
317 int so_timestamp = 0;
318 int so_timestampns = 0;
319 int siocgstamp = 0;
320 int siocgstampns = 0;
321 int ip_multicast_loop = 0;
322 char *interface;
323 int i;
324 int enabled = 1;
325 int sock;
326 struct ifreq device;
327 struct ifreq hwtstamp;
328 struct hwtstamp_config hwconfig, hwconfig_requested;
329 struct sockaddr_in addr;
330 struct ip_mreq imr;
331 struct in_addr iaddr;
332 int val;
333 socklen_t len;
334 struct timeval next;
335
336 if (argc < 2)
337 usage(0);
338 interface = argv[1];
339
340 for (i = 2; i < argc; i++) {
341 if (!strcasecmp(argv[i], "SO_TIMESTAMP"))
342 so_timestamp = 1;
343 else if (!strcasecmp(argv[i], "SO_TIMESTAMPNS"))
344 so_timestampns = 1;
345 else if (!strcasecmp(argv[i], "SIOCGSTAMP"))
346 siocgstamp = 1;
347 else if (!strcasecmp(argv[i], "SIOCGSTAMPNS"))
348 siocgstampns = 1;
349 else if (!strcasecmp(argv[i], "IP_MULTICAST_LOOP"))
350 ip_multicast_loop = 1;
351 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_HARDWARE"))
352 so_timestamping_flags |= SOF_TIMESTAMPING_TX_HARDWARE;
353 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_TX_SOFTWARE"))
354 so_timestamping_flags |= SOF_TIMESTAMPING_TX_SOFTWARE;
355 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_HARDWARE"))
356 so_timestamping_flags |= SOF_TIMESTAMPING_RX_HARDWARE;
357 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RX_SOFTWARE"))
358 so_timestamping_flags |= SOF_TIMESTAMPING_RX_SOFTWARE;
359 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_SOFTWARE"))
360 so_timestamping_flags |= SOF_TIMESTAMPING_SOFTWARE;
361 else if (!strcasecmp(argv[i], "SOF_TIMESTAMPING_RAW_HARDWARE"))
362 so_timestamping_flags |= SOF_TIMESTAMPING_RAW_HARDWARE;
363 else
364 usage(argv[i]);
365 }
366
367 sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
368 if (sock < 0)
369 bail("socket");
370
371 memset(&device, 0, sizeof(device));
372 strncpy(device.ifr_name, interface, sizeof(device.ifr_name));
373 if (ioctl(sock, SIOCGIFADDR, &device) < 0)
374 bail("getting interface IP address");
375
376 memset(&hwtstamp, 0, sizeof(hwtstamp));
377 strncpy(hwtstamp.ifr_name, interface, sizeof(hwtstamp.ifr_name));
378 hwtstamp.ifr_data = (void *)&hwconfig;
379 memset(&hwconfig, 0, sizeof(hwconfig));
380 hwconfig.tx_type =
381 (so_timestamping_flags & SOF_TIMESTAMPING_TX_HARDWARE) ?
382 HWTSTAMP_TX_ON : HWTSTAMP_TX_OFF;
383 hwconfig.rx_filter =
384 (so_timestamping_flags & SOF_TIMESTAMPING_RX_HARDWARE) ?
385 HWTSTAMP_FILTER_PTP_V1_L4_SYNC : HWTSTAMP_FILTER_NONE;
386 hwconfig_requested = hwconfig;
387 if (ioctl(sock, SIOCSHWTSTAMP, &hwtstamp) < 0) {
388 if ((errno == EINVAL || errno == ENOTSUP) &&
389 hwconfig_requested.tx_type == HWTSTAMP_TX_OFF &&
390 hwconfig_requested.rx_filter == HWTSTAMP_FILTER_NONE)
391 printf("SIOCSHWTSTAMP: disabling hardware time stamping not possible\n");
392 else
393 bail("SIOCSHWTSTAMP");
394 }
395 printf("SIOCSHWTSTAMP: tx_type %d requested, got %d; rx_filter %d requested, got %d\n",
396 hwconfig_requested.tx_type, hwconfig.tx_type,
397 hwconfig_requested.rx_filter, hwconfig.rx_filter);
398
399 /* bind to PTP port */
400 addr.sin_family = AF_INET;
401 addr.sin_addr.s_addr = htonl(INADDR_ANY);
402 addr.sin_port = htons(319 /* PTP event port */);
403 if (bind(sock,
404 (struct sockaddr *)&addr,
405 sizeof(struct sockaddr_in)) < 0)
406 bail("bind");
407
408 /* set multicast group for outgoing packets */
409 inet_aton("224.0.1.130", &iaddr); /* alternate PTP domain 1 */
410 addr.sin_addr = iaddr;
411 imr.imr_multiaddr.s_addr = iaddr.s_addr;
412 imr.imr_interface.s_addr =
413 ((struct sockaddr_in *)&device.ifr_addr)->sin_addr.s_addr;
414 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF,
415 &imr.imr_interface.s_addr, sizeof(struct in_addr)) < 0)
416 bail("set multicast");
417
418 /* join multicast group, loop our own packet */
419 if (setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
420 &imr, sizeof(struct ip_mreq)) < 0)
421 bail("join multicast group");
422
423 if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP,
424 &ip_multicast_loop, sizeof(enabled)) < 0) {
425 bail("loop multicast");
426 }
427
428 /* set socket options for time stamping */
429 if (so_timestamp &&
430 setsockopt(sock, SOL_SOCKET, SO_TIMESTAMP,
431 &enabled, sizeof(enabled)) < 0)
432 bail("setsockopt SO_TIMESTAMP");
433
434 if (so_timestampns &&
435 setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS,
436 &enabled, sizeof(enabled)) < 0)
437 bail("setsockopt SO_TIMESTAMPNS");
438
439 if (so_timestamping_flags &&
440 setsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING,
441 &so_timestamping_flags,
442 sizeof(so_timestamping_flags)) < 0)
443 bail("setsockopt SO_TIMESTAMPING");
444
445 /* request IP_PKTINFO for debugging purposes */
446 if (setsockopt(sock, SOL_IP, IP_PKTINFO,
447 &enabled, sizeof(enabled)) < 0)
448 printf("%s: %s\n", "setsockopt IP_PKTINFO", strerror(errno));
449
450 /* verify socket options */
451 len = sizeof(val);
452 if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMP, &val, &len) < 0)
453 printf("%s: %s\n", "getsockopt SO_TIMESTAMP", strerror(errno));
454 else
455 printf("SO_TIMESTAMP %d\n", val);
456
457 if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPNS, &val, &len) < 0)
458 printf("%s: %s\n", "getsockopt SO_TIMESTAMPNS",
459 strerror(errno));
460 else
461 printf("SO_TIMESTAMPNS %d\n", val);
462
463 if (getsockopt(sock, SOL_SOCKET, SO_TIMESTAMPING, &val, &len) < 0) {
464 printf("%s: %s\n", "getsockopt SO_TIMESTAMPING",
465 strerror(errno));
466 } else {
467 printf("SO_TIMESTAMPING %d\n", val);
468 if (val != so_timestamping_flags)
469 printf(" not the expected value %d\n",
470 so_timestamping_flags);
471 }
472
473 /* send packets forever every five seconds */
474 gettimeofday(&next, 0);
475 next.tv_sec = (next.tv_sec + 1) / 5 * 5;
476 next.tv_usec = 0;
477 while (1) {
478 struct timeval now;
479 struct timeval delta;
480 long delta_us;
481 int res;
482 fd_set readfs, errorfs;
483
484 gettimeofday(&now, 0);
485 delta_us = (long)(next.tv_sec - now.tv_sec) * 1000000 +
486 (long)(next.tv_usec - now.tv_usec);
487 if (delta_us > 0) {
488 /* continue waiting for timeout or data */
489 delta.tv_sec = delta_us / 1000000;
490 delta.tv_usec = delta_us % 1000000;
491
492 FD_ZERO(&readfs);
493 FD_ZERO(&errorfs);
494 FD_SET(sock, &readfs);
495 FD_SET(sock, &errorfs);
496 printf("%ld.%06ld: select %ldus\n",
497 (long)now.tv_sec, (long)now.tv_usec,
498 delta_us);
499 res = select(sock + 1, &readfs, 0, &errorfs, &delta);
500 gettimeofday(&now, 0);
501 printf("%ld.%06ld: select returned: %d, %s\n",
502 (long)now.tv_sec, (long)now.tv_usec,
503 res,
504 res < 0 ? strerror(errno) : "success");
505 if (res > 0) {
506 if (FD_ISSET(sock, &readfs))
507 printf("ready for reading\n");
508 if (FD_ISSET(sock, &errorfs))
509 printf("has error\n");
510 recvpacket(sock, 0,
511 siocgstamp,
512 siocgstampns);
513 recvpacket(sock, MSG_ERRQUEUE,
514 siocgstamp,
515 siocgstampns);
516 }
517 } else {
518 /* write one packet */
519 sendpacket(sock,
520 (struct sockaddr *)&addr,
521 sizeof(addr));
522 next.tv_sec += 5;
523 continue;
524 }
525 }
526
527 return 0;
528}
diff --git a/tools/testing/selftests/networking/timestamping/txtimestamp.c b/tools/testing/selftests/networking/timestamping/txtimestamp.c
new file mode 100644
index 000000000000..5df07047ca86
--- /dev/null
+++ b/tools/testing/selftests/networking/timestamping/txtimestamp.c
@@ -0,0 +1,549 @@
1/*
2 * Copyright 2014 Google Inc.
3 * Author: willemb@google.com (Willem de Bruijn)
4 *
5 * Test software tx timestamping, including
6 *
7 * - SCHED, SND and ACK timestamps
8 * - RAW, UDP and TCP
9 * - IPv4 and IPv6
10 * - various packet sizes (to test GSO and TSO)
11 *
12 * Consult the command line arguments for help on running
13 * the various testcases.
14 *
15 * This test requires a dummy TCP server.
16 * A simple `nc6 [-u] -l -p $DESTPORT` will do
17 *
18 *
19 * This program is free software; you can redistribute it and/or modify it
20 * under the terms and conditions of the GNU General Public License,
21 * version 2, as published by the Free Software Foundation.
22 *
23 * This program is distributed in the hope it will be useful, but WITHOUT
24 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
25 * FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for
26 * more details.
27 *
28 * You should have received a copy of the GNU General Public License along with
29 * this program; if not, write to the Free Software Foundation, Inc.,
30 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
31 */
32
33#define _GNU_SOURCE
34
35#include <arpa/inet.h>
36#include <asm/types.h>
37#include <error.h>
38#include <errno.h>
39#include <inttypes.h>
40#include <linux/errqueue.h>
41#include <linux/if_ether.h>
42#include <linux/net_tstamp.h>
43#include <netdb.h>
44#include <net/if.h>
45#include <netinet/in.h>
46#include <netinet/ip.h>
47#include <netinet/udp.h>
48#include <netinet/tcp.h>
49#include <netpacket/packet.h>
50#include <poll.h>
51#include <stdarg.h>
52#include <stdbool.h>
53#include <stdio.h>
54#include <stdlib.h>
55#include <string.h>
56#include <sys/ioctl.h>
57#include <sys/select.h>
58#include <sys/socket.h>
59#include <sys/time.h>
60#include <sys/types.h>
61#include <time.h>
62#include <unistd.h>
63
64/* command line parameters */
65static int cfg_proto = SOCK_STREAM;
66static int cfg_ipproto = IPPROTO_TCP;
67static int cfg_num_pkts = 4;
68static int do_ipv4 = 1;
69static int do_ipv6 = 1;
70static int cfg_payload_len = 10;
71static bool cfg_show_payload;
72static bool cfg_do_pktinfo;
73static bool cfg_loop_nodata;
74static uint16_t dest_port = 9000;
75
76static struct sockaddr_in daddr;
77static struct sockaddr_in6 daddr6;
78static struct timespec ts_prev;
79
80static void __print_timestamp(const char *name, struct timespec *cur,
81 uint32_t key, int payload_len)
82{
83 if (!(cur->tv_sec | cur->tv_nsec))
84 return;
85
86 fprintf(stderr, " %s: %lu s %lu us (seq=%u, len=%u)",
87 name, cur->tv_sec, cur->tv_nsec / 1000,
88 key, payload_len);
89
90 if ((ts_prev.tv_sec | ts_prev.tv_nsec)) {
91 int64_t cur_ms, prev_ms;
92
93 cur_ms = (long) cur->tv_sec * 1000 * 1000;
94 cur_ms += cur->tv_nsec / 1000;
95
96 prev_ms = (long) ts_prev.tv_sec * 1000 * 1000;
97 prev_ms += ts_prev.tv_nsec / 1000;
98
99 fprintf(stderr, " (%+" PRId64 " us)", cur_ms - prev_ms);
100 }
101
102 ts_prev = *cur;
103 fprintf(stderr, "\n");
104}
105
106static void print_timestamp_usr(void)
107{
108 struct timespec ts;
109 struct timeval tv; /* avoid dependency on -lrt */
110
111 gettimeofday(&tv, NULL);
112 ts.tv_sec = tv.tv_sec;
113 ts.tv_nsec = tv.tv_usec * 1000;
114
115 __print_timestamp(" USR", &ts, 0, 0);
116}
117
118static void print_timestamp(struct scm_timestamping *tss, int tstype,
119 int tskey, int payload_len)
120{
121 const char *tsname;
122
123 switch (tstype) {
124 case SCM_TSTAMP_SCHED:
125 tsname = " ENQ";
126 break;
127 case SCM_TSTAMP_SND:
128 tsname = " SND";
129 break;
130 case SCM_TSTAMP_ACK:
131 tsname = " ACK";
132 break;
133 default:
134 error(1, 0, "unknown timestamp type: %u",
135 tstype);
136 }
137 __print_timestamp(tsname, &tss->ts[0], tskey, payload_len);
138}
139
140/* TODO: convert to check_and_print payload once API is stable */
141static void print_payload(char *data, int len)
142{
143 int i;
144
145 if (!len)
146 return;
147
148 if (len > 70)
149 len = 70;
150
151 fprintf(stderr, "payload: ");
152 for (i = 0; i < len; i++)
153 fprintf(stderr, "%02hhx ", data[i]);
154 fprintf(stderr, "\n");
155}
156
157static void print_pktinfo(int family, int ifindex, void *saddr, void *daddr)
158{
159 char sa[INET6_ADDRSTRLEN], da[INET6_ADDRSTRLEN];
160
161 fprintf(stderr, " pktinfo: ifindex=%u src=%s dst=%s\n",
162 ifindex,
163 saddr ? inet_ntop(family, saddr, sa, sizeof(sa)) : "unknown",
164 daddr ? inet_ntop(family, daddr, da, sizeof(da)) : "unknown");
165}
166
167static void __poll(int fd)
168{
169 struct pollfd pollfd;
170 int ret;
171
172 memset(&pollfd, 0, sizeof(pollfd));
173 pollfd.fd = fd;
174 ret = poll(&pollfd, 1, 100);
175 if (ret != 1)
176 error(1, errno, "poll");
177}
178
179static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
180{
181 struct sock_extended_err *serr = NULL;
182 struct scm_timestamping *tss = NULL;
183 struct cmsghdr *cm;
184 int batch = 0;
185
186 for (cm = CMSG_FIRSTHDR(msg);
187 cm && cm->cmsg_len;
188 cm = CMSG_NXTHDR(msg, cm)) {
189 if (cm->cmsg_level == SOL_SOCKET &&
190 cm->cmsg_type == SCM_TIMESTAMPING) {
191 tss = (void *) CMSG_DATA(cm);
192 } else if ((cm->cmsg_level == SOL_IP &&
193 cm->cmsg_type == IP_RECVERR) ||
194 (cm->cmsg_level == SOL_IPV6 &&
195 cm->cmsg_type == IPV6_RECVERR)) {
196 serr = (void *) CMSG_DATA(cm);
197 if (serr->ee_errno != ENOMSG ||
198 serr->ee_origin != SO_EE_ORIGIN_TIMESTAMPING) {
199 fprintf(stderr, "unknown ip error %d %d\n",
200 serr->ee_errno,
201 serr->ee_origin);
202 serr = NULL;
203 }
204 } else if (cm->cmsg_level == SOL_IP &&
205 cm->cmsg_type == IP_PKTINFO) {
206 struct in_pktinfo *info = (void *) CMSG_DATA(cm);
207 print_pktinfo(AF_INET, info->ipi_ifindex,
208 &info->ipi_spec_dst, &info->ipi_addr);
209 } else if (cm->cmsg_level == SOL_IPV6 &&
210 cm->cmsg_type == IPV6_PKTINFO) {
211 struct in6_pktinfo *info6 = (void *) CMSG_DATA(cm);
212 print_pktinfo(AF_INET6, info6->ipi6_ifindex,
213 NULL, &info6->ipi6_addr);
214 } else
215 fprintf(stderr, "unknown cmsg %d,%d\n",
216 cm->cmsg_level, cm->cmsg_type);
217
218 if (serr && tss) {
219 print_timestamp(tss, serr->ee_info, serr->ee_data,
220 payload_len);
221 serr = NULL;
222 tss = NULL;
223 batch++;
224 }
225 }
226
227 if (batch > 1)
228 fprintf(stderr, "batched %d timestamps\n", batch);
229}
230
231static int recv_errmsg(int fd)
232{
233 static char ctrl[1024 /* overprovision*/];
234 static struct msghdr msg;
235 struct iovec entry;
236 static char *data;
237 int ret = 0;
238
239 data = malloc(cfg_payload_len);
240 if (!data)
241 error(1, 0, "malloc");
242
243 memset(&msg, 0, sizeof(msg));
244 memset(&entry, 0, sizeof(entry));
245 memset(ctrl, 0, sizeof(ctrl));
246
247 entry.iov_base = data;
248 entry.iov_len = cfg_payload_len;
249 msg.msg_iov = &entry;
250 msg.msg_iovlen = 1;
251 msg.msg_name = NULL;
252 msg.msg_namelen = 0;
253 msg.msg_control = ctrl;
254 msg.msg_controllen = sizeof(ctrl);
255
256 ret = recvmsg(fd, &msg, MSG_ERRQUEUE);
257 if (ret == -1 && errno != EAGAIN)
258 error(1, errno, "recvmsg");
259
260 if (ret >= 0) {
261 __recv_errmsg_cmsg(&msg, ret);
262 if (cfg_show_payload)
263 print_payload(data, cfg_payload_len);
264 }
265
266 free(data);
267 return ret == -1;
268}
269
270static void do_test(int family, unsigned int opt)
271{
272 char *buf;
273 int fd, i, val = 1, total_len;
274
275 if (family == AF_INET6 && cfg_proto != SOCK_STREAM) {
276 /* due to lack of checksum generation code */
277 fprintf(stderr, "test: skipping datagram over IPv6\n");
278 return;
279 }
280
281 total_len = cfg_payload_len;
282 if (cfg_proto == SOCK_RAW) {
283 total_len += sizeof(struct udphdr);
284 if (cfg_ipproto == IPPROTO_RAW)
285 total_len += sizeof(struct iphdr);
286 }
287
288 buf = malloc(total_len);
289 if (!buf)
290 error(1, 0, "malloc");
291
292 fd = socket(family, cfg_proto, cfg_ipproto);
293 if (fd < 0)
294 error(1, errno, "socket");
295
296 if (cfg_proto == SOCK_STREAM) {
297 if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
298 (char*) &val, sizeof(val)))
299 error(1, 0, "setsockopt no nagle");
300
301 if (family == PF_INET) {
302 if (connect(fd, (void *) &daddr, sizeof(daddr)))
303 error(1, errno, "connect ipv4");
304 } else {
305 if (connect(fd, (void *) &daddr6, sizeof(daddr6)))
306 error(1, errno, "connect ipv6");
307 }
308 }
309
310 if (cfg_do_pktinfo) {
311 if (family == AF_INET6) {
312 if (setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO,
313 &val, sizeof(val)))
314 error(1, errno, "setsockopt pktinfo ipv6");
315 } else {
316 if (setsockopt(fd, SOL_IP, IP_PKTINFO,
317 &val, sizeof(val)))
318 error(1, errno, "setsockopt pktinfo ipv4");
319 }
320 }
321
322 opt |= SOF_TIMESTAMPING_SOFTWARE |
323 SOF_TIMESTAMPING_OPT_CMSG |
324 SOF_TIMESTAMPING_OPT_ID;
325 if (cfg_loop_nodata)
326 opt |= SOF_TIMESTAMPING_OPT_TSONLY;
327
328 if (setsockopt(fd, SOL_SOCKET, SO_TIMESTAMPING,
329 (char *) &opt, sizeof(opt)))
330 error(1, 0, "setsockopt timestamping");
331
332 for (i = 0; i < cfg_num_pkts; i++) {
333 memset(&ts_prev, 0, sizeof(ts_prev));
334 memset(buf, 'a' + i, total_len);
335
336 if (cfg_proto == SOCK_RAW) {
337 struct udphdr *udph;
338 int off = 0;
339
340 if (cfg_ipproto == IPPROTO_RAW) {
341 struct iphdr *iph = (void *) buf;
342
343 memset(iph, 0, sizeof(*iph));
344 iph->ihl = 5;
345 iph->version = 4;
346 iph->ttl = 2;
347 iph->daddr = daddr.sin_addr.s_addr;
348 iph->protocol = IPPROTO_UDP;
349 /* kernel writes saddr, csum, len */
350
351 off = sizeof(*iph);
352 }
353
354 udph = (void *) buf + off;
355 udph->source = ntohs(9000); /* random spoof */
356 udph->dest = ntohs(dest_port);
357 udph->len = ntohs(sizeof(*udph) + cfg_payload_len);
358 udph->check = 0; /* not allowed for IPv6 */
359 }
360
361 print_timestamp_usr();
362 if (cfg_proto != SOCK_STREAM) {
363 if (family == PF_INET)
364 val = sendto(fd, buf, total_len, 0, (void *) &daddr, sizeof(daddr));
365 else
366 val = sendto(fd, buf, total_len, 0, (void *) &daddr6, sizeof(daddr6));
367 } else {
368 val = send(fd, buf, cfg_payload_len, 0);
369 }
370 if (val != total_len)
371 error(1, errno, "send");
372
373 /* wait for all errors to be queued, else ACKs arrive OOO */
374 usleep(50 * 1000);
375
376 __poll(fd);
377
378 while (!recv_errmsg(fd)) {}
379 }
380
381 if (close(fd))
382 error(1, errno, "close");
383
384 free(buf);
385 usleep(400 * 1000);
386}
387
388static void __attribute__((noreturn)) usage(const char *filepath)
389{
390 fprintf(stderr, "\nUsage: %s [options] hostname\n"
391 "\nwhere options are:\n"
392 " -4: only IPv4\n"
393 " -6: only IPv6\n"
394 " -h: show this message\n"
395 " -I: request PKTINFO\n"
396 " -l N: send N bytes at a time\n"
397 " -n: set no-payload option\n"
398 " -r: use raw\n"
399 " -R: use raw (IP_HDRINCL)\n"
400 " -p N: connect to port N\n"
401 " -u: use udp\n"
402 " -x: show payload (up to 70 bytes)\n",
403 filepath);
404 exit(1);
405}
406
407static void parse_opt(int argc, char **argv)
408{
409 int proto_count = 0;
410 char c;
411
412 while ((c = getopt(argc, argv, "46hIl:np:rRux")) != -1) {
413 switch (c) {
414 case '4':
415 do_ipv6 = 0;
416 break;
417 case '6':
418 do_ipv4 = 0;
419 break;
420 case 'I':
421 cfg_do_pktinfo = true;
422 break;
423 case 'n':
424 cfg_loop_nodata = true;
425 break;
426 case 'r':
427 proto_count++;
428 cfg_proto = SOCK_RAW;
429 cfg_ipproto = IPPROTO_UDP;
430 break;
431 case 'R':
432 proto_count++;
433 cfg_proto = SOCK_RAW;
434 cfg_ipproto = IPPROTO_RAW;
435 break;
436 case 'u':
437 proto_count++;
438 cfg_proto = SOCK_DGRAM;
439 cfg_ipproto = IPPROTO_UDP;
440 break;
441 case 'l':
442 cfg_payload_len = strtoul(optarg, NULL, 10);
443 break;
444 case 'p':
445 dest_port = strtoul(optarg, NULL, 10);
446 break;
447 case 'x':
448 cfg_show_payload = true;
449 break;
450 case 'h':
451 default:
452 usage(argv[0]);
453 }
454 }
455
456 if (!cfg_payload_len)
457 error(1, 0, "payload may not be nonzero");
458 if (cfg_proto != SOCK_STREAM && cfg_payload_len > 1472)
459 error(1, 0, "udp packet might exceed expected MTU");
460 if (!do_ipv4 && !do_ipv6)
461 error(1, 0, "pass -4 or -6, not both");
462 if (proto_count > 1)
463 error(1, 0, "pass -r, -R or -u, not multiple");
464
465 if (optind != argc - 1)
466 error(1, 0, "missing required hostname argument");
467}
468
469static void resolve_hostname(const char *hostname)
470{
471 struct addrinfo *addrs, *cur;
472 int have_ipv4 = 0, have_ipv6 = 0;
473
474 if (getaddrinfo(hostname, NULL, NULL, &addrs))
475 error(1, errno, "getaddrinfo");
476
477 cur = addrs;
478 while (cur && !have_ipv4 && !have_ipv6) {
479 if (!have_ipv4 && cur->ai_family == AF_INET) {
480 memcpy(&daddr, cur->ai_addr, sizeof(daddr));
481 daddr.sin_port = htons(dest_port);
482 have_ipv4 = 1;
483 }
484 else if (!have_ipv6 && cur->ai_family == AF_INET6) {
485 memcpy(&daddr6, cur->ai_addr, sizeof(daddr6));
486 daddr6.sin6_port = htons(dest_port);
487 have_ipv6 = 1;
488 }
489 cur = cur->ai_next;
490 }
491 if (addrs)
492 freeaddrinfo(addrs);
493
494 do_ipv4 &= have_ipv4;
495 do_ipv6 &= have_ipv6;
496}
497
498static void do_main(int family)
499{
500 fprintf(stderr, "family: %s\n",
501 family == PF_INET ? "INET" : "INET6");
502
503 fprintf(stderr, "test SND\n");
504 do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE);
505
506 fprintf(stderr, "test ENQ\n");
507 do_test(family, SOF_TIMESTAMPING_TX_SCHED);
508
509 fprintf(stderr, "test ENQ + SND\n");
510 do_test(family, SOF_TIMESTAMPING_TX_SCHED |
511 SOF_TIMESTAMPING_TX_SOFTWARE);
512
513 if (cfg_proto == SOCK_STREAM) {
514 fprintf(stderr, "\ntest ACK\n");
515 do_test(family, SOF_TIMESTAMPING_TX_ACK);
516
517 fprintf(stderr, "\ntest SND + ACK\n");
518 do_test(family, SOF_TIMESTAMPING_TX_SOFTWARE |
519 SOF_TIMESTAMPING_TX_ACK);
520
521 fprintf(stderr, "\ntest ENQ + SND + ACK\n");
522 do_test(family, SOF_TIMESTAMPING_TX_SCHED |
523 SOF_TIMESTAMPING_TX_SOFTWARE |
524 SOF_TIMESTAMPING_TX_ACK);
525 }
526}
527
528const char *sock_names[] = { NULL, "TCP", "UDP", "RAW" };
529
530int main(int argc, char **argv)
531{
532 if (argc == 1)
533 usage(argv[0]);
534
535 parse_opt(argc, argv);
536 resolve_hostname(argv[argc - 1]);
537
538 fprintf(stderr, "protocol: %s\n", sock_names[cfg_proto]);
539 fprintf(stderr, "payload: %u\n", cfg_payload_len);
540 fprintf(stderr, "server port: %u\n", dest_port);
541 fprintf(stderr, "\n");
542
543 if (do_ipv4)
544 do_main(PF_INET);
545 if (do_ipv6)
546 do_main(PF_INET6);
547
548 return 0;
549}
diff --git a/tools/testing/selftests/nsfs/Makefile b/tools/testing/selftests/nsfs/Makefile
new file mode 100644
index 000000000000..2306054a901a
--- /dev/null
+++ b/tools/testing/selftests/nsfs/Makefile
@@ -0,0 +1,12 @@
1TEST_PROGS := owner pidns
2
3CFLAGS := -Wall -Werror
4
5all: owner pidns
6owner: owner.c
7pidns: pidns.c
8
9clean:
10 $(RM) owner pidns
11
12include ../lib.mk
diff --git a/tools/testing/selftests/nsfs/owner.c b/tools/testing/selftests/nsfs/owner.c
new file mode 100644
index 000000000000..437205f8b714
--- /dev/null
+++ b/tools/testing/selftests/nsfs/owner.c
@@ -0,0 +1,91 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <signal.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <sys/ioctl.h>
12#include <sys/prctl.h>
13#include <sys/wait.h>
14
15#define NSIO 0xb7
16#define NS_GET_USERNS _IO(NSIO, 0x1)
17
18#define pr_err(fmt, ...) \
19 ({ \
20 fprintf(stderr, "%s:%d:" fmt ": %m\n", \
21 __func__, __LINE__, ##__VA_ARGS__); \
22 1; \
23 })
24
25int main(int argc, char *argvp[])
26{
27 int pfd[2], ns, uns, init_uns;
28 struct stat st1, st2;
29 char path[128];
30 pid_t pid;
31 char c;
32
33 if (pipe(pfd))
34 return 1;
35
36 pid = fork();
37 if (pid < 0)
38 return pr_err("fork");
39 if (pid == 0) {
40 prctl(PR_SET_PDEATHSIG, SIGKILL);
41 if (unshare(CLONE_NEWUTS | CLONE_NEWUSER))
42 return pr_err("unshare");
43 close(pfd[0]);
44 close(pfd[1]);
45 while (1)
46 sleep(1);
47 return 0;
48 }
49 close(pfd[1]);
50 if (read(pfd[0], &c, 1) != 0)
51 return pr_err("Unable to read from pipe");
52 close(pfd[0]);
53
54 snprintf(path, sizeof(path), "/proc/%d/ns/uts", pid);
55 ns = open(path, O_RDONLY);
56 if (ns < 0)
57 return pr_err("Unable to open %s", path);
58
59 uns = ioctl(ns, NS_GET_USERNS);
60 if (uns < 0)
61 return pr_err("Unable to get an owning user namespace");
62
63 if (fstat(uns, &st1))
64 return pr_err("fstat");
65
66 snprintf(path, sizeof(path), "/proc/%d/ns/user", pid);
67 if (stat(path, &st2))
68 return pr_err("stat");
69
70 if (st1.st_ino != st2.st_ino)
71 return pr_err("NS_GET_USERNS returned a wrong namespace");
72
73 init_uns = ioctl(uns, NS_GET_USERNS);
74 if (uns < 0)
75 return pr_err("Unable to get an owning user namespace");
76
77 if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
78 return pr_err("Don't get EPERM");
79
80 if (unshare(CLONE_NEWUSER))
81 return pr_err("unshare");
82
83 if (ioctl(ns, NS_GET_USERNS) >= 0 || errno != EPERM)
84 return pr_err("Don't get EPERM");
85 if (ioctl(init_uns, NS_GET_USERNS) >= 0 || errno != EPERM)
86 return pr_err("Don't get EPERM");
87
88 kill(pid, SIGKILL);
89 wait(NULL);
90 return 0;
91}
diff --git a/tools/testing/selftests/nsfs/pidns.c b/tools/testing/selftests/nsfs/pidns.c
new file mode 100644
index 000000000000..ae3a0d68e966
--- /dev/null
+++ b/tools/testing/selftests/nsfs/pidns.c
@@ -0,0 +1,78 @@
1#define _GNU_SOURCE
2#include <sched.h>
3#include <unistd.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <signal.h>
7#include <errno.h>
8#include <sys/types.h>
9#include <sys/stat.h>
10#include <fcntl.h>
11#include <sys/ioctl.h>
12#include <sys/prctl.h>
13#include <sys/wait.h>
14
15#define pr_err(fmt, ...) \
16 ({ \
17 fprintf(stderr, "%s:%d:" fmt ": %m\n", \
18 __func__, __LINE__, ##__VA_ARGS__); \
19 1; \
20 })
21
22#define NSIO 0xb7
23#define NS_GET_USERNS _IO(NSIO, 0x1)
24#define NS_GET_PARENT _IO(NSIO, 0x2)
25
26#define __stack_aligned__ __attribute__((aligned(16)))
27struct cr_clone_arg {
28 char stack[128] __stack_aligned__;
29 char stack_ptr[0];
30};
31
32static int child(void *args)
33{
34 prctl(PR_SET_PDEATHSIG, SIGKILL);
35 while (1)
36 sleep(1);
37 exit(0);
38}
39
40int main(int argc, char *argv[])
41{
42 char *ns_strs[] = {"pid", "user"};
43 char path[] = "/proc/0123456789/ns/pid";
44 struct cr_clone_arg ca;
45 struct stat st1, st2;
46 int ns, pns, i;
47 pid_t pid;
48
49 pid = clone(child, ca.stack_ptr, CLONE_NEWUSER | CLONE_NEWPID | SIGCHLD, NULL);
50 if (pid < 0)
51 return pr_err("clone");
52
53 for (i = 0; i < 2; i++) {
54 snprintf(path, sizeof(path), "/proc/%d/ns/%s", pid, ns_strs[i]);
55 ns = open(path, O_RDONLY);
56 if (ns < 0)
57 return pr_err("Unable to open %s", path);
58
59 pns = ioctl(ns, NS_GET_PARENT);
60 if (pns < 0)
61 return pr_err("Unable to get a parent pidns");
62
63 snprintf(path, sizeof(path), "/proc/self/ns/%s", ns_strs[i]);
64 if (stat(path, &st2))
65 return pr_err("Unable to stat %s", path);
66 if (fstat(pns, &st1))
67 return pr_err("Unable to stat the parent pidns");
68 if (st1.st_ino != st2.st_ino)
69 return pr_err("NS_GET_PARENT returned a wrong namespace");
70
71 if (ioctl(pns, NS_GET_PARENT) >= 0 || errno != EPERM)
72 return pr_err("Don't get EPERM");;
73 }
74
75 kill(pid, SIGKILL);
76 wait(NULL);
77 return 0;
78}
diff --git a/tools/testing/selftests/ntb/ntb_test.sh b/tools/testing/selftests/ntb/ntb_test.sh
new file mode 100755
index 000000000000..a676d3eefefb
--- /dev/null
+++ b/tools/testing/selftests/ntb/ntb_test.sh
@@ -0,0 +1,422 @@
1#!/bin/bash
2# Copyright (c) 2016 Microsemi. All Rights Reserved.
3#
4# This program is free software; you can redistribute it and/or
5# modify it under the terms of the GNU General Public License as
6# published by the Free Software Foundation; either version 2 of
7# the License, or (at your option) any later version.
8#
9# This program is distributed in the hope that it would be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# Author: Logan Gunthorpe <logang@deltatee.com>
15
16REMOTE_HOST=
17LIST_DEVS=FALSE
18
19DEBUGFS=${DEBUGFS-/sys/kernel/debug}
20
21PERF_RUN_ORDER=32
22MAX_MW_SIZE=0
23RUN_DMA_TESTS=
24DONT_CLEANUP=
25MW_SIZE=65536
26
27function show_help()
28{
29 echo "Usage: $0 [OPTIONS] LOCAL_DEV REMOTE_DEV"
30 echo "Run tests on a pair of NTB endpoints."
31 echo
32 echo "If the NTB device loops back to the same host then,"
33 echo "just specifying the two PCI ids on the command line is"
34 echo "sufficient. Otherwise, if the NTB link spans two hosts"
35 echo "use the -r option to specify the hostname for the remote"
36 echo "device. SSH will then be used to test the remote side."
37 echo "An SSH key between the root users of the host would then"
38 echo "be highly recommended."
39 echo
40 echo "Options:"
41 echo " -C don't cleanup ntb modules on exit"
42 echo " -d run dma tests"
43 echo " -h show this help message"
44 echo " -l list available local and remote PCI ids"
45 echo " -r REMOTE_HOST specify the remote's hostname to connect"
46 echo " to for the test (using ssh)"
47 echo " -p NUM ntb_perf run order (default: $PERF_RUN_ORDER)"
48 echo " -w max_mw_size maxmium memory window size"
49 echo
50}
51
52function parse_args()
53{
54 OPTIND=0
55 while getopts "Cdhlm:r:p:w:" opt; do
56 case "$opt" in
57 C) DONT_CLEANUP=1 ;;
58 d) RUN_DMA_TESTS=1 ;;
59 h) show_help; exit 0 ;;
60 l) LIST_DEVS=TRUE ;;
61 m) MW_SIZE=${OPTARG} ;;
62 r) REMOTE_HOST=${OPTARG} ;;
63 p) PERF_RUN_ORDER=${OPTARG} ;;
64 w) MAX_MW_SIZE=${OPTARG} ;;
65 \?)
66 echo "Invalid option: -$OPTARG" >&2
67 exit 1
68 ;;
69 esac
70 done
71}
72
73parse_args "$@"
74shift $((OPTIND-1))
75LOCAL_DEV=$1
76shift
77parse_args "$@"
78shift $((OPTIND-1))
79REMOTE_DEV=$1
80shift
81parse_args "$@"
82
83set -e
84
85function _modprobe()
86{
87 modprobe "$@"
88}
89
90function split_remote()
91{
92 VPATH=$1
93 REMOTE=
94
95 if [[ "$VPATH" == *":/"* ]]; then
96 REMOTE=${VPATH%%:*}
97 VPATH=${VPATH#*:}
98 fi
99}
100
101function read_file()
102{
103 split_remote $1
104 if [[ "$REMOTE" != "" ]]; then
105 ssh "$REMOTE" cat "$VPATH"
106 else
107 cat "$VPATH"
108 fi
109}
110
111function write_file()
112{
113 split_remote $2
114 VALUE=$1
115
116 if [[ "$REMOTE" != "" ]]; then
117 ssh "$REMOTE" "echo \"$VALUE\" > \"$VPATH\""
118 else
119 echo "$VALUE" > "$VPATH"
120 fi
121}
122
123function link_test()
124{
125 LOC=$1
126 REM=$2
127 EXP=0
128
129 echo "Running link tests on: $(basename $LOC) / $(basename $REM)"
130
131 if ! write_file "N" "$LOC/link" 2> /dev/null; then
132 echo " Unsupported"
133 return
134 fi
135
136 write_file "N" "$LOC/link_event"
137
138 if [[ $(read_file "$REM/link") != "N" ]]; then
139 echo "Expected remote link to be down in $REM/link" >&2
140 exit -1
141 fi
142
143 write_file "Y" "$LOC/link"
144 write_file "Y" "$LOC/link_event"
145
146 echo " Passed"
147}
148
149function doorbell_test()
150{
151 LOC=$1
152 REM=$2
153 EXP=0
154
155 echo "Running db tests on: $(basename $LOC) / $(basename $REM)"
156
157 write_file "c 0xFFFFFFFF" "$REM/db"
158
159 for ((i=1; i <= 8; i++)); do
160 let DB=$(read_file "$REM/db") || true
161 if [[ "$DB" != "$EXP" ]]; then
162 echo "Doorbell doesn't match expected value $EXP " \
163 "in $REM/db" >&2
164 exit -1
165 fi
166
167 let "MASK=1 << ($i-1)" || true
168 let "EXP=$EXP | $MASK" || true
169 write_file "s $MASK" "$LOC/peer_db"
170 done
171
172 echo " Passed"
173}
174
175function read_spad()
176{
177 VPATH=$1
178 IDX=$2
179
180 ROW=($(read_file "$VPATH" | grep -e "^$IDX"))
181 let VAL=${ROW[1]} || true
182 echo $VAL
183}
184
185function scratchpad_test()
186{
187 LOC=$1
188 REM=$2
189 CNT=$(read_file "$LOC/spad" | wc -l)
190
191 echo "Running spad tests on: $(basename $LOC) / $(basename $REM)"
192
193 for ((i = 0; i < $CNT; i++)); do
194 VAL=$RANDOM
195 write_file "$i $VAL" "$LOC/peer_spad"
196 RVAL=$(read_spad "$REM/spad" $i)
197
198 if [[ "$VAL" != "$RVAL" ]]; then
199 echo "Scratchpad doesn't match expected value $VAL " \
200 "in $REM/spad, got $RVAL" >&2
201 exit -1
202 fi
203
204 done
205
206 echo " Passed"
207}
208
209function write_mw()
210{
211 split_remote $2
212
213 if [[ "$REMOTE" != "" ]]; then
214 ssh "$REMOTE" \
215 dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
216 else
217 dd if=/dev/urandom "of=$VPATH" 2> /dev/null || true
218 fi
219}
220
221function mw_test()
222{
223 IDX=$1
224 LOC=$2
225 REM=$3
226
227 echo "Running $IDX tests on: $(basename $LOC) / $(basename $REM)"
228
229 write_mw "$LOC/$IDX"
230
231 split_remote "$LOC/$IDX"
232 if [[ "$REMOTE" == "" ]]; then
233 A=$VPATH
234 else
235 A=/tmp/ntb_test.$$.A
236 ssh "$REMOTE" cat "$VPATH" > "$A"
237 fi
238
239 split_remote "$REM/peer_$IDX"
240 if [[ "$REMOTE" == "" ]]; then
241 B=$VPATH
242 else
243 B=/tmp/ntb_test.$$.B
244 ssh "$REMOTE" cat "$VPATH" > "$B"
245 fi
246
247 cmp -n $MW_SIZE "$A" "$B"
248 if [[ $? != 0 ]]; then
249 echo "Memory window $MW did not match!" >&2
250 fi
251
252 if [[ "$A" == "/tmp/*" ]]; then
253 rm "$A"
254 fi
255
256 if [[ "$B" == "/tmp/*" ]]; then
257 rm "$B"
258 fi
259
260 echo " Passed"
261}
262
263function pingpong_test()
264{
265 LOC=$1
266 REM=$2
267
268 echo "Running ping pong tests on: $(basename $LOC) / $(basename $REM)"
269
270 LOC_START=$(read_file $LOC/count)
271 REM_START=$(read_file $REM/count)
272
273 sleep 7
274
275 LOC_END=$(read_file $LOC/count)
276 REM_END=$(read_file $REM/count)
277
278 if [[ $LOC_START == $LOC_END ]] || [[ $REM_START == $REM_END ]]; then
279 echo "Ping pong counter not incrementing!" >&2
280 exit 1
281 fi
282
283 echo " Passed"
284}
285
286function perf_test()
287{
288 USE_DMA=$1
289
290 if [[ $USE_DMA == "1" ]]; then
291 WITH="with"
292 else
293 WITH="without"
294 fi
295
296 _modprobe ntb_perf run_order=$PERF_RUN_ORDER \
297 max_mw_size=$MAX_MW_SIZE use_dma=$USE_DMA
298
299 echo "Running local perf test $WITH DMA"
300 write_file "" $LOCAL_PERF/run
301 echo -n " "
302 read_file $LOCAL_PERF/run
303 echo " Passed"
304
305 echo "Running remote perf test $WITH DMA"
306 write_file "" $REMOTE_PERF/run
307 echo -n " "
308 read_file $LOCAL_PERF/run
309 echo " Passed"
310
311 _modprobe -r ntb_perf
312}
313
314function ntb_tool_tests()
315{
316 LOCAL_TOOL=$DEBUGFS/ntb_tool/$LOCAL_DEV
317 REMOTE_TOOL=$REMOTE_HOST:$DEBUGFS/ntb_tool/$REMOTE_DEV
318
319 echo "Starting ntb_tool tests..."
320
321 _modprobe ntb_tool
322
323 write_file Y $LOCAL_TOOL/link_event
324 write_file Y $REMOTE_TOOL/link_event
325
326 link_test $LOCAL_TOOL $REMOTE_TOOL
327 link_test $REMOTE_TOOL $LOCAL_TOOL
328
329 for PEER_TRANS in $(ls $LOCAL_TOOL/peer_trans*); do
330 PT=$(basename $PEER_TRANS)
331 write_file $MW_SIZE $LOCAL_TOOL/$PT
332 write_file $MW_SIZE $REMOTE_TOOL/$PT
333 done
334
335 doorbell_test $LOCAL_TOOL $REMOTE_TOOL
336 doorbell_test $REMOTE_TOOL $LOCAL_TOOL
337 scratchpad_test $LOCAL_TOOL $REMOTE_TOOL
338 scratchpad_test $REMOTE_TOOL $LOCAL_TOOL
339
340 for MW in $(ls $LOCAL_TOOL/mw*); do
341 MW=$(basename $MW)
342
343 mw_test $MW $LOCAL_TOOL $REMOTE_TOOL
344 mw_test $MW $REMOTE_TOOL $LOCAL_TOOL
345 done
346
347 _modprobe -r ntb_tool
348}
349
350function ntb_pingpong_tests()
351{
352 LOCAL_PP=$DEBUGFS/ntb_pingpong/$LOCAL_DEV
353 REMOTE_PP=$REMOTE_HOST:$DEBUGFS/ntb_pingpong/$REMOTE_DEV
354
355 echo "Starting ntb_pingpong tests..."
356
357 _modprobe ntb_pingpong
358
359 pingpong_test $LOCAL_PP $REMOTE_PP
360
361 _modprobe -r ntb_pingpong
362}
363
364function ntb_perf_tests()
365{
366 LOCAL_PERF=$DEBUGFS/ntb_perf/$LOCAL_DEV
367 REMOTE_PERF=$REMOTE_HOST:$DEBUGFS/ntb_perf/$REMOTE_DEV
368
369 echo "Starting ntb_perf tests..."
370
371 perf_test 0
372
373 if [[ $RUN_DMA_TESTS ]]; then
374 perf_test 1
375 fi
376}
377
378function cleanup()
379{
380 set +e
381 _modprobe -r ntb_tool 2> /dev/null
382 _modprobe -r ntb_perf 2> /dev/null
383 _modprobe -r ntb_pingpong 2> /dev/null
384 _modprobe -r ntb_transport 2> /dev/null
385 set -e
386}
387
388cleanup
389
390if ! [[ $$DONT_CLEANUP ]]; then
391 trap cleanup EXIT
392fi
393
394if [ "$(id -u)" != "0" ]; then
395 echo "This script must be run as root" 1>&2
396 exit 1
397fi
398
399if [[ "$LIST_DEVS" == TRUE ]]; then
400 echo "Local Devices:"
401 ls -1 /sys/bus/ntb/devices
402 echo
403
404 if [[ "$REMOTE_HOST" != "" ]]; then
405 echo "Remote Devices:"
406 ssh $REMOTE_HOST ls -1 /sys/bus/ntb/devices
407 fi
408
409 exit 0
410fi
411
412if [[ "$LOCAL_DEV" == $"" ]] || [[ "$REMOTE_DEV" == $"" ]]; then
413 show_help
414 exit 1
415fi
416
417ntb_tool_tests
418echo
419ntb_pingpong_tests
420echo
421ntb_perf_tests
422echo
diff --git a/tools/testing/selftests/powerpc/Makefile b/tools/testing/selftests/powerpc/Makefile
index 4ca83fe80654..db54a33f850f 100644
--- a/tools/testing/selftests/powerpc/Makefile
+++ b/tools/testing/selftests/powerpc/Makefile
@@ -8,16 +8,18 @@ ifeq ($(ARCH),powerpc)
8 8
9GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown") 9GIT_VERSION = $(shell git describe --always --long --dirty || echo "unknown")
10 10
11CFLAGS := -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS) 11CFLAGS := -std=gnu99 -Wall -O2 -Wall -Werror -DGIT_VERSION='"$(GIT_VERSION)"' -I$(CURDIR) $(CFLAGS)
12 12
13export CFLAGS 13export CFLAGS
14 14
15SUB_DIRS = benchmarks \ 15SUB_DIRS = alignment \
16 benchmarks \
16 copyloops \ 17 copyloops \
17 context_switch \ 18 context_switch \
18 dscr \ 19 dscr \
19 mm \ 20 mm \
20 pmu \ 21 pmu \
22 signal \
21 primitives \ 23 primitives \
22 stringloops \ 24 stringloops \
23 switch_endian \ 25 switch_endian \
diff --git a/tools/testing/selftests/powerpc/alignment/.gitignore b/tools/testing/selftests/powerpc/alignment/.gitignore
new file mode 100644
index 000000000000..1d980e3d7039
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/.gitignore
@@ -0,0 +1,5 @@
1copy_unaligned
2copy_first_unaligned
3paste_unaligned
4paste_last_unaligned
5copy_paste_unaligned_common
diff --git a/tools/testing/selftests/powerpc/alignment/Makefile b/tools/testing/selftests/powerpc/alignment/Makefile
new file mode 100644
index 000000000000..ad6a4e49da91
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/Makefile
@@ -0,0 +1,10 @@
1TEST_PROGS := copy_unaligned copy_first_unaligned paste_unaligned paste_last_unaligned
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c copy_paste_unaligned_common.c
6
7include ../../lib.mk
8
9clean:
10 rm -f $(TEST_PROGS)
diff --git a/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c
new file mode 100644
index 000000000000..47b73b3a08bd
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/copy_first_unaligned.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2016, Chris Smart, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Calls to copy_first which are not 128-byte aligned should be
10 * caught and sent a SIGBUS.
11 *
12 */
13
14#include <string.h>
15#include <unistd.h>
16#include "utils.h"
17#include "instructions.h"
18#include "copy_paste_unaligned_common.h"
19
20unsigned int expected_instruction = PPC_INST_COPY_FIRST;
21unsigned int instruction_mask = 0xfc2007fe;
22
23int test_copy_first_unaligned(void)
24{
25 /* Only run this test on a P9 or later */
26 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
27
28 /* Register our signal handler with SIGBUS */
29 setup_signal_handler();
30
31 /* +1 makes buf unaligned */
32 copy_first(cacheline_buf+1);
33
34 /* We should not get here */
35 return 1;
36}
37
38int main(int argc, char *argv[])
39{
40 return test_harness(test_copy_first_unaligned, "test_copy_first_unaligned");
41}
diff --git a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c
new file mode 100644
index 000000000000..d35fa5f5d2d3
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.c
@@ -0,0 +1,53 @@
1/*
2 * Copyright 2016, Chris Smart, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Common code for copy, copy_first, paste and paste_last unaligned
10 * tests.
11 *
12 */
13
14#include <signal.h>
15#include <string.h>
16#include <unistd.h>
17#include "utils.h"
18#include "instructions.h"
19#include "copy_paste_unaligned_common.h"
20
21unsigned int expected_instruction;
22unsigned int instruction_mask;
23
24char cacheline_buf[128] __cacheline_aligned;
25
26void signal_action_handler(int signal_num, siginfo_t *info, void *ptr)
27{
28 ucontext_t *ctx = ptr;
29#if defined(__powerpc64__)
30 unsigned int *pc = (unsigned int *)ctx->uc_mcontext.gp_regs[PT_NIP];
31#else
32 unsigned int *pc = (unsigned int *)ctx->uc_mcontext.uc_regs->gregs[PT_NIP];
33#endif
34
35 /*
36 * Check that the signal was on the correct instruction, using a
37 * mask because the compiler assigns the register at RB.
38 */
39 if ((*pc & instruction_mask) == expected_instruction)
40 _exit(0); /* We hit the right instruction */
41
42 _exit(1);
43}
44
45void setup_signal_handler(void)
46{
47 struct sigaction signal_action;
48
49 memset(&signal_action, 0, sizeof(signal_action));
50 signal_action.sa_sigaction = signal_action_handler;
51 signal_action.sa_flags = SA_SIGINFO;
52 sigaction(SIGBUS, &signal_action, NULL);
53}
diff --git a/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h
new file mode 100644
index 000000000000..053899fe506e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/copy_paste_unaligned_common.h
@@ -0,0 +1,26 @@
1/*
2 * Copyright 2016, Chris Smart, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Declarations for common code for copy, copy_first, paste and
10 * paste_last unaligned tests.
11 *
12 */
13
14#ifndef _SELFTESTS_POWERPC_COPY_PASTE_H
15#define _SELFTESTS_POWERPC_COPY_PASTE_H
16
17#include <signal.h>
18
19int main(int argc, char *argv[]);
20void signal_action_handler(int signal_num, siginfo_t *info, void *ptr);
21void setup_signal_handler(void);
22extern char cacheline_buf[128] __cacheline_aligned;
23extern unsigned int expected_instruction;
24extern unsigned int instruction_mask;
25
26#endif /* _SELFTESTS_POWERPC_COPY_PASTE_H */
diff --git a/tools/testing/selftests/powerpc/alignment/copy_unaligned.c b/tools/testing/selftests/powerpc/alignment/copy_unaligned.c
new file mode 100644
index 000000000000..3a4e26461554
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/copy_unaligned.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2016, Chris Smart, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Calls to copy which are not 128-byte aligned should be caught
10 * and sent a SIGBUS.
11 *
12 */
13
14#include <string.h>
15#include <unistd.h>
16#include "utils.h"
17#include "instructions.h"
18#include "copy_paste_unaligned_common.h"
19
20unsigned int expected_instruction = PPC_INST_COPY;
21unsigned int instruction_mask = 0xfc0007fe;
22
23int test_copy_unaligned(void)
24{
25 /* Only run this test on a P9 or later */
26 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
27
28 /* Register our signal handler with SIGBUS */
29 setup_signal_handler();
30
31 /* +1 makes buf unaligned */
32 copy(cacheline_buf+1);
33
34 /* We should not get here */
35 return 1;
36}
37
38int main(int argc, char *argv[])
39{
40 return test_harness(test_copy_unaligned, "test_copy_unaligned");
41}
diff --git a/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c b/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c
new file mode 100644
index 000000000000..6e0ad045fcc3
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/paste_last_unaligned.c
@@ -0,0 +1,43 @@
1/*
2 * Copyright 2016, Chris Smart, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Calls to paste_last which are not 128-byte aligned should be
10 * caught and sent a SIGBUS.
11 *
12 */
13
14#include <string.h>
15#include <unistd.h>
16#include "utils.h"
17#include "instructions.h"
18#include "copy_paste_unaligned_common.h"
19
20unsigned int expected_instruction = PPC_INST_PASTE_LAST;
21unsigned int instruction_mask = 0xfc2007ff;
22
23int test_paste_last_unaligned(void)
24{
25 /* Only run this test on a P9 or later */
26 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
27
28 /* Register our signal handler with SIGBUS */
29 setup_signal_handler();
30
31 copy(cacheline_buf);
32
33 /* +1 makes buf unaligned */
34 paste_last(cacheline_buf+1);
35
36 /* We should not get here */
37 return 1;
38}
39
40int main(int argc, char *argv[])
41{
42 return test_harness(test_paste_last_unaligned, "test_paste_last_unaligned");
43}
diff --git a/tools/testing/selftests/powerpc/alignment/paste_unaligned.c b/tools/testing/selftests/powerpc/alignment/paste_unaligned.c
new file mode 100644
index 000000000000..6f982b45e4bd
--- /dev/null
+++ b/tools/testing/selftests/powerpc/alignment/paste_unaligned.c
@@ -0,0 +1,43 @@
1/*
2 * Copyright 2016, Chris Smart, IBM Corporation.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Calls to paste which are not 128-byte aligned should be caught
10 * and sent a SIGBUS.
11 *
12 */
13
14#include <string.h>
15#include <unistd.h>
16#include "utils.h"
17#include "instructions.h"
18#include "copy_paste_unaligned_common.h"
19
20unsigned int expected_instruction = PPC_INST_PASTE;
21unsigned int instruction_mask = 0xfc0007fe;
22
23int test_paste_unaligned(void)
24{
25 /* Only run this test on a P9 or later */
26 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_3_00));
27
28 /* Register our signal handler with SIGBUS */
29 setup_signal_handler();
30
31 copy(cacheline_buf);
32
33 /* +1 makes buf unaligned */
34 paste(cacheline_buf+1);
35
36 /* We should not get here */
37 return 1;
38}
39
40int main(int argc, char *argv[])
41{
42 return test_harness(test_paste_unaligned, "test_paste_unaligned");
43}
diff --git a/tools/testing/selftests/powerpc/benchmarks/.gitignore b/tools/testing/selftests/powerpc/benchmarks/.gitignore
index 6fa673316ac2..bce49ebd869e 100644
--- a/tools/testing/selftests/powerpc/benchmarks/.gitignore
+++ b/tools/testing/selftests/powerpc/benchmarks/.gitignore
@@ -1,2 +1,4 @@
1gettimeofday 1gettimeofday
2context_switch 2context_switch
3mmap_bench
4futex_bench \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/benchmarks/Makefile b/tools/testing/selftests/powerpc/benchmarks/Makefile
index 912445ff7ce7..a9adfb7de78f 100644
--- a/tools/testing/selftests/powerpc/benchmarks/Makefile
+++ b/tools/testing/selftests/powerpc/benchmarks/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := gettimeofday context_switch 1TEST_PROGS := gettimeofday context_switch mmap_bench futex_bench
2 2
3CFLAGS += -O2 3CFLAGS += -O2
4 4
@@ -7,6 +7,7 @@ all: $(TEST_PROGS)
7$(TEST_PROGS): ../harness.c 7$(TEST_PROGS): ../harness.c
8 8
9context_switch: ../utils.c 9context_switch: ../utils.c
10context_switch: CFLAGS += -maltivec -mvsx -mabi=altivec
10context_switch: LDLIBS += -lpthread 11context_switch: LDLIBS += -lpthread
11 12
12include ../../lib.mk 13include ../../lib.mk
diff --git a/tools/testing/selftests/powerpc/benchmarks/context_switch.c b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
index 7b785941adec..a36883ad48a4 100644
--- a/tools/testing/selftests/powerpc/benchmarks/context_switch.c
+++ b/tools/testing/selftests/powerpc/benchmarks/context_switch.c
@@ -25,7 +25,9 @@
25#include <sys/types.h> 25#include <sys/types.h>
26#include <sys/shm.h> 26#include <sys/shm.h>
27#include <linux/futex.h> 27#include <linux/futex.h>
28 28#ifdef __powerpc__
29#include <altivec.h>
30#endif
29#include "../utils.h" 31#include "../utils.h"
30 32
31static unsigned int timeout = 30; 33static unsigned int timeout = 30;
@@ -37,12 +39,15 @@ static int touch_fp = 1;
37double fp; 39double fp;
38 40
39static int touch_vector = 1; 41static int touch_vector = 1;
40typedef int v4si __attribute__ ((vector_size (16))); 42vector int a, b, c;
41v4si a, b, c;
42 43
43#ifdef __powerpc__ 44#ifdef __powerpc__
44static int touch_altivec = 1; 45static int touch_altivec = 1;
45 46
47/*
48 * Note: LTO (Link Time Optimisation) doesn't play well with this function
49 * attribute. Be very careful enabling LTO for this test.
50 */
46static void __attribute__((__target__("no-vsx"))) altivec_touch_fn(void) 51static void __attribute__((__target__("no-vsx"))) altivec_touch_fn(void)
47{ 52{
48 c = a + b; 53 c = a + b;
@@ -369,11 +374,11 @@ static void usage(void)
369 fprintf(stderr, "\t\t--process\tUse processes (default threads)\n"); 374 fprintf(stderr, "\t\t--process\tUse processes (default threads)\n");
370 fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n"); 375 fprintf(stderr, "\t\t--timeout=X\tDuration in seconds to run (default 30)\n");
371 fprintf(stderr, "\t\t--vdso\t\ttouch VDSO\n"); 376 fprintf(stderr, "\t\t--vdso\t\ttouch VDSO\n");
372 fprintf(stderr, "\t\t--fp\t\ttouch FP\n"); 377 fprintf(stderr, "\t\t--no-fp\t\tDon't touch FP\n");
373#ifdef __powerpc__ 378#ifdef __powerpc__
374 fprintf(stderr, "\t\t--altivec\ttouch altivec\n"); 379 fprintf(stderr, "\t\t--no-altivec\tDon't touch altivec\n");
375#endif 380#endif
376 fprintf(stderr, "\t\t--vector\ttouch vector\n"); 381 fprintf(stderr, "\t\t--no-vector\tDon't touch vector\n");
377} 382}
378 383
379int main(int argc, char *argv[]) 384int main(int argc, char *argv[])
diff --git a/tools/testing/selftests/powerpc/benchmarks/futex_bench.c b/tools/testing/selftests/powerpc/benchmarks/futex_bench.c
new file mode 100644
index 000000000000..2fc711d9150d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/benchmarks/futex_bench.c
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2016, Anton Blanchard, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#define _GNU_SOURCE
7
8#include <stdio.h>
9#include <sys/syscall.h>
10#include <time.h>
11#include <unistd.h>
12#include <linux/futex.h>
13
14#include "utils.h"
15
16#define ITERATIONS 100000000
17
18#define futex(A, B, C, D, E, F) syscall(__NR_futex, A, B, C, D, E, F)
19
20int test_futex(void)
21{
22 struct timespec ts_start, ts_end;
23 unsigned long i = ITERATIONS;
24
25 clock_gettime(CLOCK_MONOTONIC, &ts_start);
26
27 while (i--) {
28 unsigned int addr = 0;
29 futex(&addr, FUTEX_WAKE, 1, NULL, NULL, 0);
30 }
31
32 clock_gettime(CLOCK_MONOTONIC, &ts_end);
33
34 printf("time = %.6f\n", ts_end.tv_sec - ts_start.tv_sec + (ts_end.tv_nsec - ts_start.tv_nsec) / 1e9);
35
36 return 0;
37}
38
39int main(void)
40{
41 return test_harness(test_futex, "futex_bench");
42}
diff --git a/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c
new file mode 100644
index 000000000000..8d084a2d6e74
--- /dev/null
+++ b/tools/testing/selftests/powerpc/benchmarks/mmap_bench.c
@@ -0,0 +1,41 @@
1/*
2 * Copyright 2016, Anton Blanchard, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <sys/mman.h>
9#include <time.h>
10
11#include "utils.h"
12
13#define ITERATIONS 5000000
14
15#define MEMSIZE (128 * 1024 * 1024)
16
17int test_mmap(void)
18{
19 struct timespec ts_start, ts_end;
20 unsigned long i = ITERATIONS;
21
22 clock_gettime(CLOCK_MONOTONIC, &ts_start);
23
24 while (i--) {
25 char *c = mmap(NULL, MEMSIZE, PROT_READ|PROT_WRITE,
26 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
27 FAIL_IF(c == MAP_FAILED);
28 munmap(c, MEMSIZE);
29 }
30
31 clock_gettime(CLOCK_MONOTONIC, &ts_end);
32
33 printf("time = %.6f\n", ts_end.tv_sec - ts_start.tv_sec + (ts_end.tv_nsec - ts_start.tv_nsec) / 1e9);
34
35 return 0;
36}
37
38int main(void)
39{
40 return test_harness(test_mmap, "mmap_bench");
41}
diff --git a/tools/testing/selftests/powerpc/copyloops/asm/export.h b/tools/testing/selftests/powerpc/copyloops/asm/export.h
new file mode 100644
index 000000000000..2d14a9b4248c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/copyloops/asm/export.h
@@ -0,0 +1 @@
#define EXPORT_SYMBOL(x)
diff --git a/tools/testing/selftests/powerpc/fpu_asm.h b/tools/testing/selftests/powerpc/fpu_asm.h
new file mode 100644
index 000000000000..6a387d255e27
--- /dev/null
+++ b/tools/testing/selftests/powerpc/fpu_asm.h
@@ -0,0 +1,80 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#ifndef _SELFTESTS_POWERPC_FPU_ASM_H
11#define _SELFTESTS_POWERPC_FPU_ASM_H
12#include "basic_asm.h"
13
14#define PUSH_FPU(stack_size) \
15 stfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \
16 stfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \
17 stfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \
18 stfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \
19 stfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \
20 stfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \
21 stfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \
22 stfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \
23 stfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \
24 stfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \
25 stfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \
26 stfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \
27 stfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \
28 stfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \
29 stfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \
30 stfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \
31 stfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \
32 stfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1);
33
34#define POP_FPU(stack_size) \
35 lfd f31,(stack_size + STACK_FRAME_MIN_SIZE)(%r1); \
36 lfd f30,(stack_size + STACK_FRAME_MIN_SIZE - 8)(%r1); \
37 lfd f29,(stack_size + STACK_FRAME_MIN_SIZE - 16)(%r1); \
38 lfd f28,(stack_size + STACK_FRAME_MIN_SIZE - 24)(%r1); \
39 lfd f27,(stack_size + STACK_FRAME_MIN_SIZE - 32)(%r1); \
40 lfd f26,(stack_size + STACK_FRAME_MIN_SIZE - 40)(%r1); \
41 lfd f25,(stack_size + STACK_FRAME_MIN_SIZE - 48)(%r1); \
42 lfd f24,(stack_size + STACK_FRAME_MIN_SIZE - 56)(%r1); \
43 lfd f23,(stack_size + STACK_FRAME_MIN_SIZE - 64)(%r1); \
44 lfd f22,(stack_size + STACK_FRAME_MIN_SIZE - 72)(%r1); \
45 lfd f21,(stack_size + STACK_FRAME_MIN_SIZE - 80)(%r1); \
46 lfd f20,(stack_size + STACK_FRAME_MIN_SIZE - 88)(%r1); \
47 lfd f19,(stack_size + STACK_FRAME_MIN_SIZE - 96)(%r1); \
48 lfd f18,(stack_size + STACK_FRAME_MIN_SIZE - 104)(%r1); \
49 lfd f17,(stack_size + STACK_FRAME_MIN_SIZE - 112)(%r1); \
50 lfd f16,(stack_size + STACK_FRAME_MIN_SIZE - 120)(%r1); \
51 lfd f15,(stack_size + STACK_FRAME_MIN_SIZE - 128)(%r1); \
52 lfd f14,(stack_size + STACK_FRAME_MIN_SIZE - 136)(%r1);
53
54/*
55 * Careful calling this, it will 'clobber' fpu (by design)
56 * Don't call this from C
57 */
58FUNC_START(load_fpu)
59 lfd f14,0(r3)
60 lfd f15,8(r3)
61 lfd f16,16(r3)
62 lfd f17,24(r3)
63 lfd f18,32(r3)
64 lfd f19,40(r3)
65 lfd f20,48(r3)
66 lfd f21,56(r3)
67 lfd f22,64(r3)
68 lfd f23,72(r3)
69 lfd f24,80(r3)
70 lfd f25,88(r3)
71 lfd f26,96(r3)
72 lfd f27,104(r3)
73 lfd f28,112(r3)
74 lfd f29,120(r3)
75 lfd f30,128(r3)
76 lfd f31,136(r3)
77 blr
78FUNC_END(load_fpu)
79
80#endif /* _SELFTESTS_POWERPC_FPU_ASM_H */
diff --git a/tools/testing/selftests/powerpc/gpr_asm.h b/tools/testing/selftests/powerpc/gpr_asm.h
new file mode 100644
index 000000000000..f6f38852d3a0
--- /dev/null
+++ b/tools/testing/selftests/powerpc/gpr_asm.h
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#ifndef _SELFTESTS_POWERPC_GPR_ASM_H
11#define _SELFTESTS_POWERPC_GPR_ASM_H
12
13#include "basic_asm.h"
14
15#define __PUSH_NVREGS(top_pos); \
16 std r31,(top_pos)(%r1); \
17 std r30,(top_pos - 8)(%r1); \
18 std r29,(top_pos - 16)(%r1); \
19 std r28,(top_pos - 24)(%r1); \
20 std r27,(top_pos - 32)(%r1); \
21 std r26,(top_pos - 40)(%r1); \
22 std r25,(top_pos - 48)(%r1); \
23 std r24,(top_pos - 56)(%r1); \
24 std r23,(top_pos - 64)(%r1); \
25 std r22,(top_pos - 72)(%r1); \
26 std r21,(top_pos - 80)(%r1); \
27 std r20,(top_pos - 88)(%r1); \
28 std r19,(top_pos - 96)(%r1); \
29 std r18,(top_pos - 104)(%r1); \
30 std r17,(top_pos - 112)(%r1); \
31 std r16,(top_pos - 120)(%r1); \
32 std r15,(top_pos - 128)(%r1); \
33 std r14,(top_pos - 136)(%r1)
34
35#define __POP_NVREGS(top_pos); \
36 ld r31,(top_pos)(%r1); \
37 ld r30,(top_pos - 8)(%r1); \
38 ld r29,(top_pos - 16)(%r1); \
39 ld r28,(top_pos - 24)(%r1); \
40 ld r27,(top_pos - 32)(%r1); \
41 ld r26,(top_pos - 40)(%r1); \
42 ld r25,(top_pos - 48)(%r1); \
43 ld r24,(top_pos - 56)(%r1); \
44 ld r23,(top_pos - 64)(%r1); \
45 ld r22,(top_pos - 72)(%r1); \
46 ld r21,(top_pos - 80)(%r1); \
47 ld r20,(top_pos - 88)(%r1); \
48 ld r19,(top_pos - 96)(%r1); \
49 ld r18,(top_pos - 104)(%r1); \
50 ld r17,(top_pos - 112)(%r1); \
51 ld r16,(top_pos - 120)(%r1); \
52 ld r15,(top_pos - 128)(%r1); \
53 ld r14,(top_pos - 136)(%r1)
54
55#define PUSH_NVREGS(stack_size) \
56 __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE)
57
58/* 18 NV FPU REGS */
59#define PUSH_NVREGS_BELOW_FPU(stack_size) \
60 __PUSH_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8))
61
62#define POP_NVREGS(stack_size) \
63 __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE)
64
65/* 18 NV FPU REGS */
66#define POP_NVREGS_BELOW_FPU(stack_size) \
67 __POP_NVREGS(stack_size + STACK_FRAME_MIN_SIZE - (18 * 8))
68
69/*
70 * Careful calling this, it will 'clobber' NVGPRs (by design)
71 * Don't call this from C
72 */
73FUNC_START(load_gpr)
74 ld r14,0(r3)
75 ld r15,8(r3)
76 ld r16,16(r3)
77 ld r17,24(r3)
78 ld r18,32(r3)
79 ld r19,40(r3)
80 ld r20,48(r3)
81 ld r21,56(r3)
82 ld r22,64(r3)
83 ld r23,72(r3)
84 ld r24,80(r3)
85 ld r25,88(r3)
86 ld r26,96(r3)
87 ld r27,104(r3)
88 ld r28,112(r3)
89 ld r29,120(r3)
90 ld r30,128(r3)
91 ld r31,136(r3)
92 blr
93FUNC_END(load_gpr)
94
95
96#endif /* _SELFTESTS_POWERPC_GPR_ASM_H */
diff --git a/tools/testing/selftests/powerpc/harness.c b/tools/testing/selftests/powerpc/harness.c
index 52f9be7f61f0..248a820048df 100644
--- a/tools/testing/selftests/powerpc/harness.c
+++ b/tools/testing/selftests/powerpc/harness.c
@@ -19,9 +19,9 @@
19#include "subunit.h" 19#include "subunit.h"
20#include "utils.h" 20#include "utils.h"
21 21
22#define TIMEOUT 120
23#define KILL_TIMEOUT 5 22#define KILL_TIMEOUT 5
24 23
24static uint64_t timeout = 120;
25 25
26int run_test(int (test_function)(void), char *name) 26int run_test(int (test_function)(void), char *name)
27{ 27{
@@ -44,7 +44,7 @@ int run_test(int (test_function)(void), char *name)
44 setpgid(pid, pid); 44 setpgid(pid, pid);
45 45
46 /* Wake us up in timeout seconds */ 46 /* Wake us up in timeout seconds */
47 alarm(TIMEOUT); 47 alarm(timeout);
48 terminated = false; 48 terminated = false;
49 49
50wait: 50wait:
@@ -94,6 +94,11 @@ static struct sigaction alarm_action = {
94 .sa_handler = alarm_handler, 94 .sa_handler = alarm_handler,
95}; 95};
96 96
97void test_harness_set_timeout(uint64_t time)
98{
99 timeout = time;
100}
101
97int test_harness(int (test_function)(void), char *name) 102int test_harness(int (test_function)(void), char *name)
98{ 103{
99 int rc; 104 int rc;
diff --git a/tools/testing/selftests/powerpc/instructions.h b/tools/testing/selftests/powerpc/instructions.h
new file mode 100644
index 000000000000..0fb0bd3b28c9
--- /dev/null
+++ b/tools/testing/selftests/powerpc/instructions.h
@@ -0,0 +1,68 @@
1#ifndef _SELFTESTS_POWERPC_INSTRUCTIONS_H
2#define _SELFTESTS_POWERPC_INSTRUCTIONS_H
3
4#include <stdio.h>
5#include <stdlib.h>
6
7/* This defines the "copy" instruction from Power ISA 3.0 Book II, section 4.4. */
8#define __COPY(RA, RB, L) \
9 (0x7c00060c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10))
10#define COPY(RA, RB, L) \
11 .long __COPY((RA), (RB), (L))
12
13static inline void copy(void *i)
14{
15 asm volatile(str(COPY(0, %0, 0))";"
16 :
17 : "b" (i)
18 : "memory"
19 );
20}
21
22static inline void copy_first(void *i)
23{
24 asm volatile(str(COPY(0, %0, 1))";"
25 :
26 : "b" (i)
27 : "memory"
28 );
29}
30
31/* This defines the "paste" instruction from Power ISA 3.0 Book II, section 4.4. */
32#define __PASTE(RA, RB, L, RC) \
33 (0x7c00070c | (RA) << (31-15) | (RB) << (31-20) | (L) << (31-10) | (RC) << (31-31))
34#define PASTE(RA, RB, L, RC) \
35 .long __PASTE((RA), (RB), (L), (RC))
36
37static inline int paste(void *i)
38{
39 int cr;
40
41 asm volatile(str(PASTE(0, %1, 0, 0))";"
42 "mfcr %0;"
43 : "=r" (cr)
44 : "b" (i)
45 : "memory"
46 );
47 return cr;
48}
49
50static inline int paste_last(void *i)
51{
52 int cr;
53
54 asm volatile(str(PASTE(0, %1, 1, 1))";"
55 "mfcr %0;"
56 : "=r" (cr)
57 : "b" (i)
58 : "memory"
59 );
60 return cr;
61}
62
63#define PPC_INST_COPY __COPY(0, 0, 0)
64#define PPC_INST_COPY_FIRST __COPY(0, 0, 1)
65#define PPC_INST_PASTE __PASTE(0, 0, 0, 0)
66#define PPC_INST_PASTE_LAST __PASTE(0, 0, 1, 1)
67
68#endif /* _SELFTESTS_POWERPC_INSTRUCTIONS_H */
diff --git a/tools/testing/selftests/powerpc/math/.gitignore b/tools/testing/selftests/powerpc/math/.gitignore
index 4fe13a439fd7..50ded63e25b7 100644
--- a/tools/testing/selftests/powerpc/math/.gitignore
+++ b/tools/testing/selftests/powerpc/math/.gitignore
@@ -4,3 +4,4 @@ fpu_preempt
4vmx_preempt 4vmx_preempt
5fpu_signal 5fpu_signal
6vmx_signal 6vmx_signal
7vsx_preempt
diff --git a/tools/testing/selftests/powerpc/math/Makefile b/tools/testing/selftests/powerpc/math/Makefile
index 5b88875d5955..a505b66d408a 100644
--- a/tools/testing/selftests/powerpc/math/Makefile
+++ b/tools/testing/selftests/powerpc/math/Makefile
@@ -1,4 +1,4 @@
1TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal 1TEST_PROGS := fpu_syscall fpu_preempt fpu_signal vmx_syscall vmx_preempt vmx_signal vsx_preempt
2 2
3all: $(TEST_PROGS) 3all: $(TEST_PROGS)
4 4
@@ -13,6 +13,9 @@ vmx_syscall: vmx_asm.S
13vmx_preempt: vmx_asm.S 13vmx_preempt: vmx_asm.S
14vmx_signal: vmx_asm.S 14vmx_signal: vmx_asm.S
15 15
16vsx_preempt: CFLAGS += -mvsx
17vsx_preempt: vsx_asm.S
18
16include ../../lib.mk 19include ../../lib.mk
17 20
18clean: 21clean:
diff --git a/tools/testing/selftests/powerpc/math/fpu_asm.S b/tools/testing/selftests/powerpc/math/fpu_asm.S
index f3711d80e709..241f067a510f 100644
--- a/tools/testing/selftests/powerpc/math/fpu_asm.S
+++ b/tools/testing/selftests/powerpc/math/fpu_asm.S
@@ -8,70 +8,7 @@
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "../basic_asm.h"
11 11#include "../fpu_asm.h"
12#define PUSH_FPU(pos) \
13 stfd f14,pos(sp); \
14 stfd f15,pos+8(sp); \
15 stfd f16,pos+16(sp); \
16 stfd f17,pos+24(sp); \
17 stfd f18,pos+32(sp); \
18 stfd f19,pos+40(sp); \
19 stfd f20,pos+48(sp); \
20 stfd f21,pos+56(sp); \
21 stfd f22,pos+64(sp); \
22 stfd f23,pos+72(sp); \
23 stfd f24,pos+80(sp); \
24 stfd f25,pos+88(sp); \
25 stfd f26,pos+96(sp); \
26 stfd f27,pos+104(sp); \
27 stfd f28,pos+112(sp); \
28 stfd f29,pos+120(sp); \
29 stfd f30,pos+128(sp); \
30 stfd f31,pos+136(sp);
31
32#define POP_FPU(pos) \
33 lfd f14,pos(sp); \
34 lfd f15,pos+8(sp); \
35 lfd f16,pos+16(sp); \
36 lfd f17,pos+24(sp); \
37 lfd f18,pos+32(sp); \
38 lfd f19,pos+40(sp); \
39 lfd f20,pos+48(sp); \
40 lfd f21,pos+56(sp); \
41 lfd f22,pos+64(sp); \
42 lfd f23,pos+72(sp); \
43 lfd f24,pos+80(sp); \
44 lfd f25,pos+88(sp); \
45 lfd f26,pos+96(sp); \
46 lfd f27,pos+104(sp); \
47 lfd f28,pos+112(sp); \
48 lfd f29,pos+120(sp); \
49 lfd f30,pos+128(sp); \
50 lfd f31,pos+136(sp);
51
52# Careful calling this, it will 'clobber' fpu (by design)
53# Don't call this from C
54FUNC_START(load_fpu)
55 lfd f14,0(r3)
56 lfd f15,8(r3)
57 lfd f16,16(r3)
58 lfd f17,24(r3)
59 lfd f18,32(r3)
60 lfd f19,40(r3)
61 lfd f20,48(r3)
62 lfd f21,56(r3)
63 lfd f22,64(r3)
64 lfd f23,72(r3)
65 lfd f24,80(r3)
66 lfd f25,88(r3)
67 lfd f26,96(r3)
68 lfd f27,104(r3)
69 lfd f28,112(r3)
70 lfd f29,120(r3)
71 lfd f30,128(r3)
72 lfd f31,136(r3)
73 blr
74FUNC_END(load_fpu)
75 12
76FUNC_START(check_fpu) 13FUNC_START(check_fpu)
77 mr r4,r3 14 mr r4,r3
@@ -138,9 +75,9 @@ FUNC_START(test_fpu)
138 # r4 holds pointer to the pid 75 # r4 holds pointer to the pid
139 # f14-f31 are non volatiles 76 # f14-f31 are non volatiles
140 PUSH_BASIC_STACK(256) 77 PUSH_BASIC_STACK(256)
78 PUSH_FPU(256)
141 std r3,STACK_FRAME_PARAM(0)(sp) # Address of darray 79 std r3,STACK_FRAME_PARAM(0)(sp) # Address of darray
142 std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid 80 std r4,STACK_FRAME_PARAM(1)(sp) # Address of pid
143 PUSH_FPU(STACK_FRAME_LOCAL(2,0))
144 81
145 bl load_fpu 82 bl load_fpu
146 nop 83 nop
@@ -155,7 +92,7 @@ FUNC_START(test_fpu)
155 bl check_fpu 92 bl check_fpu
156 nop 93 nop
157 94
158 POP_FPU(STACK_FRAME_LOCAL(2,0)) 95 POP_FPU(256)
159 POP_BASIC_STACK(256) 96 POP_BASIC_STACK(256)
160 blr 97 blr
161FUNC_END(test_fpu) 98FUNC_END(test_fpu)
@@ -166,10 +103,10 @@ FUNC_END(test_fpu)
166# registers while running is not zero. 103# registers while running is not zero.
167FUNC_START(preempt_fpu) 104FUNC_START(preempt_fpu)
168 PUSH_BASIC_STACK(256) 105 PUSH_BASIC_STACK(256)
106 PUSH_FPU(256)
169 std r3,STACK_FRAME_PARAM(0)(sp) # double *darray 107 std r3,STACK_FRAME_PARAM(0)(sp) # double *darray
170 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting 108 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
171 std r5,STACK_FRAME_PARAM(2)(sp) # int *running 109 std r5,STACK_FRAME_PARAM(2)(sp) # int *running
172 PUSH_FPU(STACK_FRAME_LOCAL(3,0))
173 110
174 bl load_fpu 111 bl load_fpu
175 nop 112 nop
@@ -192,7 +129,7 @@ FUNC_START(preempt_fpu)
192 cmpwi r5,0 129 cmpwi r5,0
193 bne 2b 130 bne 2b
194 131
1953: POP_FPU(STACK_FRAME_LOCAL(3,0)) 1323: POP_FPU(256)
196 POP_BASIC_STACK(256) 133 POP_BASIC_STACK(256)
197 blr 134 blr
198FUNC_END(preempt_fpu) 135FUNC_END(preempt_fpu)
diff --git a/tools/testing/selftests/powerpc/math/vmx_asm.S b/tools/testing/selftests/powerpc/math/vmx_asm.S
index 1b8c248b3ac1..fd74da488625 100644
--- a/tools/testing/selftests/powerpc/math/vmx_asm.S
+++ b/tools/testing/selftests/powerpc/math/vmx_asm.S
@@ -8,90 +8,7 @@
8 */ 8 */
9 9
10#include "../basic_asm.h" 10#include "../basic_asm.h"
11 11#include "../vmx_asm.h"
12# POS MUST BE 16 ALIGNED!
13#define PUSH_VMX(pos,reg) \
14 li reg,pos; \
15 stvx v20,reg,sp; \
16 addi reg,reg,16; \
17 stvx v21,reg,sp; \
18 addi reg,reg,16; \
19 stvx v22,reg,sp; \
20 addi reg,reg,16; \
21 stvx v23,reg,sp; \
22 addi reg,reg,16; \
23 stvx v24,reg,sp; \
24 addi reg,reg,16; \
25 stvx v25,reg,sp; \
26 addi reg,reg,16; \
27 stvx v26,reg,sp; \
28 addi reg,reg,16; \
29 stvx v27,reg,sp; \
30 addi reg,reg,16; \
31 stvx v28,reg,sp; \
32 addi reg,reg,16; \
33 stvx v29,reg,sp; \
34 addi reg,reg,16; \
35 stvx v30,reg,sp; \
36 addi reg,reg,16; \
37 stvx v31,reg,sp;
38
39# POS MUST BE 16 ALIGNED!
40#define POP_VMX(pos,reg) \
41 li reg,pos; \
42 lvx v20,reg,sp; \
43 addi reg,reg,16; \
44 lvx v21,reg,sp; \
45 addi reg,reg,16; \
46 lvx v22,reg,sp; \
47 addi reg,reg,16; \
48 lvx v23,reg,sp; \
49 addi reg,reg,16; \
50 lvx v24,reg,sp; \
51 addi reg,reg,16; \
52 lvx v25,reg,sp; \
53 addi reg,reg,16; \
54 lvx v26,reg,sp; \
55 addi reg,reg,16; \
56 lvx v27,reg,sp; \
57 addi reg,reg,16; \
58 lvx v28,reg,sp; \
59 addi reg,reg,16; \
60 lvx v29,reg,sp; \
61 addi reg,reg,16; \
62 lvx v30,reg,sp; \
63 addi reg,reg,16; \
64 lvx v31,reg,sp;
65
66# Carefull this will 'clobber' vmx (by design)
67# Don't call this from C
68FUNC_START(load_vmx)
69 li r5,0
70 lvx v20,r5,r3
71 addi r5,r5,16
72 lvx v21,r5,r3
73 addi r5,r5,16
74 lvx v22,r5,r3
75 addi r5,r5,16
76 lvx v23,r5,r3
77 addi r5,r5,16
78 lvx v24,r5,r3
79 addi r5,r5,16
80 lvx v25,r5,r3
81 addi r5,r5,16
82 lvx v26,r5,r3
83 addi r5,r5,16
84 lvx v27,r5,r3
85 addi r5,r5,16
86 lvx v28,r5,r3
87 addi r5,r5,16
88 lvx v29,r5,r3
89 addi r5,r5,16
90 lvx v30,r5,r3
91 addi r5,r5,16
92 lvx v31,r5,r3
93 blr
94FUNC_END(load_vmx)
95 12
96# Should be safe from C, only touches r4, r5 and v0,v1,v2 13# Should be safe from C, only touches r4, r5 and v0,v1,v2
97FUNC_START(check_vmx) 14FUNC_START(check_vmx)
diff --git a/tools/testing/selftests/powerpc/math/vsx_asm.S b/tools/testing/selftests/powerpc/math/vsx_asm.S
new file mode 100644
index 000000000000..a110dd882d5e
--- /dev/null
+++ b/tools/testing/selftests/powerpc/math/vsx_asm.S
@@ -0,0 +1,61 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "../basic_asm.h"
11#include "../vsx_asm.h"
12
13#long check_vsx(vector int *r3);
14#This function wraps storeing VSX regs to the end of an array and a
15#call to a comparison function in C which boils down to a memcmp()
16FUNC_START(check_vsx)
17 PUSH_BASIC_STACK(32)
18 std r3,STACK_FRAME_PARAM(0)(sp)
19 addi r3, r3, 16 * 12 #Second half of array
20 bl store_vsx
21 ld r3,STACK_FRAME_PARAM(0)(sp)
22 bl vsx_memcmp
23 POP_BASIC_STACK(32)
24 blr
25FUNC_END(check_vsx)
26
27# int preempt_vmx(vector int *varray, int *threads_starting,
28# int *running);
29# On starting will (atomically) decrement threads_starting as a signal
30# that the VMX have been loaded with varray. Will proceed to check the
31# validity of the VMX registers while running is not zero.
32FUNC_START(preempt_vsx)
33 PUSH_BASIC_STACK(512)
34 std r3,STACK_FRAME_PARAM(0)(sp) # vector int *varray
35 std r4,STACK_FRAME_PARAM(1)(sp) # int *threads_starting
36 std r5,STACK_FRAME_PARAM(2)(sp) # int *running
37
38 bl load_vsx
39 nop
40
41 sync
42 # Atomic DEC
43 ld r3,STACK_FRAME_PARAM(1)(sp)
441: lwarx r4,0,r3
45 addi r4,r4,-1
46 stwcx. r4,0,r3
47 bne- 1b
48
492: ld r3,STACK_FRAME_PARAM(0)(sp)
50 bl check_vsx
51 nop
52 cmpdi r3,0
53 bne 3f
54 ld r4,STACK_FRAME_PARAM(2)(sp)
55 ld r5,0(r4)
56 cmpwi r5,0
57 bne 2b
58
593: POP_BASIC_STACK(512)
60 blr
61FUNC_END(preempt_vsx)
diff --git a/tools/testing/selftests/powerpc/math/vsx_preempt.c b/tools/testing/selftests/powerpc/math/vsx_preempt.c
new file mode 100644
index 000000000000..6387f03a0a6a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/math/vsx_preempt.c
@@ -0,0 +1,147 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * This test attempts to see if the VSX registers change across preemption.
10 * There is no way to be sure preemption happened so this test just
11 * uses many threads and a long wait. As such, a successful test
12 * doesn't mean much but a failure is bad.
13 */
14
15#include <stdio.h>
16#include <string.h>
17#include <unistd.h>
18#include <sys/syscall.h>
19#include <sys/time.h>
20#include <sys/types.h>
21#include <sys/wait.h>
22#include <stdlib.h>
23#include <pthread.h>
24
25#include "utils.h"
26
27/* Time to wait for workers to get preempted (seconds) */
28#define PREEMPT_TIME 20
29/*
30 * Factor by which to multiply number of online CPUs for total number of
31 * worker threads
32 */
33#define THREAD_FACTOR 8
34
35/*
36 * Ensure there is twice the number of non-volatile VMX regs!
37 * check_vmx() is going to use the other half as space to put the live
38 * registers before calling vsx_memcmp()
39 */
40__thread vector int varray[24] = {
41 {1, 2, 3, 4 }, {5, 6, 7, 8 }, {9, 10,11,12},
42 {13,14,15,16}, {17,18,19,20}, {21,22,23,24},
43 {25,26,27,28}, {29,30,31,32}, {33,34,35,36},
44 {37,38,39,40}, {41,42,43,44}, {45,46,47,48}
45};
46
47int threads_starting;
48int running;
49
50extern long preempt_vsx(vector int *varray, int *threads_starting, int *running);
51
52long vsx_memcmp(vector int *a) {
53 vector int zero = {0, 0, 0, 0};
54 int i;
55
56 FAIL_IF(a != varray);
57
58 for(i = 0; i < 12; i++) {
59 if (memcmp(&a[i + 12], &zero, sizeof(vector int)) == 0) {
60 fprintf(stderr, "Detected zero from the VSX reg %d\n", i + 12);
61 return 2;
62 }
63 }
64
65 if (memcmp(a, &a[12], 12 * sizeof(vector int))) {
66 long *p = (long *)a;
67 fprintf(stderr, "VSX mismatch\n");
68 for (i = 0; i < 24; i=i+2)
69 fprintf(stderr, "%d: 0x%08lx%08lx | 0x%08lx%08lx\n",
70 i/2 + i%2 + 20, p[i], p[i + 1], p[i + 24], p[i + 25]);
71 return 1;
72 }
73 return 0;
74}
75
76void *preempt_vsx_c(void *p)
77{
78 int i, j;
79 long rc;
80 srand(pthread_self());
81 for (i = 0; i < 12; i++)
82 for (j = 0; j < 4; j++) {
83 varray[i][j] = rand();
84 /* Don't want zero because it hides kernel problems */
85 if (varray[i][j] == 0)
86 j--;
87 }
88 rc = preempt_vsx(varray, &threads_starting, &running);
89 if (rc == 2)
90 fprintf(stderr, "Caught zeros in VSX compares\n");
91 return (void *)rc;
92}
93
94int test_preempt_vsx(void)
95{
96 int i, rc, threads;
97 pthread_t *tids;
98
99 threads = sysconf(_SC_NPROCESSORS_ONLN) * THREAD_FACTOR;
100 tids = malloc(threads * sizeof(pthread_t));
101 FAIL_IF(!tids);
102
103 running = true;
104 threads_starting = threads;
105 for (i = 0; i < threads; i++) {
106 rc = pthread_create(&tids[i], NULL, preempt_vsx_c, NULL);
107 FAIL_IF(rc);
108 }
109
110 setbuf(stdout, NULL);
111 /* Not really nessesary but nice to wait for every thread to start */
112 printf("\tWaiting for %d workers to start...", threads_starting);
113 while(threads_starting)
114 asm volatile("": : :"memory");
115 printf("done\n");
116
117 printf("\tWaiting for %d seconds to let some workers get preempted...", PREEMPT_TIME);
118 sleep(PREEMPT_TIME);
119 printf("done\n");
120
121 printf("\tStopping workers...");
122 /*
123 * Working are checking this value every loop. In preempt_vsx 'cmpwi r5,0; bne 2b'.
124 * r5 will have loaded the value of running.
125 */
126 running = 0;
127 for (i = 0; i < threads; i++) {
128 void *rc_p;
129 pthread_join(tids[i], &rc_p);
130
131 /*
132 * Harness will say the fail was here, look at why preempt_vsx
133 * returned
134 */
135 if ((long) rc_p)
136 printf("oops\n");
137 FAIL_IF((long) rc_p);
138 }
139 printf("done\n");
140
141 return 0;
142}
143
144int main(int argc, char *argv[])
145{
146 return test_harness(test_preempt_vsx, "vsx_preempt");
147}
diff --git a/tools/testing/selftests/powerpc/mm/.gitignore b/tools/testing/selftests/powerpc/mm/.gitignore
index b43ade0ec861..e715a3f2fbf4 100644
--- a/tools/testing/selftests/powerpc/mm/.gitignore
+++ b/tools/testing/selftests/powerpc/mm/.gitignore
@@ -1,3 +1,4 @@
1hugetlb_vs_thp_test 1hugetlb_vs_thp_test
2subpage_prot 2subpage_prot
3tempfile 3tempfile
4prot_sao \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/mm/Makefile b/tools/testing/selftests/powerpc/mm/Makefile
index ee179e22308c..3bdb96eae558 100644
--- a/tools/testing/selftests/powerpc/mm/Makefile
+++ b/tools/testing/selftests/powerpc/mm/Makefile
@@ -1,13 +1,15 @@
1noarg: 1noarg:
2 $(MAKE) -C ../ 2 $(MAKE) -C ../
3 3
4TEST_PROGS := hugetlb_vs_thp_test subpage_prot 4TEST_PROGS := hugetlb_vs_thp_test subpage_prot prot_sao
5TEST_FILES := tempfile 5TEST_FILES := tempfile
6 6
7all: $(TEST_PROGS) $(TEST_FILES) 7all: $(TEST_PROGS) $(TEST_FILES)
8 8
9$(TEST_PROGS): ../harness.c 9$(TEST_PROGS): ../harness.c
10 10
11prot_sao: ../utils.c
12
11include ../../lib.mk 13include ../../lib.mk
12 14
13tempfile: 15tempfile:
diff --git a/tools/testing/selftests/powerpc/mm/prot_sao.c b/tools/testing/selftests/powerpc/mm/prot_sao.c
new file mode 100644
index 000000000000..611530d43fa9
--- /dev/null
+++ b/tools/testing/selftests/powerpc/mm/prot_sao.c
@@ -0,0 +1,42 @@
1/*
2 * Copyright 2016, Michael Ellerman, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <sys/mman.h>
10
11#include <asm/cputable.h>
12
13#include "utils.h"
14
15#define SIZE (64 * 1024)
16
17int test_prot_sao(void)
18{
19 char *p;
20
21 /* 2.06 or later should support SAO */
22 SKIP_IF(!have_hwcap(PPC_FEATURE_ARCH_2_06));
23
24 /*
25 * Ensure we can ask for PROT_SAO.
26 * We can't really verify that it does the right thing, but at least we
27 * confirm the kernel will accept it.
28 */
29 p = mmap(NULL, SIZE, PROT_READ | PROT_WRITE | PROT_SAO,
30 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
31 FAIL_IF(p == MAP_FAILED);
32
33 /* Write to the mapping, to at least cause a fault */
34 memset(p, 0xaa, SIZE);
35
36 return 0;
37}
38
39int main(void)
40{
41 return test_harness(test_prot_sao, "prot-sao");
42}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore
index 42bddbed8b64..44b7df14a936 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/.gitignore
+++ b/tools/testing/selftests/powerpc/pmu/ebb/.gitignore
@@ -20,3 +20,5 @@ back_to_back_ebbs_test
20lost_exception_test 20lost_exception_test
21no_handler_test 21no_handler_test
22cycles_with_mmcr2_test 22cycles_with_mmcr2_test
23ebb_lmr
24ebb_lmr_regs \ No newline at end of file
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/Makefile b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
index 8d2279c4bb4b..6b0453e60d53 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/Makefile
+++ b/tools/testing/selftests/powerpc/pmu/ebb/Makefile
@@ -14,7 +14,7 @@ TEST_PROGS := reg_access_test event_attributes_test cycles_test \
14 fork_cleanup_test ebb_on_child_test \ 14 fork_cleanup_test ebb_on_child_test \
15 ebb_on_willing_child_test back_to_back_ebbs_test \ 15 ebb_on_willing_child_test back_to_back_ebbs_test \
16 lost_exception_test no_handler_test \ 16 lost_exception_test no_handler_test \
17 cycles_with_mmcr2_test 17 cycles_with_mmcr2_test ebb_lmr ebb_lmr_regs
18 18
19all: $(TEST_PROGS) 19all: $(TEST_PROGS)
20 20
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c
new file mode 100644
index 000000000000..c47ebd55ba4d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.c
@@ -0,0 +1,143 @@
1/*
2 * Copyright 2016, Jack Miller, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdlib.h>
7#include <stdio.h>
8
9#include "ebb.h"
10#include "ebb_lmr.h"
11
12#define SIZE (32 * 1024 * 1024) /* 32M */
13#define LM_SIZE 0 /* Smallest encoding, 32M */
14
15#define SECTIONS 64 /* 1 per bit in LMSER */
16#define SECTION_SIZE (SIZE / SECTIONS)
17#define SECTION_LONGS (SECTION_SIZE / sizeof(long))
18
19static unsigned long *test_mem;
20
21static int lmr_count = 0;
22
23void ebb_lmr_handler(void)
24{
25 lmr_count++;
26}
27
28void ldmx_full_section(unsigned long *mem, int section)
29{
30 unsigned long *ptr;
31 int i;
32
33 for (i = 0; i < SECTION_LONGS; i++) {
34 ptr = &mem[(SECTION_LONGS * section) + i];
35 ldmx((unsigned long) &ptr);
36 ebb_lmr_reset();
37 }
38}
39
40unsigned long section_masks[] = {
41 0x8000000000000000,
42 0xFF00000000000000,
43 0x0000000F70000000,
44 0x8000000000000001,
45 0xF0F0F0F0F0F0F0F0,
46 0x0F0F0F0F0F0F0F0F,
47 0x0
48};
49
50int ebb_lmr_section_test(unsigned long *mem)
51{
52 unsigned long *mask = section_masks;
53 int i;
54
55 for (; *mask; mask++) {
56 mtspr(SPRN_LMSER, *mask);
57 printf("Testing mask 0x%016lx\n", mfspr(SPRN_LMSER));
58
59 for (i = 0; i < 64; i++) {
60 lmr_count = 0;
61 ldmx_full_section(mem, i);
62 if (*mask & (1UL << (63 - i)))
63 FAIL_IF(lmr_count != SECTION_LONGS);
64 else
65 FAIL_IF(lmr_count);
66 }
67 }
68
69 return 0;
70}
71
72int ebb_lmr(void)
73{
74 int i;
75
76 SKIP_IF(!lmr_is_supported());
77
78 setup_ebb_handler(ebb_lmr_handler);
79
80 ebb_global_enable();
81
82 FAIL_IF(posix_memalign((void **)&test_mem, SIZE, SIZE) != 0);
83
84 mtspr(SPRN_LMSER, 0);
85
86 FAIL_IF(mfspr(SPRN_LMSER) != 0);
87
88 mtspr(SPRN_LMRR, ((unsigned long)test_mem | LM_SIZE));
89
90 FAIL_IF(mfspr(SPRN_LMRR) != ((unsigned long)test_mem | LM_SIZE));
91
92 /* Read every single byte to ensure we get no false positives */
93 for (i = 0; i < SECTIONS; i++)
94 ldmx_full_section(test_mem, i);
95
96 FAIL_IF(lmr_count != 0);
97
98 /* Turn on the first section */
99
100 mtspr(SPRN_LMSER, (1UL << 63));
101 FAIL_IF(mfspr(SPRN_LMSER) != (1UL << 63));
102
103 /* Enable LM (BESCR) */
104
105 mtspr(SPRN_BESCR, mfspr(SPRN_BESCR) | BESCR_LME);
106 FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LME));
107
108 ldmx((unsigned long)&test_mem);
109
110 FAIL_IF(lmr_count != 1); // exactly one exception
111 FAIL_IF(mfspr(SPRN_BESCR) & BESCR_LME); // LM now disabled
112 FAIL_IF(!(mfspr(SPRN_BESCR) & BESCR_LMEO)); // occurred bit set
113
114 printf("Simple LMR EBB OK\n");
115
116 /* This shouldn't cause an EBB since it's been disabled */
117 ldmx((unsigned long)&test_mem);
118 FAIL_IF(lmr_count != 1);
119
120 printf("LMR disable on EBB OK\n");
121
122 ebb_lmr_reset();
123
124 /* This should cause an EBB or reset is broken */
125 ldmx((unsigned long)&test_mem);
126 FAIL_IF(lmr_count != 2);
127
128 printf("LMR reset EBB OK\n");
129
130 ebb_lmr_reset();
131
132 return ebb_lmr_section_test(test_mem);
133}
134
135int main(void)
136{
137 int ret = test_harness(ebb_lmr, "ebb_lmr");
138
139 if (test_mem)
140 free(test_mem);
141
142 return ret;
143}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h
new file mode 100644
index 000000000000..ef50abd557cd
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr.h
@@ -0,0 +1,39 @@
1#ifndef _SELFTESTS_POWERPC_PMU_EBB_LMR_H
2#define _SELFTESTS_POWERPC_PMU_EBB_LMR_H
3
4#include "reg.h"
5
6#ifndef PPC_FEATURE2_ARCH_3_00
7#define PPC_FEATURE2_ARCH_3_00 0x00800000
8#endif
9
10#define lmr_is_supported() have_hwcap2(PPC_FEATURE2_ARCH_3_00)
11
12static inline void ebb_lmr_reset(void)
13{
14 unsigned long bescr = mfspr(SPRN_BESCR);
15 bescr &= ~(BESCR_LMEO);
16 bescr |= BESCR_LME;
17 mtspr(SPRN_BESCR, bescr);
18}
19
20#define LDMX(t, a, b)\
21 (0x7c00026a | \
22 (((t) & 0x1f) << 21) | \
23 (((a) & 0x1f) << 16) | \
24 (((b) & 0x1f) << 11))
25
26static inline unsigned long ldmx(unsigned long address)
27{
28 unsigned long ret;
29
30 asm volatile ("mr 9, %1\r\n"
31 ".long " __stringify(LDMX(9, 0, 9)) "\r\n"
32 "mr %0, 9\r\n":"=r"(ret)
33 :"r"(address)
34 :"r9");
35
36 return ret;
37}
38
39#endif
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c
new file mode 100644
index 000000000000..aff4241fd88a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/pmu/ebb/ebb_lmr_regs.c
@@ -0,0 +1,37 @@
1/*
2 * Copyright 2016, Jack Miller, IBM Corp.
3 * Licensed under GPLv2.
4 */
5
6#include <stdlib.h>
7#include <stdio.h>
8#include <unistd.h>
9
10#include "ebb.h"
11#include "ebb_lmr.h"
12
13#define CHECKS 10000
14
15int ebb_lmr_regs(void)
16{
17 int i;
18
19 SKIP_IF(!lmr_is_supported());
20
21 ebb_global_enable();
22
23 for (i = 0; i < CHECKS; i++) {
24 mtspr(SPRN_LMRR, i << 25); // skip size and rsvd bits
25 mtspr(SPRN_LMSER, i);
26
27 FAIL_IF(mfspr(SPRN_LMRR) != (i << 25));
28 FAIL_IF(mfspr(SPRN_LMSER) != i);
29 }
30
31 return 0;
32}
33
34int main(void)
35{
36 return test_harness(ebb_lmr_regs, "ebb_lmr_regs");
37}
diff --git a/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
index 5da355135df2..ae9a79086111 100644
--- a/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
+++ b/tools/testing/selftests/powerpc/pmu/ebb/instruction_count_test.c
@@ -51,7 +51,7 @@ static int do_count_loop(struct event *event, uint64_t instructions,
51 printf("Looped for %lu instructions, overhead %lu\n", instructions, overhead); 51 printf("Looped for %lu instructions, overhead %lu\n", instructions, overhead);
52 printf("Expected %lu\n", expected); 52 printf("Expected %lu\n", expected);
53 printf("Actual %llu\n", event->result.value); 53 printf("Actual %llu\n", event->result.value);
54 printf("Error %ld, %f%%\n", difference, percentage); 54 printf("Delta %ld, %f%%\n", difference, percentage);
55 printf("Took %d EBBs\n", ebb_state.stats.ebb_count); 55 printf("Took %d EBBs\n", ebb_state.stats.ebb_count);
56 } 56 }
57 57
diff --git a/tools/testing/selftests/powerpc/pmu/lib.c b/tools/testing/selftests/powerpc/pmu/lib.c
index a361ad3334ce..8b992fa5b478 100644
--- a/tools/testing/selftests/powerpc/pmu/lib.c
+++ b/tools/testing/selftests/powerpc/pmu/lib.c
@@ -190,7 +190,7 @@ int parse_proc_maps(void)
190 190
191bool require_paranoia_below(int level) 191bool require_paranoia_below(int level)
192{ 192{
193 unsigned long current; 193 long current;
194 char *end, buf[16]; 194 char *end, buf[16];
195 FILE *f; 195 FILE *f;
196 int rc; 196 int rc;
@@ -208,7 +208,7 @@ bool require_paranoia_below(int level)
208 goto out_close; 208 goto out_close;
209 } 209 }
210 210
211 current = strtoul(buf, &end, 10); 211 current = strtol(buf, &end, 10);
212 212
213 if (end == buf) { 213 if (end == buf) {
214 printf("Couldn't parse " PARANOID_PATH "?\n"); 214 printf("Couldn't parse " PARANOID_PATH "?\n");
@@ -216,7 +216,7 @@ bool require_paranoia_below(int level)
216 } 216 }
217 217
218 if (current >= level) 218 if (current >= level)
219 goto out; 219 goto out_close;
220 220
221 rc = 0; 221 rc = 0;
222out_close: 222out_close:
diff --git a/tools/testing/selftests/powerpc/reg.h b/tools/testing/selftests/powerpc/reg.h
index 65bfdeeebdee..fddf368ed82f 100644
--- a/tools/testing/selftests/powerpc/reg.h
+++ b/tools/testing/selftests/powerpc/reg.h
@@ -34,6 +34,11 @@
34 34
35#define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */ 35#define BESCR_PMEO 0x1 /* PMU Event-based exception Occurred */
36#define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */ 36#define BESCR_PME (0x1ul << 32) /* PMU Event-based exception Enable */
37#define BESCR_LME (0x1ul << 34) /* Load Monitor Enable */
38#define BESCR_LMEO (0x1ul << 2) /* Load Monitor Exception Occurred */
39
40#define SPRN_LMRR 813 /* Load Monitor Region Register */
41#define SPRN_LMSER 814 /* Load Monitor Section Enable Register */
37 42
38#define SPRN_PMC1 771 43#define SPRN_PMC1 771
39#define SPRN_PMC2 772 44#define SPRN_PMC2 772
diff --git a/tools/testing/selftests/powerpc/signal/.gitignore b/tools/testing/selftests/powerpc/signal/.gitignore
new file mode 100644
index 000000000000..1b89224a8aab
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/.gitignore
@@ -0,0 +1,2 @@
1signal
2signal_tm
diff --git a/tools/testing/selftests/powerpc/signal/Makefile b/tools/testing/selftests/powerpc/signal/Makefile
new file mode 100644
index 000000000000..f0eef27458e2
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/Makefile
@@ -0,0 +1,13 @@
1TEST_PROGS := signal signal_tm
2
3all: $(TEST_PROGS)
4
5$(TEST_PROGS): ../harness.c ../utils.c signal.S
6
7CFLAGS += -maltivec
8signal_tm: CFLAGS += -mhtm
9
10include ../../lib.mk
11
12clean:
13 rm -f $(TEST_PROGS) *.o
diff --git a/tools/testing/selftests/powerpc/signal/signal.S b/tools/testing/selftests/powerpc/signal/signal.S
new file mode 100644
index 000000000000..7043d521df0a
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal.S
@@ -0,0 +1,50 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "../basic_asm.h"
11
12/* long signal_self(pid_t pid, int sig); */
13FUNC_START(signal_self)
14 li r0,37 /* sys_kill */
15 /* r3 already has our pid in it */
16 /* r4 already has signal type in it */
17 sc
18 bc 4,3,1f
19 subfze r3,r3
201: blr
21FUNC_END(signal_self)
22
23/* long tm_signal_self(pid_t pid, int sig, int *ret); */
24FUNC_START(tm_signal_self)
25 PUSH_BASIC_STACK(8)
26 std r5,STACK_FRAME_PARAM(0)(sp) /* ret */
27 tbegin.
28 beq 1f
29 tsuspend.
30 li r0,37 /* sys_kill */
31 /* r3 already has our pid in it */
32 /* r4 already has signal type in it */
33 sc
34 ld r5,STACK_FRAME_PARAM(0)(sp) /* ret */
35 bc 4,3,2f
36 subfze r3,r3
372: std r3,0(r5)
38 tabort. 0
39 tresume. /* Be nice to some cleanup, jumps back to tbegin then to 1: */
40 /*
41 * Transaction should be proper doomed and we should never get
42 * here
43 */
44 li r3,1
45 POP_BASIC_STACK(8)
46 blr
471: li r3,0
48 POP_BASIC_STACK(8)
49 blr
50FUNC_END(tm_signal_self)
diff --git a/tools/testing/selftests/powerpc/signal/signal.c b/tools/testing/selftests/powerpc/signal/signal.c
new file mode 100644
index 000000000000..e7dedd28b3c2
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal.c
@@ -0,0 +1,111 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Sending one self a signal should always get delivered.
10 */
11
12#include <signal.h>
13#include <stdio.h>
14#include <stdlib.h>
15#include <string.h>
16#include <sys/types.h>
17#include <sys/wait.h>
18#include <unistd.h>
19
20#include <altivec.h>
21
22#include "utils.h"
23
24#define MAX_ATTEMPT 500000
25#define TIMEOUT 5
26
27extern long signal_self(pid_t pid, int sig);
28
29static sig_atomic_t signaled;
30static sig_atomic_t fail;
31
32static void signal_handler(int sig)
33{
34 if (sig == SIGUSR1)
35 signaled = 1;
36 else
37 fail = 1;
38}
39
40static int test_signal()
41{
42 int i;
43 struct sigaction act;
44 pid_t ppid = getpid();
45 pid_t pid;
46
47 act.sa_handler = signal_handler;
48 act.sa_flags = 0;
49 sigemptyset(&act.sa_mask);
50 if (sigaction(SIGUSR1, &act, NULL) < 0) {
51 perror("sigaction SIGUSR1");
52 exit(1);
53 }
54 if (sigaction(SIGALRM, &act, NULL) < 0) {
55 perror("sigaction SIGALRM");
56 exit(1);
57 }
58
59 /* Don't do this for MAX_ATTEMPT, its simply too long */
60 for(i = 0; i < 1000; i++) {
61 pid = fork();
62 if (pid == -1) {
63 perror("fork");
64 exit(1);
65 }
66 if (pid == 0) {
67 signal_self(ppid, SIGUSR1);
68 exit(1);
69 } else {
70 alarm(0); /* Disable any pending */
71 alarm(2);
72 while (!signaled && !fail)
73 asm volatile("": : :"memory");
74 if (!signaled) {
75 fprintf(stderr, "Didn't get signal from child\n");
76 FAIL_IF(1); /* For the line number */
77 }
78 /* Otherwise we'll loop too fast and fork() will eventually fail */
79 waitpid(pid, NULL, 0);
80 }
81 }
82
83 for (i = 0; i < MAX_ATTEMPT; i++) {
84 long rc;
85
86 alarm(0); /* Disable any pending */
87 signaled = 0;
88 alarm(TIMEOUT);
89 rc = signal_self(ppid, SIGUSR1);
90 if (rc) {
91 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
92 i, fail, rc);
93 FAIL_IF(1); /* For the line number */
94 }
95 while (!signaled && !fail)
96 asm volatile("": : :"memory");
97 if (!signaled) {
98 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx",
99 i, fail, rc);
100 FAIL_IF(1); /* For the line number */
101 }
102 }
103
104 return 0;
105}
106
107int main(void)
108{
109 test_harness_set_timeout(300);
110 return test_harness(test_signal, "signal");
111}
diff --git a/tools/testing/selftests/powerpc/signal/signal_tm.c b/tools/testing/selftests/powerpc/signal/signal_tm.c
new file mode 100644
index 000000000000..2e7451a37cc6
--- /dev/null
+++ b/tools/testing/selftests/powerpc/signal/signal_tm.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Sending one self a signal should always get delivered.
10 */
11
12#include <errno.h>
13#include <stdlib.h>
14#include <stdio.h>
15#include <string.h>
16#include <signal.h>
17#include <unistd.h>
18
19#include <altivec.h>
20
21#include "utils.h"
22#include "../tm/tm.h"
23
24#define MAX_ATTEMPT 500000
25#define TIMEOUT 10
26
27extern long tm_signal_self(pid_t pid, int sig, long *ret);
28
29static sig_atomic_t signaled;
30static sig_atomic_t fail;
31
32static void signal_handler(int sig)
33{
34 if (tcheck_active()) {
35 fail = 2;
36 return;
37 }
38
39 if (sig == SIGUSR1)
40 signaled = 1;
41 else
42 fail = 1;
43}
44
45static int test_signal_tm()
46{
47 int i;
48 struct sigaction act;
49
50 act.sa_handler = signal_handler;
51 act.sa_flags = 0;
52 sigemptyset(&act.sa_mask);
53 if (sigaction(SIGUSR1, &act, NULL) < 0) {
54 perror("sigaction SIGUSR1");
55 exit(1);
56 }
57 if (sigaction(SIGALRM, &act, NULL) < 0) {
58 perror("sigaction SIGALRM");
59 exit(1);
60 }
61
62 SKIP_IF(!have_htm());
63
64 for (i = 0; i < MAX_ATTEMPT; i++) {
65 /*
66 * If anything bad happens in ASM and we fail to set ret
67 * because *handwave* TM this will cause failure
68 */
69 long ret = 0xdead;
70 long rc = 0xbeef;
71
72 alarm(0); /* Disable any pending */
73 signaled = 0;
74 alarm(TIMEOUT);
75 FAIL_IF(tcheck_transactional());
76 rc = tm_signal_self(getpid(), SIGUSR1, &ret);
77 if (ret == 0xdead)
78 /*
79 * This basically means the transaction aborted before we
80 * even got to the suspend... this is crazy but it
81 * happens.
82 * Yes this also means we might never make forward
83 * progress... the alarm() will trip eventually...
84 */
85 continue;
86
87 if (rc || ret) {
88 /* Ret is actually an errno */
89 printf("TEXASR 0x%016lx, TFIAR 0x%016lx\n",
90 __builtin_get_texasr(), __builtin_get_tfiar());
91 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n",
92 i, fail, rc, ret);
93 FAIL_IF(ret);
94 }
95 while(!signaled && !fail)
96 asm volatile("": : :"memory");
97 if (!signaled) {
98 fprintf(stderr, "(%d) Fail reason: %d rc=0x%lx ret=0x%lx\n",
99 i, fail, rc, ret);
100 FAIL_IF(fail); /* For the line number */
101 }
102 }
103
104 return 0;
105}
106
107int main(void)
108{
109 return test_harness(test_signal_tm, "signal_tm");
110}
diff --git a/tools/testing/selftests/powerpc/stringloops/asm/export.h b/tools/testing/selftests/powerpc/stringloops/asm/export.h
new file mode 100644
index 000000000000..2d14a9b4248c
--- /dev/null
+++ b/tools/testing/selftests/powerpc/stringloops/asm/export.h
@@ -0,0 +1 @@
#define EXPORT_SYMBOL(x)
diff --git a/tools/testing/selftests/powerpc/tm/.gitignore b/tools/testing/selftests/powerpc/tm/.gitignore
index bb942db845bf..427621792229 100644
--- a/tools/testing/selftests/powerpc/tm/.gitignore
+++ b/tools/testing/selftests/powerpc/tm/.gitignore
@@ -6,3 +6,8 @@ tm-vmxcopy
6tm-fork 6tm-fork
7tm-tar 7tm-tar
8tm-tmspr 8tm-tmspr
9tm-exec
10tm-signal-context-chk-fpu
11tm-signal-context-chk-gpr
12tm-signal-context-chk-vmx
13tm-signal-context-chk-vsx
diff --git a/tools/testing/selftests/powerpc/tm/Makefile b/tools/testing/selftests/powerpc/tm/Makefile
index d0505dbd22d5..c6c53c82fdd6 100644
--- a/tools/testing/selftests/powerpc/tm/Makefile
+++ b/tools/testing/selftests/powerpc/tm/Makefile
@@ -1,13 +1,22 @@
1TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack tm-vmxcopy tm-fork tm-tar tm-tmspr 1SIGNAL_CONTEXT_CHK_TESTS := tm-signal-context-chk-gpr tm-signal-context-chk-fpu \
2 tm-signal-context-chk-vmx tm-signal-context-chk-vsx
3
4TEST_PROGS := tm-resched-dscr tm-syscall tm-signal-msr-resv tm-signal-stack \
5 tm-vmxcopy tm-fork tm-tar tm-tmspr $(SIGNAL_CONTEXT_CHK_TESTS)
2 6
3all: $(TEST_PROGS) 7all: $(TEST_PROGS)
4 8
5$(TEST_PROGS): ../harness.c ../utils.c 9$(TEST_PROGS): ../harness.c ../utils.c
6 10
11CFLAGS += -mhtm
12
7tm-syscall: tm-syscall-asm.S 13tm-syscall: tm-syscall-asm.S
8tm-syscall: CFLAGS += -mhtm -I../../../../../usr/include 14tm-syscall: CFLAGS += -I../../../../../usr/include
9tm-tmspr: CFLAGS += -pthread 15tm-tmspr: CFLAGS += -pthread
10 16
17$(SIGNAL_CONTEXT_CHK_TESTS): tm-signal.S
18$(SIGNAL_CONTEXT_CHK_TESTS): CFLAGS += -mhtm -m64 -mvsx
19
11include ../../lib.mk 20include ../../lib.mk
12 21
13clean: 22clean:
diff --git a/tools/testing/selftests/powerpc/tm/tm-exec.c b/tools/testing/selftests/powerpc/tm/tm-exec.c
new file mode 100644
index 000000000000..3d27fa0ece04
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-exec.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 * Syscalls can be performed provided the transactions are suspended.
10 * The exec() class of syscall is unique as a new process is loaded.
11 *
12 * It makes little sense for after an exec() call for the previously
13 * suspended transaction to still exist.
14 */
15
16#define _GNU_SOURCE
17#include <errno.h>
18#include <inttypes.h>
19#include <libgen.h>
20#include <pthread.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <unistd.h>
25
26#include "utils.h"
27#include "tm.h"
28
29static char *path;
30
31static int test_exec(void)
32{
33 SKIP_IF(!have_htm());
34
35 asm __volatile__(
36 "tbegin.;"
37 "blt 1f; "
38 "tsuspend.;"
39 "1: ;"
40 : : : "memory");
41
42 execl(path, "tm-exec", "--child", NULL);
43
44 /* Shouldn't get here */
45 perror("execl() failed");
46 return 1;
47}
48
49static int after_exec(void)
50{
51 asm __volatile__(
52 "tbegin.;"
53 "blt 1f;"
54 "tsuspend.;"
55 "1: ;"
56 : : : "memory");
57
58 FAIL_IF(failure_is_nesting());
59 return 0;
60}
61
62int main(int argc, char *argv[])
63{
64 path = argv[0];
65
66 if (argc > 1 && strcmp(argv[1], "--child") == 0)
67 return after_exec();
68
69 return test_harness(test_exec, "tm_exec");
70}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
new file mode 100644
index 000000000000..c760debbd5ad
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-fpu.c
@@ -0,0 +1,92 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <signal.h>
27#include <unistd.h>
28
29#include <altivec.h>
30
31#include "utils.h"
32#include "tm.h"
33
34#define MAX_ATTEMPT 500000
35
36#define NV_FPU_REGS 18
37
38long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
39
40/* Be sure there are 2x as many as there are NV FPU regs (2x18) */
41static double fps[] = {
42 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
43 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
44};
45
46static sig_atomic_t fail;
47
48static void signal_usr1(int signum, siginfo_t *info, void *uc)
49{
50 int i;
51 ucontext_t *ucp = uc;
52 ucontext_t *tm_ucp = ucp->uc_link;
53
54 for (i = 0; i < NV_FPU_REGS && !fail; i++) {
55 fail = (ucp->uc_mcontext.fp_regs[i + 14] != fps[i]);
56 fail |= (tm_ucp->uc_mcontext.fp_regs[i + 14] != fps[i + NV_FPU_REGS]);
57 if (fail)
58 printf("Failed on %d FP %g or %g\n", i, ucp->uc_mcontext.fp_regs[i + 14], tm_ucp->uc_mcontext.fp_regs[i + 14]);
59 }
60}
61
62static int tm_signal_context_chk_fpu()
63{
64 struct sigaction act;
65 int i;
66 long rc;
67 pid_t pid = getpid();
68
69 SKIP_IF(!have_htm());
70
71 act.sa_sigaction = signal_usr1;
72 sigemptyset(&act.sa_mask);
73 act.sa_flags = SA_SIGINFO;
74 if (sigaction(SIGUSR1, &act, NULL) < 0) {
75 perror("sigaction sigusr1");
76 exit(1);
77 }
78
79 i = 0;
80 while (i < MAX_ATTEMPT && !fail) {
81 rc = tm_signal_self_context_load(pid, NULL, fps, NULL, NULL);
82 FAIL_IF(rc != pid);
83 i++;
84 }
85
86 return fail;
87}
88
89int main(void)
90{
91 return test_harness(tm_signal_context_chk_fpu, "tm_signal_context_chk_fpu");
92}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
new file mode 100644
index 000000000000..df91330a08ef
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-gpr.c
@@ -0,0 +1,90 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <signal.h>
27#include <unistd.h>
28
29#include <altivec.h>
30
31#include "utils.h"
32#include "tm.h"
33
34#define MAX_ATTEMPT 500000
35
36#define NV_GPR_REGS 18
37
38long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
39
40static sig_atomic_t fail;
41
42static long gps[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
43 -1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18};
44
45static void signal_usr1(int signum, siginfo_t *info, void *uc)
46{
47 int i;
48 ucontext_t *ucp = uc;
49 ucontext_t *tm_ucp = ucp->uc_link;
50
51 for (i = 0; i < NV_GPR_REGS && !fail; i++) {
52 fail = (ucp->uc_mcontext.gp_regs[i + 14] != gps[i]);
53 fail |= (tm_ucp->uc_mcontext.gp_regs[i + 14] != gps[i + NV_GPR_REGS]);
54 if (fail)
55 printf("Failed on %d GPR %lu or %lu\n", i,
56 ucp->uc_mcontext.gp_regs[i + 14], tm_ucp->uc_mcontext.gp_regs[i + 14]);
57 }
58}
59
60static int tm_signal_context_chk_gpr()
61{
62 struct sigaction act;
63 int i;
64 long rc;
65 pid_t pid = getpid();
66
67 SKIP_IF(!have_htm());
68
69 act.sa_sigaction = signal_usr1;
70 sigemptyset(&act.sa_mask);
71 act.sa_flags = SA_SIGINFO;
72 if (sigaction(SIGUSR1, &act, NULL) < 0) {
73 perror("sigaction sigusr1");
74 exit(1);
75 }
76
77 i = 0;
78 while (i < MAX_ATTEMPT && !fail) {
79 rc = tm_signal_self_context_load(pid, gps, NULL, NULL, NULL);
80 FAIL_IF(rc != pid);
81 i++;
82 }
83
84 return fail;
85}
86
87int main(void)
88{
89 return test_harness(tm_signal_context_chk_gpr, "tm_signal_context_chk_gpr");
90}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
new file mode 100644
index 000000000000..f0ee55fd5185
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vmx.c
@@ -0,0 +1,110 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29
30#include <altivec.h>
31
32#include "utils.h"
33#include "tm.h"
34
35#define MAX_ATTEMPT 500000
36
37#define NV_VMX_REGS 12
38
39long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
40
41static sig_atomic_t fail;
42
43vector int vms[] = {
44 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
45 {13,14,15,16},{17,18,19,20},{21,22,23,24},
46 {25,26,27,28},{29,30,31,32},{33,34,35,36},
47 {37,38,39,40},{41,42,43,44},{45,46,47,48},
48 {-1, -2, -3, -4}, {-5, -6, -7, -8}, {-9, -10,-11,-12},
49 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
50 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
51 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
52};
53
54static void signal_usr1(int signum, siginfo_t *info, void *uc)
55{
56 int i;
57 ucontext_t *ucp = uc;
58 ucontext_t *tm_ucp = ucp->uc_link;
59
60 for (i = 0; i < NV_VMX_REGS && !fail; i++) {
61 fail = memcmp(ucp->uc_mcontext.v_regs->vrregs[i + 20],
62 &vms[i], sizeof(vector int));
63 fail |= memcmp(tm_ucp->uc_mcontext.v_regs->vrregs[i + 20],
64 &vms[i + NV_VMX_REGS], sizeof (vector int));
65
66 if (fail) {
67 int j;
68
69 fprintf(stderr, "Failed on %d vmx 0x", i);
70 for (j = 0; j < 4; j++)
71 fprintf(stderr, "%04x", ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
72 fprintf(stderr, " vs 0x");
73 for (j = 0 ; j < 4; j++)
74 fprintf(stderr, "%04x", tm_ucp->uc_mcontext.v_regs->vrregs[i + 20][j]);
75 fprintf(stderr, "\n");
76 }
77 }
78}
79
80static int tm_signal_context_chk()
81{
82 struct sigaction act;
83 int i;
84 long rc;
85 pid_t pid = getpid();
86
87 SKIP_IF(!have_htm());
88
89 act.sa_sigaction = signal_usr1;
90 sigemptyset(&act.sa_mask);
91 act.sa_flags = SA_SIGINFO;
92 if (sigaction(SIGUSR1, &act, NULL) < 0) {
93 perror("sigaction sigusr1");
94 exit(1);
95 }
96
97 i = 0;
98 while (i < MAX_ATTEMPT && !fail) {
99 rc = tm_signal_self_context_load(pid, NULL, NULL, vms, NULL);
100 FAIL_IF(rc != pid);
101 i++;
102 }
103
104 return fail;
105}
106
107int main(void)
108{
109 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vmx");
110}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
new file mode 100644
index 000000000000..b99c3d835957
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal-context-chk-vsx.c
@@ -0,0 +1,125 @@
1/*
2 * Copyright 2016, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 *
9 *
10 * Test the kernel's signal frame code.
11 *
12 * The kernel sets up two sets of ucontexts if the signal was to be
13 * delivered while the thread was in a transaction.
14 * Expected behaviour is that the checkpointed state is in the user
15 * context passed to the signal handler. The speculated state can be
16 * accessed with the uc_link pointer.
17 *
18 * The rationale for this is that if TM unaware code (which linked
19 * against TM libs) installs a signal handler it will not know of the
20 * speculative nature of the 'live' registers and may infer the wrong
21 * thing.
22 */
23
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29
30#include <altivec.h>
31
32#include "utils.h"
33#include "tm.h"
34
35#define MAX_ATTEMPT 500000
36
37#define NV_VSX_REGS 12
38
39long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
40
41static sig_atomic_t fail;
42
43vector int vss[] = {
44 {1, 2, 3, 4 },{5, 6, 7, 8 },{9, 10,11,12},
45 {13,14,15,16},{17,18,19,20},{21,22,23,24},
46 {25,26,27,28},{29,30,31,32},{33,34,35,36},
47 {37,38,39,40},{41,42,43,44},{45,46,47,48},
48 {-1, -2, -3, -4 },{-5, -6, -7, -8 },{-9, -10,-11,-12},
49 {-13,-14,-15,-16},{-17,-18,-19,-20},{-21,-22,-23,-24},
50 {-25,-26,-27,-28},{-29,-30,-31,-32},{-33,-34,-35,-36},
51 {-37,-38,-39,-40},{-41,-42,-43,-44},{-45,-46,-47,-48}
52};
53
54static void signal_usr1(int signum, siginfo_t *info, void *uc)
55{
56 int i;
57 uint8_t vsc[sizeof(vector int)];
58 uint8_t vst[sizeof(vector int)];
59 ucontext_t *ucp = uc;
60 ucontext_t *tm_ucp = ucp->uc_link;
61
62 /*
63 * The other half of the VSX regs will be after v_regs.
64 *
65 * In short, vmx_reserve array holds everything. v_regs is a 16
66 * byte aligned pointer at the start of vmx_reserve (vmx_reserve
67 * may or may not be 16 aligned) where the v_regs structure exists.
68 * (half of) The VSX regsters are directly after v_regs so the
69 * easiest way to find them below.
70 */
71 long *vsx_ptr = (long *)(ucp->uc_mcontext.v_regs + 1);
72 long *tm_vsx_ptr = (long *)(tm_ucp->uc_mcontext.v_regs + 1);
73 for (i = 0; i < NV_VSX_REGS && !fail; i++) {
74 memcpy(vsc, &ucp->uc_mcontext.fp_regs[i + 20], 8);
75 memcpy(vsc + 8, &vsx_ptr[20 + i], 8);
76 fail = memcmp(vsc, &vss[i], sizeof(vector int));
77 memcpy(vst, &tm_ucp->uc_mcontext.fp_regs[i + 20], 8);
78 memcpy(vst + 8, &tm_vsx_ptr[20 + i], 8);
79 fail |= memcmp(vst, &vss[i + NV_VSX_REGS], sizeof(vector int));
80
81 if (fail) {
82 int j;
83
84 fprintf(stderr, "Failed on %d vsx 0x", i);
85 for (j = 0; j < 16; j++)
86 fprintf(stderr, "%02x", vsc[j]);
87 fprintf(stderr, " vs 0x");
88 for (j = 0; j < 16; j++)
89 fprintf(stderr, "%02x", vst[j]);
90 fprintf(stderr, "\n");
91 }
92 }
93}
94
95static int tm_signal_context_chk()
96{
97 struct sigaction act;
98 int i;
99 long rc;
100 pid_t pid = getpid();
101
102 SKIP_IF(!have_htm());
103
104 act.sa_sigaction = signal_usr1;
105 sigemptyset(&act.sa_mask);
106 act.sa_flags = SA_SIGINFO;
107 if (sigaction(SIGUSR1, &act, NULL) < 0) {
108 perror("sigaction sigusr1");
109 exit(1);
110 }
111
112 i = 0;
113 while (i < MAX_ATTEMPT && !fail) {
114 rc = tm_signal_self_context_load(pid, NULL, NULL, NULL, vss);
115 FAIL_IF(rc != pid);
116 i++;
117 }
118
119 return fail;
120}
121
122int main(void)
123{
124 return test_harness(tm_signal_context_chk, "tm_signal_context_chk_vsx");
125}
diff --git a/tools/testing/selftests/powerpc/tm/tm-signal.S b/tools/testing/selftests/powerpc/tm/tm-signal.S
new file mode 100644
index 000000000000..4e13e8b3a96f
--- /dev/null
+++ b/tools/testing/selftests/powerpc/tm/tm-signal.S
@@ -0,0 +1,114 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "../basic_asm.h"
11#include "../gpr_asm.h"
12#include "../fpu_asm.h"
13#include "../vmx_asm.h"
14#include "../vsx_asm.h"
15
16/*
17 * Large caveat here being that the caller cannot expect the
18 * signal to always be sent! The hardware can (AND WILL!) abort
19 * the transaction between the tbegin and the tsuspend (however
20 * unlikely it seems or infrequently it actually happens).
21 * You have been warned.
22 */
23/* long tm_signal_self(pid_t pid, long *gprs, double *fps, vector *vms, vector *vss); */
24FUNC_START(tm_signal_self_context_load)
25 PUSH_BASIC_STACK(512)
26 /*
27 * Don't strictly need to save and restore as it depends on if
28 * we're going to use them, however this reduces messy logic
29 */
30 PUSH_VMX(STACK_FRAME_LOCAL(5,0),r8)
31 PUSH_FPU(512)
32 PUSH_NVREGS_BELOW_FPU(512)
33 std r3, STACK_FRAME_PARAM(0)(sp) /* pid */
34 std r4, STACK_FRAME_PARAM(1)(sp) /* gps */
35 std r5, STACK_FRAME_PARAM(2)(sp) /* fps */
36 std r6, STACK_FRAME_PARAM(3)(sp) /* vms */
37 std r7, STACK_FRAME_PARAM(4)(sp) /* vss */
38
39 ld r3, STACK_FRAME_PARAM(1)(sp)
40 cmpdi r3, 0
41 beq skip_gpr_lc
42 bl load_gpr
43skip_gpr_lc:
44 ld r3, STACK_FRAME_PARAM(2)(sp)
45 cmpdi r3, 0
46 beq skip_fpu_lc
47 bl load_fpu
48skip_fpu_lc:
49 ld r3, STACK_FRAME_PARAM(3)(sp)
50 cmpdi r3, 0
51 beq skip_vmx_lc
52 bl load_vmx
53skip_vmx_lc:
54 ld r3, STACK_FRAME_PARAM(4)(sp)
55 cmpdi r3, 0
56 beq skip_vsx_lc
57 bl load_vsx
58skip_vsx_lc:
59 /*
60 * Set r3 (return value) before tbegin. Use the pid as a known
61 * 'all good' return value, zero is used to indicate a non-doomed
62 * transaction.
63 */
64 ld r3, STACK_FRAME_PARAM(0)(sp)
65 tbegin.
66 beq 1f
67 tsuspend. /* Can't enter a syscall transactionally */
68 ld r3, STACK_FRAME_PARAM(1)(sp)
69 cmpdi r3, 0
70 beq skip_gpr_lt
71 /* Get the second half of the array */
72 addi r3, r3, 8 * 18
73 bl load_gpr
74skip_gpr_lt:
75 ld r3, STACK_FRAME_PARAM(2)(sp)
76 cmpdi r3, 0
77 beq skip_fpu_lt
78 /* Get the second half of the array */
79 addi r3, r3, 8 * 18
80 bl load_fpu
81skip_fpu_lt:
82 ld r3, STACK_FRAME_PARAM(3)(sp)
83 cmpdi r3, 0
84 beq skip_vmx_lt
85 /* Get the second half of the array */
86 addi r3, r3, 16 * 12
87 bl load_vmx
88skip_vmx_lt:
89 ld r3, STACK_FRAME_PARAM(4)(sp)
90 cmpdi r3, 0
91 beq skip_vsx_lt
92 /* Get the second half of the array */
93 addi r3, r3, 16 * 12
94 bl load_vsx
95skip_vsx_lt:
96 li r0, 37 /* sys_kill */
97 ld r3, STACK_FRAME_PARAM(0)(sp) /* pid */
98 li r4, 10 /* SIGUSR1 */
99 sc /* Taking the signal will doom the transaction */
100 tabort. 0
101 tresume. /* Be super sure we abort */
102 /*
103 * This will cause us to resume doomed transaction and cause
104 * hardware to cleanup, we'll end up at 1: anything between
105 * tresume. and 1: shouldn't ever run.
106 */
107 li r3, 0
108 1:
109 POP_VMX(STACK_FRAME_LOCAL(5,0),r4)
110 POP_FPU(512)
111 POP_NVREGS_BELOW_FPU(512)
112 POP_BASIC_STACK(512)
113 blr
114FUNC_END(tm_signal_self_context_load)
diff --git a/tools/testing/selftests/powerpc/tm/tm-syscall.c b/tools/testing/selftests/powerpc/tm/tm-syscall.c
index 60560cb20e38..454b965a2db3 100644
--- a/tools/testing/selftests/powerpc/tm/tm-syscall.c
+++ b/tools/testing/selftests/powerpc/tm/tm-syscall.c
@@ -27,21 +27,6 @@ unsigned retries = 0;
27#define TEST_DURATION 10 /* seconds */ 27#define TEST_DURATION 10 /* seconds */
28#define TM_RETRIES 100 28#define TM_RETRIES 100
29 29
30long failure_code(void)
31{
32 return __builtin_get_texasru() >> 24;
33}
34
35bool failure_is_persistent(void)
36{
37 return (failure_code() & TM_CAUSE_PERSISTENT) == TM_CAUSE_PERSISTENT;
38}
39
40bool failure_is_syscall(void)
41{
42 return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL;
43}
44
45pid_t getppid_tm(bool suspend) 30pid_t getppid_tm(bool suspend)
46{ 31{
47 int i; 32 int i;
diff --git a/tools/testing/selftests/powerpc/tm/tm.h b/tools/testing/selftests/powerpc/tm/tm.h
index 24144b25772c..2c8da74304e7 100644
--- a/tools/testing/selftests/powerpc/tm/tm.h
+++ b/tools/testing/selftests/powerpc/tm/tm.h
@@ -6,8 +6,9 @@
6#ifndef _SELFTESTS_POWERPC_TM_TM_H 6#ifndef _SELFTESTS_POWERPC_TM_TM_H
7#define _SELFTESTS_POWERPC_TM_TM_H 7#define _SELFTESTS_POWERPC_TM_TM_H
8 8
9#include <stdbool.h> 9#include <asm/tm.h>
10#include <asm/cputable.h> 10#include <asm/cputable.h>
11#include <stdbool.h>
11 12
12#include "../utils.h" 13#include "../utils.h"
13 14
@@ -31,4 +32,51 @@ static inline bool have_htm_nosc(void)
31#endif 32#endif
32} 33}
33 34
35static inline long failure_code(void)
36{
37 return __builtin_get_texasru() >> 24;
38}
39
40static inline bool failure_is_persistent(void)
41{
42 return (failure_code() & TM_CAUSE_PERSISTENT) == TM_CAUSE_PERSISTENT;
43}
44
45static inline bool failure_is_syscall(void)
46{
47 return (failure_code() & TM_CAUSE_SYSCALL) == TM_CAUSE_SYSCALL;
48}
49
50static inline bool failure_is_nesting(void)
51{
52 return (__builtin_get_texasru() & 0x400000);
53}
54
55static inline int tcheck(void)
56{
57 long cr;
58 asm volatile ("tcheck 0" : "=r"(cr) : : "cr0");
59 return (cr >> 28) & 4;
60}
61
62static inline bool tcheck_doomed(void)
63{
64 return tcheck() & 8;
65}
66
67static inline bool tcheck_active(void)
68{
69 return tcheck() & 4;
70}
71
72static inline bool tcheck_suspended(void)
73{
74 return tcheck() & 2;
75}
76
77static inline bool tcheck_transactional(void)
78{
79 return tcheck() & 6;
80}
81
34#endif /* _SELFTESTS_POWERPC_TM_TM_H */ 82#endif /* _SELFTESTS_POWERPC_TM_TM_H */
diff --git a/tools/testing/selftests/powerpc/utils.h b/tools/testing/selftests/powerpc/utils.h
index a985cfaa535e..53405e8a52ab 100644
--- a/tools/testing/selftests/powerpc/utils.h
+++ b/tools/testing/selftests/powerpc/utils.h
@@ -22,15 +22,27 @@ typedef uint32_t u32;
22typedef uint16_t u16; 22typedef uint16_t u16;
23typedef uint8_t u8; 23typedef uint8_t u8;
24 24
25 25void test_harness_set_timeout(uint64_t time);
26int test_harness(int (test_function)(void), char *name); 26int test_harness(int (test_function)(void), char *name);
27extern void *get_auxv_entry(int type); 27extern void *get_auxv_entry(int type);
28int pick_online_cpu(void); 28int pick_online_cpu(void);
29 29
30static inline bool have_hwcap(unsigned long ftr)
31{
32 return ((unsigned long)get_auxv_entry(AT_HWCAP) & ftr) == ftr;
33}
34
35#ifdef AT_HWCAP2
30static inline bool have_hwcap2(unsigned long ftr2) 36static inline bool have_hwcap2(unsigned long ftr2)
31{ 37{
32 return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2; 38 return ((unsigned long)get_auxv_entry(AT_HWCAP2) & ftr2) == ftr2;
33} 39}
40#else
41static inline bool have_hwcap2(unsigned long ftr2)
42{
43 return false;
44}
45#endif
34 46
35/* Yes, this is evil */ 47/* Yes, this is evil */
36#define FAIL_IF(x) \ 48#define FAIL_IF(x) \
diff --git a/tools/testing/selftests/powerpc/vmx_asm.h b/tools/testing/selftests/powerpc/vmx_asm.h
new file mode 100644
index 000000000000..2eaaeca9cf1d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vmx_asm.h
@@ -0,0 +1,96 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "basic_asm.h"
11
12/* POS MUST BE 16 ALIGNED! */
13#define PUSH_VMX(pos,reg) \
14 li reg,pos; \
15 stvx v20,reg,%r1; \
16 addi reg,reg,16; \
17 stvx v21,reg,%r1; \
18 addi reg,reg,16; \
19 stvx v22,reg,%r1; \
20 addi reg,reg,16; \
21 stvx v23,reg,%r1; \
22 addi reg,reg,16; \
23 stvx v24,reg,%r1; \
24 addi reg,reg,16; \
25 stvx v25,reg,%r1; \
26 addi reg,reg,16; \
27 stvx v26,reg,%r1; \
28 addi reg,reg,16; \
29 stvx v27,reg,%r1; \
30 addi reg,reg,16; \
31 stvx v28,reg,%r1; \
32 addi reg,reg,16; \
33 stvx v29,reg,%r1; \
34 addi reg,reg,16; \
35 stvx v30,reg,%r1; \
36 addi reg,reg,16; \
37 stvx v31,reg,%r1;
38
39/* POS MUST BE 16 ALIGNED! */
40#define POP_VMX(pos,reg) \
41 li reg,pos; \
42 lvx v20,reg,%r1; \
43 addi reg,reg,16; \
44 lvx v21,reg,%r1; \
45 addi reg,reg,16; \
46 lvx v22,reg,%r1; \
47 addi reg,reg,16; \
48 lvx v23,reg,%r1; \
49 addi reg,reg,16; \
50 lvx v24,reg,%r1; \
51 addi reg,reg,16; \
52 lvx v25,reg,%r1; \
53 addi reg,reg,16; \
54 lvx v26,reg,%r1; \
55 addi reg,reg,16; \
56 lvx v27,reg,%r1; \
57 addi reg,reg,16; \
58 lvx v28,reg,%r1; \
59 addi reg,reg,16; \
60 lvx v29,reg,%r1; \
61 addi reg,reg,16; \
62 lvx v30,reg,%r1; \
63 addi reg,reg,16; \
64 lvx v31,reg,%r1;
65
66/*
67 * Careful this will 'clobber' vmx (by design)
68 * Don't call this from C
69 */
70FUNC_START(load_vmx)
71 li r5,0
72 lvx v20,r5,r3
73 addi r5,r5,16
74 lvx v21,r5,r3
75 addi r5,r5,16
76 lvx v22,r5,r3
77 addi r5,r5,16
78 lvx v23,r5,r3
79 addi r5,r5,16
80 lvx v24,r5,r3
81 addi r5,r5,16
82 lvx v25,r5,r3
83 addi r5,r5,16
84 lvx v26,r5,r3
85 addi r5,r5,16
86 lvx v27,r5,r3
87 addi r5,r5,16
88 lvx v28,r5,r3
89 addi r5,r5,16
90 lvx v29,r5,r3
91 addi r5,r5,16
92 lvx v30,r5,r3
93 addi r5,r5,16
94 lvx v31,r5,r3
95 blr
96FUNC_END(load_vmx)
diff --git a/tools/testing/selftests/powerpc/vsx_asm.h b/tools/testing/selftests/powerpc/vsx_asm.h
new file mode 100644
index 000000000000..d828bfb6ef2d
--- /dev/null
+++ b/tools/testing/selftests/powerpc/vsx_asm.h
@@ -0,0 +1,71 @@
1/*
2 * Copyright 2015, Cyril Bur, IBM Corp.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include "basic_asm.h"
11
12/*
13 * Careful this will 'clobber' vsx (by design), VSX are always
14 * volatile though so unlike vmx this isn't so much of an issue
15 * Still should avoid calling from C
16 */
17FUNC_START(load_vsx)
18 li r5,0
19 lxvx vs20,r5,r3
20 addi r5,r5,16
21 lxvx vs21,r5,r3
22 addi r5,r5,16
23 lxvx vs22,r5,r3
24 addi r5,r5,16
25 lxvx vs23,r5,r3
26 addi r5,r5,16
27 lxvx vs24,r5,r3
28 addi r5,r5,16
29 lxvx vs25,r5,r3
30 addi r5,r5,16
31 lxvx vs26,r5,r3
32 addi r5,r5,16
33 lxvx vs27,r5,r3
34 addi r5,r5,16
35 lxvx vs28,r5,r3
36 addi r5,r5,16
37 lxvx vs29,r5,r3
38 addi r5,r5,16
39 lxvx vs30,r5,r3
40 addi r5,r5,16
41 lxvx vs31,r5,r3
42 blr
43FUNC_END(load_vsx)
44
45FUNC_START(store_vsx)
46 li r5,0
47 stxvx vs20,r5,r3
48 addi r5,r5,16
49 stxvx vs21,r5,r3
50 addi r5,r5,16
51 stxvx vs22,r5,r3
52 addi r5,r5,16
53 stxvx vs23,r5,r3
54 addi r5,r5,16
55 stxvx vs24,r5,r3
56 addi r5,r5,16
57 stxvx vs25,r5,r3
58 addi r5,r5,16
59 stxvx vs26,r5,r3
60 addi r5,r5,16
61 stxvx vs27,r5,r3
62 addi r5,r5,16
63 stxvx vs28,r5,r3
64 addi r5,r5,16
65 stxvx vs29,r5,r3
66 addi r5,r5,16
67 stxvx vs30,r5,r3
68 addi r5,r5,16
69 stxvx vs31,r5,r3
70 blr
71FUNC_END(store_vsx)
diff --git a/tools/testing/selftests/prctl/.gitignore b/tools/testing/selftests/prctl/.gitignore
new file mode 100644
index 000000000000..0b5c27447bf6
--- /dev/null
+++ b/tools/testing/selftests/prctl/.gitignore
@@ -0,0 +1,3 @@
1disable-tsc-ctxt-sw-stress-test
2disable-tsc-on-off-stress-test
3disable-tsc-test
diff --git a/tools/testing/selftests/prctl/Makefile b/tools/testing/selftests/prctl/Makefile
new file mode 100644
index 000000000000..35aa1c8f2df2
--- /dev/null
+++ b/tools/testing/selftests/prctl/Makefile
@@ -0,0 +1,15 @@
1ifndef CROSS_COMPILE
2uname_M := $(shell uname -m 2>/dev/null || echo not)
3ARCH ?= $(shell echo $(uname_M) | sed -e s/i.86/x86/ -e s/x86_64/x86/)
4
5ifeq ($(ARCH),x86)
6TEST_PROGS := disable-tsc-ctxt-sw-stress-test disable-tsc-on-off-stress-test \
7 disable-tsc-test
8all: $(TEST_PROGS)
9
10include ../lib.mk
11
12clean:
13 rm -fr $(TEST_PROGS)
14endif
15endif
diff --git a/tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c b/tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c
new file mode 100644
index 000000000000..f7499d1c0415
--- /dev/null
+++ b/tools/testing/selftests/prctl/disable-tsc-ctxt-sw-stress-test.c
@@ -0,0 +1,97 @@
1/*
2 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
3 *
4 * Tests if the control register is updated correctly
5 * at context switches
6 *
7 * Warning: this test will cause a very high load for a few seconds
8 *
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <signal.h>
15#include <inttypes.h>
16#include <wait.h>
17
18
19#include <sys/prctl.h>
20#include <linux/prctl.h>
21
22/* Get/set the process' ability to use the timestamp counter instruction */
23#ifndef PR_GET_TSC
24#define PR_GET_TSC 25
25#define PR_SET_TSC 26
26# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
27# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
28#endif
29
30static uint64_t rdtsc(void)
31{
32uint32_t lo, hi;
33/* We cannot use "=A", since this would use %rax on x86_64 */
34__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
35return (uint64_t)hi << 32 | lo;
36}
37
38static void sigsegv_expect(int sig)
39{
40 /* */
41}
42
43static void segvtask(void)
44{
45 if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
46 {
47 perror("prctl");
48 exit(0);
49 }
50 signal(SIGSEGV, sigsegv_expect);
51 alarm(10);
52 rdtsc();
53 fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
54 exit(0);
55}
56
57
58static void sigsegv_fail(int sig)
59{
60 fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
61 exit(0);
62}
63
64static void rdtsctask(void)
65{
66 if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
67 {
68 perror("prctl");
69 exit(0);
70 }
71 signal(SIGSEGV, sigsegv_fail);
72 alarm(10);
73 for(;;) rdtsc();
74}
75
76
77int main(void)
78{
79 int n_tasks = 100, i;
80
81 fprintf(stderr, "[No further output means we're allright]\n");
82
83 for (i=0; i<n_tasks; i++)
84 if (fork() == 0)
85 {
86 if (i & 1)
87 segvtask();
88 else
89 rdtsctask();
90 }
91
92 for (i=0; i<n_tasks; i++)
93 wait(NULL);
94
95 exit(0);
96}
97
diff --git a/tools/testing/selftests/prctl/disable-tsc-on-off-stress-test.c b/tools/testing/selftests/prctl/disable-tsc-on-off-stress-test.c
new file mode 100644
index 000000000000..a06f027e9d16
--- /dev/null
+++ b/tools/testing/selftests/prctl/disable-tsc-on-off-stress-test.c
@@ -0,0 +1,96 @@
1/*
2 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
3 *
4 * Tests if the control register is updated correctly
5 * when set with prctl()
6 *
7 * Warning: this test will cause a very high load for a few seconds
8 *
9 */
10
11#include <stdio.h>
12#include <stdlib.h>
13#include <unistd.h>
14#include <signal.h>
15#include <inttypes.h>
16#include <wait.h>
17
18
19#include <sys/prctl.h>
20#include <linux/prctl.h>
21
22/* Get/set the process' ability to use the timestamp counter instruction */
23#ifndef PR_GET_TSC
24#define PR_GET_TSC 25
25#define PR_SET_TSC 26
26# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
27# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
28#endif
29
30/* snippet from wikipedia :-) */
31
32static uint64_t rdtsc(void)
33{
34uint32_t lo, hi;
35/* We cannot use "=A", since this would use %rax on x86_64 */
36__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
37return (uint64_t)hi << 32 | lo;
38}
39
40int should_segv = 0;
41
42static void sigsegv_cb(int sig)
43{
44 if (!should_segv)
45 {
46 fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n");
47 exit(0);
48 }
49 if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0)
50 {
51 perror("prctl");
52 exit(0);
53 }
54 should_segv = 0;
55
56 rdtsc();
57}
58
59static void task(void)
60{
61 signal(SIGSEGV, sigsegv_cb);
62 alarm(10);
63 for(;;)
64 {
65 rdtsc();
66 if (should_segv)
67 {
68 fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n");
69 exit(0);
70 }
71 if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0)
72 {
73 perror("prctl");
74 exit(0);
75 }
76 should_segv = 1;
77 }
78}
79
80
81int main(void)
82{
83 int n_tasks = 100, i;
84
85 fprintf(stderr, "[No further output means we're allright]\n");
86
87 for (i=0; i<n_tasks; i++)
88 if (fork() == 0)
89 task();
90
91 for (i=0; i<n_tasks; i++)
92 wait(NULL);
93
94 exit(0);
95}
96
diff --git a/tools/testing/selftests/prctl/disable-tsc-test.c b/tools/testing/selftests/prctl/disable-tsc-test.c
new file mode 100644
index 000000000000..8d494f7bebdb
--- /dev/null
+++ b/tools/testing/selftests/prctl/disable-tsc-test.c
@@ -0,0 +1,95 @@
1/*
2 * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...)
3 *
4 * Basic test to test behaviour of PR_GET_TSC and PR_SET_TSC
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <unistd.h>
10#include <signal.h>
11#include <inttypes.h>
12
13
14#include <sys/prctl.h>
15#include <linux/prctl.h>
16
17/* Get/set the process' ability to use the timestamp counter instruction */
18#ifndef PR_GET_TSC
19#define PR_GET_TSC 25
20#define PR_SET_TSC 26
21# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */
22# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */
23#endif
24
25const char *tsc_names[] =
26{
27 [0] = "[not set]",
28 [PR_TSC_ENABLE] = "PR_TSC_ENABLE",
29 [PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV",
30};
31
32static uint64_t rdtsc(void)
33{
34uint32_t lo, hi;
35/* We cannot use "=A", since this would use %rax on x86_64 */
36__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
37return (uint64_t)hi << 32 | lo;
38}
39
40static void sigsegv_cb(int sig)
41{
42 int tsc_val = 0;
43
44 printf("[ SIG_SEGV ]\n");
45 printf("prctl(PR_GET_TSC, &tsc_val); ");
46 fflush(stdout);
47
48 if ( prctl(PR_GET_TSC, &tsc_val) == -1)
49 perror("prctl");
50
51 printf("tsc_val == %s\n", tsc_names[tsc_val]);
52 printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
53 fflush(stdout);
54 if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
55 perror("prctl");
56
57 printf("rdtsc() == ");
58}
59
60int main(void)
61{
62 int tsc_val = 0;
63
64 signal(SIGSEGV, sigsegv_cb);
65
66 printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
67 printf("prctl(PR_GET_TSC, &tsc_val); ");
68 fflush(stdout);
69
70 if ( prctl(PR_GET_TSC, &tsc_val) == -1)
71 perror("prctl");
72
73 printf("tsc_val == %s\n", tsc_names[tsc_val]);
74 printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
75 printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n");
76 fflush(stdout);
77
78 if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1)
79 perror("prctl");
80
81 printf("rdtsc() == %llu\n", (unsigned long long)rdtsc());
82 printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n");
83 fflush(stdout);
84
85 if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1)
86 perror("prctl");
87
88 printf("rdtsc() == ");
89 fflush(stdout);
90 printf("%llu\n", (unsigned long long)rdtsc());
91 fflush(stdout);
92
93 exit(EXIT_SUCCESS);
94}
95
diff --git a/tools/testing/selftests/ptp/.gitignore b/tools/testing/selftests/ptp/.gitignore
new file mode 100644
index 000000000000..f562e49d6917
--- /dev/null
+++ b/tools/testing/selftests/ptp/.gitignore
@@ -0,0 +1 @@
testptp
diff --git a/tools/testing/selftests/ptp/Makefile b/tools/testing/selftests/ptp/Makefile
new file mode 100644
index 000000000000..83dd42b2129e
--- /dev/null
+++ b/tools/testing/selftests/ptp/Makefile
@@ -0,0 +1,8 @@
1TEST_PROGS := testptp
2LDLIBS += -lrt
3all: $(TEST_PROGS)
4
5include ../lib.mk
6
7clean:
8 rm -fr $(TEST_PROGS)
diff --git a/tools/testing/selftests/ptp/testptp.c b/tools/testing/selftests/ptp/testptp.c
new file mode 100644
index 000000000000..5d2eae16f7ee
--- /dev/null
+++ b/tools/testing/selftests/ptp/testptp.c
@@ -0,0 +1,523 @@
1/*
2 * PTP 1588 clock support - User space test program
3 *
4 * Copyright (C) 2010 OMICRON electronics GmbH
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#define _GNU_SOURCE
21#define __SANE_USERSPACE_TYPES__ /* For PPC64, to get LL64 types */
22#include <errno.h>
23#include <fcntl.h>
24#include <inttypes.h>
25#include <math.h>
26#include <signal.h>
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <sys/ioctl.h>
31#include <sys/mman.h>
32#include <sys/stat.h>
33#include <sys/time.h>
34#include <sys/timex.h>
35#include <sys/types.h>
36#include <time.h>
37#include <unistd.h>
38
39#include <linux/ptp_clock.h>
40
41#define DEVICE "/dev/ptp0"
42
43#ifndef ADJ_SETOFFSET
44#define ADJ_SETOFFSET 0x0100
45#endif
46
47#ifndef CLOCK_INVALID
48#define CLOCK_INVALID -1
49#endif
50
51/* clock_adjtime is not available in GLIBC < 2.14 */
52#if !__GLIBC_PREREQ(2, 14)
53#include <sys/syscall.h>
54static int clock_adjtime(clockid_t id, struct timex *tx)
55{
56 return syscall(__NR_clock_adjtime, id, tx);
57}
58#endif
59
60static clockid_t get_clockid(int fd)
61{
62#define CLOCKFD 3
63#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD)
64
65 return FD_TO_CLOCKID(fd);
66}
67
68static void handle_alarm(int s)
69{
70 printf("received signal %d\n", s);
71}
72
73static int install_handler(int signum, void (*handler)(int))
74{
75 struct sigaction action;
76 sigset_t mask;
77
78 /* Unblock the signal. */
79 sigemptyset(&mask);
80 sigaddset(&mask, signum);
81 sigprocmask(SIG_UNBLOCK, &mask, NULL);
82
83 /* Install the signal handler. */
84 action.sa_handler = handler;
85 action.sa_flags = 0;
86 sigemptyset(&action.sa_mask);
87 sigaction(signum, &action, NULL);
88
89 return 0;
90}
91
92static long ppb_to_scaled_ppm(int ppb)
93{
94 /*
95 * The 'freq' field in the 'struct timex' is in parts per
96 * million, but with a 16 bit binary fractional field.
97 * Instead of calculating either one of
98 *
99 * scaled_ppm = (ppb / 1000) << 16 [1]
100 * scaled_ppm = (ppb << 16) / 1000 [2]
101 *
102 * we simply use double precision math, in order to avoid the
103 * truncation in [1] and the possible overflow in [2].
104 */
105 return (long) (ppb * 65.536);
106}
107
108static int64_t pctns(struct ptp_clock_time *t)
109{
110 return t->sec * 1000000000LL + t->nsec;
111}
112
113static void usage(char *progname)
114{
115 fprintf(stderr,
116 "usage: %s [options]\n"
117 " -a val request a one-shot alarm after 'val' seconds\n"
118 " -A val request a periodic alarm every 'val' seconds\n"
119 " -c query the ptp clock's capabilities\n"
120 " -d name device to open\n"
121 " -e val read 'val' external time stamp events\n"
122 " -f val adjust the ptp clock frequency by 'val' ppb\n"
123 " -g get the ptp clock time\n"
124 " -h prints this message\n"
125 " -i val index for event/trigger\n"
126 " -k val measure the time offset between system and phc clock\n"
127 " for 'val' times (Maximum 25)\n"
128 " -l list the current pin configuration\n"
129 " -L pin,val configure pin index 'pin' with function 'val'\n"
130 " the channel index is taken from the '-i' option\n"
131 " 'val' specifies the auxiliary function:\n"
132 " 0 - none\n"
133 " 1 - external time stamp\n"
134 " 2 - periodic output\n"
135 " -p val enable output with a period of 'val' nanoseconds\n"
136 " -P val enable or disable (val=1|0) the system clock PPS\n"
137 " -s set the ptp clock time from the system time\n"
138 " -S set the system time from the ptp clock time\n"
139 " -t val shift the ptp clock time by 'val' seconds\n"
140 " -T val set the ptp clock time to 'val' seconds\n",
141 progname);
142}
143
144int main(int argc, char *argv[])
145{
146 struct ptp_clock_caps caps;
147 struct ptp_extts_event event;
148 struct ptp_extts_request extts_request;
149 struct ptp_perout_request perout_request;
150 struct ptp_pin_desc desc;
151 struct timespec ts;
152 struct timex tx;
153
154 static timer_t timerid;
155 struct itimerspec timeout;
156 struct sigevent sigevent;
157
158 struct ptp_clock_time *pct;
159 struct ptp_sys_offset *sysoff;
160
161
162 char *progname;
163 unsigned int i;
164 int c, cnt, fd;
165
166 char *device = DEVICE;
167 clockid_t clkid;
168 int adjfreq = 0x7fffffff;
169 int adjtime = 0;
170 int capabilities = 0;
171 int extts = 0;
172 int gettime = 0;
173 int index = 0;
174 int list_pins = 0;
175 int oneshot = 0;
176 int pct_offset = 0;
177 int n_samples = 0;
178 int periodic = 0;
179 int perout = -1;
180 int pin_index = -1, pin_func;
181 int pps = -1;
182 int seconds = 0;
183 int settime = 0;
184
185 int64_t t1, t2, tp;
186 int64_t interval, offset;
187
188 progname = strrchr(argv[0], '/');
189 progname = progname ? 1+progname : argv[0];
190 while (EOF != (c = getopt(argc, argv, "a:A:cd:e:f:ghi:k:lL:p:P:sSt:T:v"))) {
191 switch (c) {
192 case 'a':
193 oneshot = atoi(optarg);
194 break;
195 case 'A':
196 periodic = atoi(optarg);
197 break;
198 case 'c':
199 capabilities = 1;
200 break;
201 case 'd':
202 device = optarg;
203 break;
204 case 'e':
205 extts = atoi(optarg);
206 break;
207 case 'f':
208 adjfreq = atoi(optarg);
209 break;
210 case 'g':
211 gettime = 1;
212 break;
213 case 'i':
214 index = atoi(optarg);
215 break;
216 case 'k':
217 pct_offset = 1;
218 n_samples = atoi(optarg);
219 break;
220 case 'l':
221 list_pins = 1;
222 break;
223 case 'L':
224 cnt = sscanf(optarg, "%d,%d", &pin_index, &pin_func);
225 if (cnt != 2) {
226 usage(progname);
227 return -1;
228 }
229 break;
230 case 'p':
231 perout = atoi(optarg);
232 break;
233 case 'P':
234 pps = atoi(optarg);
235 break;
236 case 's':
237 settime = 1;
238 break;
239 case 'S':
240 settime = 2;
241 break;
242 case 't':
243 adjtime = atoi(optarg);
244 break;
245 case 'T':
246 settime = 3;
247 seconds = atoi(optarg);
248 break;
249 case 'h':
250 usage(progname);
251 return 0;
252 case '?':
253 default:
254 usage(progname);
255 return -1;
256 }
257 }
258
259 fd = open(device, O_RDWR);
260 if (fd < 0) {
261 fprintf(stderr, "opening %s: %s\n", device, strerror(errno));
262 return -1;
263 }
264
265 clkid = get_clockid(fd);
266 if (CLOCK_INVALID == clkid) {
267 fprintf(stderr, "failed to read clock id\n");
268 return -1;
269 }
270
271 if (capabilities) {
272 if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) {
273 perror("PTP_CLOCK_GETCAPS");
274 } else {
275 printf("capabilities:\n"
276 " %d maximum frequency adjustment (ppb)\n"
277 " %d programmable alarms\n"
278 " %d external time stamp channels\n"
279 " %d programmable periodic signals\n"
280 " %d pulse per second\n"
281 " %d programmable pins\n"
282 " %d cross timestamping\n",
283 caps.max_adj,
284 caps.n_alarm,
285 caps.n_ext_ts,
286 caps.n_per_out,
287 caps.pps,
288 caps.n_pins,
289 caps.cross_timestamping);
290 }
291 }
292
293 if (0x7fffffff != adjfreq) {
294 memset(&tx, 0, sizeof(tx));
295 tx.modes = ADJ_FREQUENCY;
296 tx.freq = ppb_to_scaled_ppm(adjfreq);
297 if (clock_adjtime(clkid, &tx)) {
298 perror("clock_adjtime");
299 } else {
300 puts("frequency adjustment okay");
301 }
302 }
303
304 if (adjtime) {
305 memset(&tx, 0, sizeof(tx));
306 tx.modes = ADJ_SETOFFSET;
307 tx.time.tv_sec = adjtime;
308 tx.time.tv_usec = 0;
309 if (clock_adjtime(clkid, &tx) < 0) {
310 perror("clock_adjtime");
311 } else {
312 puts("time shift okay");
313 }
314 }
315
316 if (gettime) {
317 if (clock_gettime(clkid, &ts)) {
318 perror("clock_gettime");
319 } else {
320 printf("clock time: %ld.%09ld or %s",
321 ts.tv_sec, ts.tv_nsec, ctime(&ts.tv_sec));
322 }
323 }
324
325 if (settime == 1) {
326 clock_gettime(CLOCK_REALTIME, &ts);
327 if (clock_settime(clkid, &ts)) {
328 perror("clock_settime");
329 } else {
330 puts("set time okay");
331 }
332 }
333
334 if (settime == 2) {
335 clock_gettime(clkid, &ts);
336 if (clock_settime(CLOCK_REALTIME, &ts)) {
337 perror("clock_settime");
338 } else {
339 puts("set time okay");
340 }
341 }
342
343 if (settime == 3) {
344 ts.tv_sec = seconds;
345 ts.tv_nsec = 0;
346 if (clock_settime(clkid, &ts)) {
347 perror("clock_settime");
348 } else {
349 puts("set time okay");
350 }
351 }
352
353 if (extts) {
354 memset(&extts_request, 0, sizeof(extts_request));
355 extts_request.index = index;
356 extts_request.flags = PTP_ENABLE_FEATURE;
357 if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
358 perror("PTP_EXTTS_REQUEST");
359 extts = 0;
360 } else {
361 puts("external time stamp request okay");
362 }
363 for (; extts; extts--) {
364 cnt = read(fd, &event, sizeof(event));
365 if (cnt != sizeof(event)) {
366 perror("read");
367 break;
368 }
369 printf("event index %u at %lld.%09u\n", event.index,
370 event.t.sec, event.t.nsec);
371 fflush(stdout);
372 }
373 /* Disable the feature again. */
374 extts_request.flags = 0;
375 if (ioctl(fd, PTP_EXTTS_REQUEST, &extts_request)) {
376 perror("PTP_EXTTS_REQUEST");
377 }
378 }
379
380 if (list_pins) {
381 int n_pins = 0;
382 if (ioctl(fd, PTP_CLOCK_GETCAPS, &caps)) {
383 perror("PTP_CLOCK_GETCAPS");
384 } else {
385 n_pins = caps.n_pins;
386 }
387 for (i = 0; i < n_pins; i++) {
388 desc.index = i;
389 if (ioctl(fd, PTP_PIN_GETFUNC, &desc)) {
390 perror("PTP_PIN_GETFUNC");
391 break;
392 }
393 printf("name %s index %u func %u chan %u\n",
394 desc.name, desc.index, desc.func, desc.chan);
395 }
396 }
397
398 if (oneshot) {
399 install_handler(SIGALRM, handle_alarm);
400 /* Create a timer. */
401 sigevent.sigev_notify = SIGEV_SIGNAL;
402 sigevent.sigev_signo = SIGALRM;
403 if (timer_create(clkid, &sigevent, &timerid)) {
404 perror("timer_create");
405 return -1;
406 }
407 /* Start the timer. */
408 memset(&timeout, 0, sizeof(timeout));
409 timeout.it_value.tv_sec = oneshot;
410 if (timer_settime(timerid, 0, &timeout, NULL)) {
411 perror("timer_settime");
412 return -1;
413 }
414 pause();
415 timer_delete(timerid);
416 }
417
418 if (periodic) {
419 install_handler(SIGALRM, handle_alarm);
420 /* Create a timer. */
421 sigevent.sigev_notify = SIGEV_SIGNAL;
422 sigevent.sigev_signo = SIGALRM;
423 if (timer_create(clkid, &sigevent, &timerid)) {
424 perror("timer_create");
425 return -1;
426 }
427 /* Start the timer. */
428 memset(&timeout, 0, sizeof(timeout));
429 timeout.it_interval.tv_sec = periodic;
430 timeout.it_value.tv_sec = periodic;
431 if (timer_settime(timerid, 0, &timeout, NULL)) {
432 perror("timer_settime");
433 return -1;
434 }
435 while (1) {
436 pause();
437 }
438 timer_delete(timerid);
439 }
440
441 if (perout >= 0) {
442 if (clock_gettime(clkid, &ts)) {
443 perror("clock_gettime");
444 return -1;
445 }
446 memset(&perout_request, 0, sizeof(perout_request));
447 perout_request.index = index;
448 perout_request.start.sec = ts.tv_sec + 2;
449 perout_request.start.nsec = 0;
450 perout_request.period.sec = 0;
451 perout_request.period.nsec = perout;
452 if (ioctl(fd, PTP_PEROUT_REQUEST, &perout_request)) {
453 perror("PTP_PEROUT_REQUEST");
454 } else {
455 puts("periodic output request okay");
456 }
457 }
458
459 if (pin_index >= 0) {
460 memset(&desc, 0, sizeof(desc));
461 desc.index = pin_index;
462 desc.func = pin_func;
463 desc.chan = index;
464 if (ioctl(fd, PTP_PIN_SETFUNC, &desc)) {
465 perror("PTP_PIN_SETFUNC");
466 } else {
467 puts("set pin function okay");
468 }
469 }
470
471 if (pps != -1) {
472 int enable = pps ? 1 : 0;
473 if (ioctl(fd, PTP_ENABLE_PPS, enable)) {
474 perror("PTP_ENABLE_PPS");
475 } else {
476 puts("pps for system time request okay");
477 }
478 }
479
480 if (pct_offset) {
481 if (n_samples <= 0 || n_samples > 25) {
482 puts("n_samples should be between 1 and 25");
483 usage(progname);
484 return -1;
485 }
486
487 sysoff = calloc(1, sizeof(*sysoff));
488 if (!sysoff) {
489 perror("calloc");
490 return -1;
491 }
492 sysoff->n_samples = n_samples;
493
494 if (ioctl(fd, PTP_SYS_OFFSET, sysoff))
495 perror("PTP_SYS_OFFSET");
496 else
497 puts("system and phc clock time offset request okay");
498
499 pct = &sysoff->ts[0];
500 for (i = 0; i < sysoff->n_samples; i++) {
501 t1 = pctns(pct+2*i);
502 tp = pctns(pct+2*i+1);
503 t2 = pctns(pct+2*i+2);
504 interval = t2 - t1;
505 offset = (t2 + t1) / 2 - tp;
506
507 printf("system time: %lld.%u\n",
508 (pct+2*i)->sec, (pct+2*i)->nsec);
509 printf("phc time: %lld.%u\n",
510 (pct+2*i+1)->sec, (pct+2*i+1)->nsec);
511 printf("system time: %lld.%u\n",
512 (pct+2*i+2)->sec, (pct+2*i+2)->nsec);
513 printf("system/phc clock time offset is %" PRId64 " ns\n"
514 "system clock time delay is %" PRId64 " ns\n",
515 offset, interval);
516 }
517
518 free(sysoff);
519 }
520
521 close(fd);
522 return 0;
523}
diff --git a/tools/testing/selftests/ptp/testptp.mk b/tools/testing/selftests/ptp/testptp.mk
new file mode 100644
index 000000000000..4ef2d9755421
--- /dev/null
+++ b/tools/testing/selftests/ptp/testptp.mk
@@ -0,0 +1,33 @@
1# PTP 1588 clock support - User space test program
2#
3# Copyright (C) 2010 OMICRON electronics GmbH
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18
19CC = $(CROSS_COMPILE)gcc
20INC = -I$(KBUILD_OUTPUT)/usr/include
21CFLAGS = -Wall $(INC)
22LDLIBS = -lrt
23PROGS = testptp
24
25all: $(PROGS)
26
27testptp: testptp.o
28
29clean:
30 rm -f testptp.o
31
32distclean: clean
33 rm -f $(PROGS)
diff --git a/tools/testing/selftests/rcutorture/bin/functions.sh b/tools/testing/selftests/rcutorture/bin/functions.sh
index b325470c01b3..1426a9b97494 100644
--- a/tools/testing/selftests/rcutorture/bin/functions.sh
+++ b/tools/testing/selftests/rcutorture/bin/functions.sh
@@ -99,8 +99,9 @@ configfrag_hotplug_cpu () {
99# identify_boot_image qemu-cmd 99# identify_boot_image qemu-cmd
100# 100#
101# Returns the relative path to the kernel build image. This will be 101# Returns the relative path to the kernel build image. This will be
102# arch/<arch>/boot/bzImage unless overridden with the TORTURE_BOOT_IMAGE 102# arch/<arch>/boot/bzImage or vmlinux if bzImage is not a target for the
103# environment variable. 103# architecture, unless overridden with the TORTURE_BOOT_IMAGE environment
104# variable.
104identify_boot_image () { 105identify_boot_image () {
105 if test -n "$TORTURE_BOOT_IMAGE" 106 if test -n "$TORTURE_BOOT_IMAGE"
106 then 107 then
@@ -110,11 +111,8 @@ identify_boot_image () {
110 qemu-system-x86_64|qemu-system-i386) 111 qemu-system-x86_64|qemu-system-i386)
111 echo arch/x86/boot/bzImage 112 echo arch/x86/boot/bzImage
112 ;; 113 ;;
113 qemu-system-ppc64)
114 echo arch/powerpc/boot/bzImage
115 ;;
116 *) 114 *)
117 echo "" 115 echo vmlinux
118 ;; 116 ;;
119 esac 117 esac
120 fi 118 fi
@@ -175,7 +173,7 @@ identify_qemu_args () {
175 qemu-system-x86_64|qemu-system-i386) 173 qemu-system-x86_64|qemu-system-i386)
176 ;; 174 ;;
177 qemu-system-ppc64) 175 qemu-system-ppc64)
178 echo -enable-kvm -M pseries -cpu POWER7 -nodefaults 176 echo -enable-kvm -M pseries -nodefaults
179 echo -device spapr-vscsi 177 echo -device spapr-vscsi
180 if test -n "$TORTURE_QEMU_INTERACTIVE" -a -n "$TORTURE_QEMU_MAC" 178 if test -n "$TORTURE_QEMU_INTERACTIVE" -a -n "$TORTURE_QEMU_MAC"
181 then 179 then
diff --git a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
index 4109f306d855..ea6e373edc27 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm-test-1-run.sh
@@ -8,9 +8,9 @@
8# 8#
9# Usage: kvm-test-1-run.sh config builddir resdir seconds qemu-args boot_args 9# Usage: kvm-test-1-run.sh config builddir resdir seconds qemu-args boot_args
10# 10#
11# qemu-args defaults to "-enable-kvm -soundhw pcspk -nographic", along with 11# qemu-args defaults to "-enable-kvm -nographic", along with arguments
12# arguments specifying the number of CPUs and other 12# specifying the number of CPUs and other options
13# options generated from the underlying CPU architecture. 13# generated from the underlying CPU architecture.
14# boot_args defaults to value returned by the per_version_boot_params 14# boot_args defaults to value returned by the per_version_boot_params
15# shell function. 15# shell function.
16# 16#
@@ -96,7 +96,8 @@ if test "$base_resdir" != "$resdir" -a -f $base_resdir/bzImage -a -f $base_resdi
96then 96then
97 # Rerunning previous test, so use that test's kernel. 97 # Rerunning previous test, so use that test's kernel.
98 QEMU="`identify_qemu $base_resdir/vmlinux`" 98 QEMU="`identify_qemu $base_resdir/vmlinux`"
99 KERNEL=$base_resdir/bzImage 99 BOOT_IMAGE="`identify_boot_image $QEMU`"
100 KERNEL=$base_resdir/${BOOT_IMAGE##*/} # use the last component of ${BOOT_IMAGE}
100 ln -s $base_resdir/Make*.out $resdir # for kvm-recheck.sh 101 ln -s $base_resdir/Make*.out $resdir # for kvm-recheck.sh
101 ln -s $base_resdir/.config $resdir # for kvm-recheck.sh 102 ln -s $base_resdir/.config $resdir # for kvm-recheck.sh
102elif kvm-build.sh $config_template $builddir $T 103elif kvm-build.sh $config_template $builddir $T
@@ -110,7 +111,7 @@ then
110 if test -n "$BOOT_IMAGE" 111 if test -n "$BOOT_IMAGE"
111 then 112 then
112 cp $builddir/$BOOT_IMAGE $resdir 113 cp $builddir/$BOOT_IMAGE $resdir
113 KERNEL=$resdir/bzImage 114 KERNEL=$resdir/${BOOT_IMAGE##*/}
114 else 115 else
115 echo No identifiable boot image, not running KVM, see $resdir. 116 echo No identifiable boot image, not running KVM, see $resdir.
116 echo Do the torture scripts know about your architecture? 117 echo Do the torture scripts know about your architecture?
@@ -147,7 +148,7 @@ then
147fi 148fi
148 149
149# Generate -smp qemu argument. 150# Generate -smp qemu argument.
150qemu_args="-enable-kvm -soundhw pcspk -nographic $qemu_args" 151qemu_args="-enable-kvm -nographic $qemu_args"
151cpu_count=`configNR_CPUS.sh $config_template` 152cpu_count=`configNR_CPUS.sh $config_template`
152cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"` 153cpu_count=`configfrag_boot_cpus "$boot_args" "$config_template" "$cpu_count"`
153vcpus=`identify_qemu_vcpus` 154vcpus=`identify_qemu_vcpus`
@@ -229,6 +230,7 @@ fi
229if test $commandcompleted -eq 0 -a -n "$qemu_pid" 230if test $commandcompleted -eq 0 -a -n "$qemu_pid"
230then 231then
231 echo Grace period for qemu job at pid $qemu_pid 232 echo Grace period for qemu job at pid $qemu_pid
233 oldline="`tail $resdir/console.log`"
232 while : 234 while :
233 do 235 do
234 kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null` 236 kruntime=`awk 'BEGIN { print systime() - '"$kstarttime"' }' < /dev/null`
@@ -238,13 +240,29 @@ then
238 else 240 else
239 break 241 break
240 fi 242 fi
241 if test $kruntime -ge $((seconds + $TORTURE_SHUTDOWN_GRACE)) 243 must_continue=no
244 newline="`tail $resdir/console.log`"
245 if test "$newline" != "$oldline" && echo $newline | grep -q ' [0-9]\+us : '
246 then
247 must_continue=yes
248 fi
249 last_ts="`tail $resdir/console.log | grep '^\[ *[0-9]\+\.[0-9]\+]' | tail -1 | sed -e 's/^\[ *//' -e 's/\..*$//'`"
250 if test -z "last_ts"
251 then
252 last_ts=0
253 fi
254 if test "$newline" != "$oldline" -a "$last_ts" -lt $((seconds + $TORTURE_SHUTDOWN_GRACE))
255 then
256 must_continue=yes
257 fi
258 if test $must_continue = no -a $kruntime -ge $((seconds + $TORTURE_SHUTDOWN_GRACE))
242 then 259 then
243 echo "!!! PID $qemu_pid hung at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1 260 echo "!!! PID $qemu_pid hung at $kruntime vs. $seconds seconds" >> $resdir/Warnings 2>&1
244 kill -KILL $qemu_pid 261 kill -KILL $qemu_pid
245 break 262 break
246 fi 263 fi
247 sleep 1 264 oldline=$newline
265 sleep 10
248 done 266 done
249elif test -z "$qemu_pid" 267elif test -z "$qemu_pid"
250then 268then
diff --git a/tools/testing/selftests/rcutorture/bin/kvm.sh b/tools/testing/selftests/rcutorture/bin/kvm.sh
index 0d598145873e..0aed965f0062 100755
--- a/tools/testing/selftests/rcutorture/bin/kvm.sh
+++ b/tools/testing/selftests/rcutorture/bin/kvm.sh
@@ -48,7 +48,7 @@ resdir=""
48configs="" 48configs=""
49cpus=0 49cpus=0
50ds=`date +%Y.%m.%d-%H:%M:%S` 50ds=`date +%Y.%m.%d-%H:%M:%S`
51jitter=0 51jitter="-1"
52 52
53. functions.sh 53. functions.sh
54 54
diff --git a/tools/testing/selftests/rcutorture/bin/parse-console.sh b/tools/testing/selftests/rcutorture/bin/parse-console.sh
index 5eb49b7f864c..08aa7d50ae0e 100755
--- a/tools/testing/selftests/rcutorture/bin/parse-console.sh
+++ b/tools/testing/selftests/rcutorture/bin/parse-console.sh
@@ -33,7 +33,7 @@ if grep -Pq '\x00' < $file
33then 33then
34 print_warning Console output contains nul bytes, old qemu still running? 34 print_warning Console output contains nul bytes, old qemu still running?
35fi 35fi
36egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags 36egrep 'Badness|WARNING:|Warn|BUG|===========|Call Trace:|Oops:|detected stalls on CPUs/tasks:|self-detected stall on CPU|Stall ended before state dump start|\?\?\? Writer stall state|rcu_.*kthread starved for' < $file | grep -v 'ODEBUG: ' | grep -v 'Warning: unable to open an initial console' > $1.diags
37if test -s $1.diags 37if test -s $1.diags
38then 38then
39 print_warning Assertion failure in $file $title 39 print_warning Assertion failure in $file $title
@@ -69,6 +69,11 @@ then
69 then 69 then
70 summary="$summary Stalls: $n_stalls" 70 summary="$summary Stalls: $n_stalls"
71 fi 71 fi
72 n_starves=`grep -c 'rcu_.*kthread starved for' $1`
73 if test "$n_starves" -ne 0
74 then
75 summary="$summary Starves: $n_starves"
76 fi
72 print_warning Summary: $summary 77 print_warning Summary: $summary
73else 78else
74 rm $1.diags 79 rm $1.diags
diff --git a/tools/testing/selftests/rcutorture/doc/initrd.txt b/tools/testing/selftests/rcutorture/doc/initrd.txt
index 4170e714f044..833f826d6ec2 100644
--- a/tools/testing/selftests/rcutorture/doc/initrd.txt
+++ b/tools/testing/selftests/rcutorture/doc/initrd.txt
@@ -13,6 +13,22 @@ cd initrd
13cpio -id < /tmp/initrd.img.zcat 13cpio -id < /tmp/initrd.img.zcat
14------------------------------------------------------------------------ 14------------------------------------------------------------------------
15 15
16Another way to create an initramfs image is using "dracut"[1], which is
17available on many distros, however the initramfs dracut generates is a cpio
18archive with another cpio archive in it, so an extra step is needed to create
19the initrd directory hierarchy.
20
21Here are the commands to create a initrd directory for rcutorture using
22dracut:
23
24------------------------------------------------------------------------
25dracut --no-hostonly --no-hostonly-cmdline --module "base bash shutdown" /tmp/initramfs.img
26cd tools/testing/selftests/rcutorture
27mkdir initrd
28cd initrd
29/usr/lib/dracut/skipcpio /tmp/initramfs.img | zcat | cpio -id < /tmp/initramfs.img
30------------------------------------------------------------------------
31
16Interestingly enough, if you are running rcutorture, you don't really 32Interestingly enough, if you are running rcutorture, you don't really
17need userspace in many cases. Running without userspace has the 33need userspace in many cases. Running without userspace has the
18advantage of allowing you to test your kernel independently of the 34advantage of allowing you to test your kernel independently of the
@@ -89,3 +105,9 @@ while :
89do 105do
90 sleep 10 106 sleep 10
91done 107done
108------------------------------------------------------------------------
109
110References:
111[1]: https://dracut.wiki.kernel.org/index.php/Main_Page
112[2]: http://blog.elastocloud.org/2015/06/rapid-linux-kernel-devtest-with-qemu.html
113[3]: https://www.centos.org/forums/viewtopic.php?t=51621
diff --git a/tools/testing/selftests/seccomp/seccomp_bpf.c b/tools/testing/selftests/seccomp/seccomp_bpf.c
index 2e58549b2f02..03f1fa495d74 100644
--- a/tools/testing/selftests/seccomp/seccomp_bpf.c
+++ b/tools/testing/selftests/seccomp/seccomp_bpf.c
@@ -1021,8 +1021,8 @@ void tracer_stop(int sig)
1021typedef void tracer_func_t(struct __test_metadata *_metadata, 1021typedef void tracer_func_t(struct __test_metadata *_metadata,
1022 pid_t tracee, int status, void *args); 1022 pid_t tracee, int status, void *args);
1023 1023
1024void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee, 1024void start_tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
1025 tracer_func_t tracer_func, void *args) 1025 tracer_func_t tracer_func, void *args, bool ptrace_syscall)
1026{ 1026{
1027 int ret = -1; 1027 int ret = -1;
1028 struct sigaction action = { 1028 struct sigaction action = {
@@ -1042,12 +1042,16 @@ void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
1042 /* Wait for attach stop */ 1042 /* Wait for attach stop */
1043 wait(NULL); 1043 wait(NULL);
1044 1044
1045 ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, PTRACE_O_TRACESECCOMP); 1045 ret = ptrace(PTRACE_SETOPTIONS, tracee, NULL, ptrace_syscall ?
1046 PTRACE_O_TRACESYSGOOD :
1047 PTRACE_O_TRACESECCOMP);
1046 ASSERT_EQ(0, ret) { 1048 ASSERT_EQ(0, ret) {
1047 TH_LOG("Failed to set PTRACE_O_TRACESECCOMP"); 1049 TH_LOG("Failed to set PTRACE_O_TRACESECCOMP");
1048 kill(tracee, SIGKILL); 1050 kill(tracee, SIGKILL);
1049 } 1051 }
1050 ptrace(PTRACE_CONT, tracee, NULL, 0); 1052 ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT,
1053 tracee, NULL, 0);
1054 ASSERT_EQ(0, ret);
1051 1055
1052 /* Unblock the tracee */ 1056 /* Unblock the tracee */
1053 ASSERT_EQ(1, write(fd, "A", 1)); 1057 ASSERT_EQ(1, write(fd, "A", 1));
@@ -1063,12 +1067,13 @@ void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
1063 /* Child is dead. Time to go. */ 1067 /* Child is dead. Time to go. */
1064 return; 1068 return;
1065 1069
1066 /* Make sure this is a seccomp event. */ 1070 /* Check if this is a seccomp event. */
1067 ASSERT_EQ(true, IS_SECCOMP_EVENT(status)); 1071 ASSERT_EQ(!ptrace_syscall, IS_SECCOMP_EVENT(status));
1068 1072
1069 tracer_func(_metadata, tracee, status, args); 1073 tracer_func(_metadata, tracee, status, args);
1070 1074
1071 ret = ptrace(PTRACE_CONT, tracee, NULL, NULL); 1075 ret = ptrace(ptrace_syscall ? PTRACE_SYSCALL : PTRACE_CONT,
1076 tracee, NULL, 0);
1072 ASSERT_EQ(0, ret); 1077 ASSERT_EQ(0, ret);
1073 } 1078 }
1074 /* Directly report the status of our test harness results. */ 1079 /* Directly report the status of our test harness results. */
@@ -1079,7 +1084,7 @@ void tracer(struct __test_metadata *_metadata, int fd, pid_t tracee,
1079void cont_handler(int num) 1084void cont_handler(int num)
1080{ } 1085{ }
1081pid_t setup_trace_fixture(struct __test_metadata *_metadata, 1086pid_t setup_trace_fixture(struct __test_metadata *_metadata,
1082 tracer_func_t func, void *args) 1087 tracer_func_t func, void *args, bool ptrace_syscall)
1083{ 1088{
1084 char sync; 1089 char sync;
1085 int pipefd[2]; 1090 int pipefd[2];
@@ -1095,7 +1100,8 @@ pid_t setup_trace_fixture(struct __test_metadata *_metadata,
1095 signal(SIGALRM, cont_handler); 1100 signal(SIGALRM, cont_handler);
1096 if (tracer_pid == 0) { 1101 if (tracer_pid == 0) {
1097 close(pipefd[0]); 1102 close(pipefd[0]);
1098 tracer(_metadata, pipefd[1], tracee, func, args); 1103 start_tracer(_metadata, pipefd[1], tracee, func, args,
1104 ptrace_syscall);
1099 syscall(__NR_exit, 0); 1105 syscall(__NR_exit, 0);
1100 } 1106 }
1101 close(pipefd[1]); 1107 close(pipefd[1]);
@@ -1177,7 +1183,7 @@ FIXTURE_SETUP(TRACE_poke)
1177 1183
1178 /* Launch tracer. */ 1184 /* Launch tracer. */
1179 self->tracer = setup_trace_fixture(_metadata, tracer_poke, 1185 self->tracer = setup_trace_fixture(_metadata, tracer_poke,
1180 &self->tracer_args); 1186 &self->tracer_args, false);
1181} 1187}
1182 1188
1183FIXTURE_TEARDOWN(TRACE_poke) 1189FIXTURE_TEARDOWN(TRACE_poke)
@@ -1399,6 +1405,29 @@ void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
1399 1405
1400} 1406}
1401 1407
1408void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
1409 int status, void *args)
1410{
1411 int ret, nr;
1412 unsigned long msg;
1413 static bool entry;
1414
1415 /* Make sure we got an empty message. */
1416 ret = ptrace(PTRACE_GETEVENTMSG, tracee, NULL, &msg);
1417 EXPECT_EQ(0, ret);
1418 EXPECT_EQ(0, msg);
1419
1420 /* The only way to tell PTRACE_SYSCALL entry/exit is by counting. */
1421 entry = !entry;
1422 if (!entry)
1423 return;
1424
1425 nr = get_syscall(_metadata, tracee);
1426
1427 if (nr == __NR_getpid)
1428 change_syscall(_metadata, tracee, __NR_getppid);
1429}
1430
1402FIXTURE_DATA(TRACE_syscall) { 1431FIXTURE_DATA(TRACE_syscall) {
1403 struct sock_fprog prog; 1432 struct sock_fprog prog;
1404 pid_t tracer, mytid, mypid, parent; 1433 pid_t tracer, mytid, mypid, parent;
@@ -1440,7 +1469,8 @@ FIXTURE_SETUP(TRACE_syscall)
1440 ASSERT_NE(self->parent, self->mypid); 1469 ASSERT_NE(self->parent, self->mypid);
1441 1470
1442 /* Launch tracer. */ 1471 /* Launch tracer. */
1443 self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL); 1472 self->tracer = setup_trace_fixture(_metadata, tracer_syscall, NULL,
1473 false);
1444} 1474}
1445 1475
1446FIXTURE_TEARDOWN(TRACE_syscall) 1476FIXTURE_TEARDOWN(TRACE_syscall)
@@ -1500,6 +1530,130 @@ TEST_F(TRACE_syscall, syscall_dropped)
1500 EXPECT_NE(self->mytid, syscall(__NR_gettid)); 1530 EXPECT_NE(self->mytid, syscall(__NR_gettid));
1501} 1531}
1502 1532
1533TEST_F(TRACE_syscall, skip_after_RET_TRACE)
1534{
1535 struct sock_filter filter[] = {
1536 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1537 offsetof(struct seccomp_data, nr)),
1538 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
1539 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM),
1540 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1541 };
1542 struct sock_fprog prog = {
1543 .len = (unsigned short)ARRAY_SIZE(filter),
1544 .filter = filter,
1545 };
1546 long ret;
1547
1548 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1549 ASSERT_EQ(0, ret);
1550
1551 /* Install fixture filter. */
1552 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1553 ASSERT_EQ(0, ret);
1554
1555 /* Install "errno on getppid" filter. */
1556 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
1557 ASSERT_EQ(0, ret);
1558
1559 /* Tracer will redirect getpid to getppid, and we should see EPERM. */
1560 EXPECT_EQ(-1, syscall(__NR_getpid));
1561 EXPECT_EQ(EPERM, errno);
1562}
1563
1564TEST_F_SIGNAL(TRACE_syscall, kill_after_RET_TRACE, SIGSYS)
1565{
1566 struct sock_filter filter[] = {
1567 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1568 offsetof(struct seccomp_data, nr)),
1569 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
1570 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
1571 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1572 };
1573 struct sock_fprog prog = {
1574 .len = (unsigned short)ARRAY_SIZE(filter),
1575 .filter = filter,
1576 };
1577 long ret;
1578
1579 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1580 ASSERT_EQ(0, ret);
1581
1582 /* Install fixture filter. */
1583 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
1584 ASSERT_EQ(0, ret);
1585
1586 /* Install "death on getppid" filter. */
1587 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
1588 ASSERT_EQ(0, ret);
1589
1590 /* Tracer will redirect getpid to getppid, and we should die. */
1591 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1592}
1593
1594TEST_F(TRACE_syscall, skip_after_ptrace)
1595{
1596 struct sock_filter filter[] = {
1597 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1598 offsetof(struct seccomp_data, nr)),
1599 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
1600 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ERRNO | EPERM),
1601 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1602 };
1603 struct sock_fprog prog = {
1604 .len = (unsigned short)ARRAY_SIZE(filter),
1605 .filter = filter,
1606 };
1607 long ret;
1608
1609 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1610 teardown_trace_fixture(_metadata, self->tracer);
1611 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1612 true);
1613
1614 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1615 ASSERT_EQ(0, ret);
1616
1617 /* Install "errno on getppid" filter. */
1618 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
1619 ASSERT_EQ(0, ret);
1620
1621 /* Tracer will redirect getpid to getppid, and we should see EPERM. */
1622 EXPECT_EQ(-1, syscall(__NR_getpid));
1623 EXPECT_EQ(EPERM, errno);
1624}
1625
1626TEST_F_SIGNAL(TRACE_syscall, kill_after_ptrace, SIGSYS)
1627{
1628 struct sock_filter filter[] = {
1629 BPF_STMT(BPF_LD|BPF_W|BPF_ABS,
1630 offsetof(struct seccomp_data, nr)),
1631 BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
1632 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_KILL),
1633 BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
1634 };
1635 struct sock_fprog prog = {
1636 .len = (unsigned short)ARRAY_SIZE(filter),
1637 .filter = filter,
1638 };
1639 long ret;
1640
1641 /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
1642 teardown_trace_fixture(_metadata, self->tracer);
1643 self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
1644 true);
1645
1646 ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
1647 ASSERT_EQ(0, ret);
1648
1649 /* Install "death on getppid" filter. */
1650 ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog, 0, 0);
1651 ASSERT_EQ(0, ret);
1652
1653 /* Tracer will redirect getpid to getppid, and we should die. */
1654 EXPECT_NE(self->mypid, syscall(__NR_getpid));
1655}
1656
1503#ifndef __NR_seccomp 1657#ifndef __NR_seccomp
1504# if defined(__i386__) 1658# if defined(__i386__)
1505# define __NR_seccomp 354 1659# define __NR_seccomp 354
diff --git a/tools/testing/selftests/timers/Makefile b/tools/testing/selftests/timers/Makefile
index 4a1be1b75a7f..1d5556869137 100644
--- a/tools/testing/selftests/timers/Makefile
+++ b/tools/testing/selftests/timers/Makefile
@@ -10,7 +10,7 @@ TEST_PROGS = posix_timers nanosleep nsleep-lat set-timer-lat mqueue-lat \
10 10
11TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \ 11TEST_PROGS_EXTENDED = alarmtimer-suspend valid-adjtimex adjtick change_skew \
12 skew_consistency clocksource-switch leap-a-day \ 12 skew_consistency clocksource-switch leap-a-day \
13 leapcrash set-tai set-2038 13 leapcrash set-tai set-2038 set-tz
14 14
15bins = $(TEST_PROGS) $(TEST_PROGS_EXTENDED) 15bins = $(TEST_PROGS) $(TEST_PROGS_EXTENDED)
16 16
@@ -30,6 +30,7 @@ run_destructive_tests: run_tests
30 ./clocksource-switch 30 ./clocksource-switch
31 ./leap-a-day -s -i 10 31 ./leap-a-day -s -i 10
32 ./leapcrash 32 ./leapcrash
33 ./set-tz
33 ./set-tai 34 ./set-tai
34 ./set-2038 35 ./set-2038
35 36
diff --git a/tools/testing/selftests/timers/posix_timers.c b/tools/testing/selftests/timers/posix_timers.c
index 5a246a02dff3..15cf56d32155 100644
--- a/tools/testing/selftests/timers/posix_timers.c
+++ b/tools/testing/selftests/timers/posix_timers.c
@@ -122,7 +122,7 @@ static int check_itimer(int which)
122 else if (which == ITIMER_REAL) 122 else if (which == ITIMER_REAL)
123 idle_loop(); 123 idle_loop();
124 124
125 gettimeofday(&end, NULL); 125 err = gettimeofday(&end, NULL);
126 if (err < 0) { 126 if (err < 0) {
127 perror("Can't call gettimeofday()\n"); 127 perror("Can't call gettimeofday()\n");
128 return -1; 128 return -1;
@@ -175,7 +175,7 @@ static int check_timer_create(int which)
175 175
176 user_loop(); 176 user_loop();
177 177
178 gettimeofday(&end, NULL); 178 err = gettimeofday(&end, NULL);
179 if (err < 0) { 179 if (err < 0) {
180 perror("Can't call gettimeofday()\n"); 180 perror("Can't call gettimeofday()\n");
181 return -1; 181 return -1;
diff --git a/tools/testing/selftests/timers/rtctest.c b/tools/testing/selftests/timers/rtctest.c
index 624bce51b27d..4230d3052e5d 100644
--- a/tools/testing/selftests/timers/rtctest.c
+++ b/tools/testing/selftests/timers/rtctest.c
@@ -144,11 +144,12 @@ test_READ:
144 144
145 retval = ioctl(fd, RTC_ALM_SET, &rtc_tm); 145 retval = ioctl(fd, RTC_ALM_SET, &rtc_tm);
146 if (retval == -1) { 146 if (retval == -1) {
147 if (errno == ENOTTY) { 147 if (errno == EINVAL) {
148 fprintf(stderr, 148 fprintf(stderr,
149 "\n...Alarm IRQs not supported.\n"); 149 "\n...Alarm IRQs not supported.\n");
150 goto test_PIE; 150 goto test_PIE;
151 } 151 }
152
152 perror("RTC_ALM_SET ioctl"); 153 perror("RTC_ALM_SET ioctl");
153 exit(errno); 154 exit(errno);
154 } 155 }
@@ -166,6 +167,12 @@ test_READ:
166 /* Enable alarm interrupts */ 167 /* Enable alarm interrupts */
167 retval = ioctl(fd, RTC_AIE_ON, 0); 168 retval = ioctl(fd, RTC_AIE_ON, 0);
168 if (retval == -1) { 169 if (retval == -1) {
170 if (errno == EINVAL) {
171 fprintf(stderr,
172 "\n...Alarm IRQs not supported.\n");
173 goto test_PIE;
174 }
175
169 perror("RTC_AIE_ON ioctl"); 176 perror("RTC_AIE_ON ioctl");
170 exit(errno); 177 exit(errno);
171 } 178 }
@@ -193,7 +200,7 @@ test_PIE:
193 retval = ioctl(fd, RTC_IRQP_READ, &tmp); 200 retval = ioctl(fd, RTC_IRQP_READ, &tmp);
194 if (retval == -1) { 201 if (retval == -1) {
195 /* not all RTCs support periodic IRQs */ 202 /* not all RTCs support periodic IRQs */
196 if (errno == ENOTTY) { 203 if (errno == EINVAL) {
197 fprintf(stderr, "\nNo periodic IRQ support\n"); 204 fprintf(stderr, "\nNo periodic IRQ support\n");
198 goto done; 205 goto done;
199 } 206 }
@@ -211,7 +218,7 @@ test_PIE:
211 retval = ioctl(fd, RTC_IRQP_SET, tmp); 218 retval = ioctl(fd, RTC_IRQP_SET, tmp);
212 if (retval == -1) { 219 if (retval == -1) {
213 /* not all RTCs can change their periodic IRQ rate */ 220 /* not all RTCs can change their periodic IRQ rate */
214 if (errno == ENOTTY) { 221 if (errno == EINVAL) {
215 fprintf(stderr, 222 fprintf(stderr,
216 "\n...Periodic IRQ rate is fixed\n"); 223 "\n...Periodic IRQ rate is fixed\n");
217 goto done; 224 goto done;
diff --git a/tools/testing/selftests/timers/set-tz.c b/tools/testing/selftests/timers/set-tz.c
new file mode 100644
index 000000000000..f4184928b16b
--- /dev/null
+++ b/tools/testing/selftests/timers/set-tz.c
@@ -0,0 +1,119 @@
1/* Set tz value
2 * by: John Stultz <john.stultz@linaro.org>
3 * (C) Copyright Linaro 2016
4 * Licensed under the GPLv2
5 *
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <time.h>
21#include <sys/time.h>
22#include <sys/timex.h>
23#include <string.h>
24#include <signal.h>
25#include <unistd.h>
26#ifdef KTEST
27#include "../kselftest.h"
28#else
29static inline int ksft_exit_pass(void)
30{
31 exit(0);
32}
33static inline int ksft_exit_fail(void)
34{
35 exit(1);
36}
37#endif
38
39int set_tz(int min, int dst)
40{
41 struct timezone tz;
42
43 tz.tz_minuteswest = min;
44 tz.tz_dsttime = dst;
45
46 return settimeofday(0, &tz);
47}
48
49int get_tz_min(void)
50{
51 struct timezone tz;
52 struct timeval tv;
53
54 memset(&tz, 0, sizeof(tz));
55 gettimeofday(&tv, &tz);
56 return tz.tz_minuteswest;
57}
58
59int get_tz_dst(void)
60{
61 struct timezone tz;
62 struct timeval tv;
63
64 memset(&tz, 0, sizeof(tz));
65 gettimeofday(&tv, &tz);
66 return tz.tz_dsttime;
67}
68
69int main(int argc, char **argv)
70{
71 int i, ret;
72 int min, dst;
73
74 min = get_tz_min();
75 dst = get_tz_dst();
76 printf("tz_minuteswest started at %i, dst at %i\n", min, dst);
77
78 printf("Checking tz_minuteswest can be properly set: ");
79 for (i = -15*60; i < 15*60; i += 30) {
80 ret = set_tz(i, dst);
81 ret = get_tz_min();
82 if (ret != i) {
83 printf("[FAILED] expected: %i got %i\n", i, ret);
84 goto err;
85 }
86 }
87 printf("[OK]\n");
88
89 printf("Checking invalid tz_minuteswest values are caught: ");
90
91 if (!set_tz(-15*60-1, dst)) {
92 printf("[FAILED] %i didn't return failure!\n", -15*60-1);
93 goto err;
94 }
95
96 if (!set_tz(15*60+1, dst)) {
97 printf("[FAILED] %i didn't return failure!\n", 15*60+1);
98 goto err;
99 }
100
101 if (!set_tz(-24*60, dst)) {
102 printf("[FAILED] %i didn't return failure!\n", -24*60);
103 goto err;
104 }
105
106 if (!set_tz(24*60, dst)) {
107 printf("[FAILED] %i didn't return failure!\n", 24*60);
108 goto err;
109 }
110
111 printf("[OK]\n");
112
113 set_tz(min, dst);
114 return ksft_exit_pass();
115
116err:
117 set_tz(min, dst);
118 return ksft_exit_fail();
119}
diff --git a/tools/testing/selftests/vDSO/.gitignore b/tools/testing/selftests/vDSO/.gitignore
new file mode 100644
index 000000000000..133bf9ee986c
--- /dev/null
+++ b/tools/testing/selftests/vDSO/.gitignore
@@ -0,0 +1,2 @@
1vdso_test
2vdso_standalone_test_x86
diff --git a/tools/testing/selftests/vDSO/Makefile b/tools/testing/selftests/vDSO/Makefile
new file mode 100644
index 000000000000..706b68b1c372
--- /dev/null
+++ b/tools/testing/selftests/vDSO/Makefile
@@ -0,0 +1,20 @@
1ifndef CROSS_COMPILE
2CFLAGS := -std=gnu99
3CFLAGS_vdso_standalone_test_x86 := -nostdlib -fno-asynchronous-unwind-tables -fno-stack-protector
4ifeq ($(CONFIG_X86_32),y)
5LDLIBS += -lgcc_s
6endif
7
8TEST_PROGS := vdso_test vdso_standalone_test_x86
9
10all: $(TEST_PROGS)
11vdso_test: parse_vdso.c vdso_test.c
12vdso_standalone_test_x86: vdso_standalone_test_x86.c parse_vdso.c
13 $(CC) $(CFLAGS) $(CFLAGS_vdso_standalone_test_x86) \
14 vdso_standalone_test_x86.c parse_vdso.c \
15 -o vdso_standalone_test_x86
16
17include ../lib.mk
18clean:
19 rm -fr $(TEST_PROGS)
20endif
diff --git a/tools/testing/selftests/vDSO/parse_vdso.c b/tools/testing/selftests/vDSO/parse_vdso.c
new file mode 100644
index 000000000000..1dbb4b87268f
--- /dev/null
+++ b/tools/testing/selftests/vDSO/parse_vdso.c
@@ -0,0 +1,269 @@
1/*
2 * parse_vdso.c: Linux reference vDSO parser
3 * Written by Andrew Lutomirski, 2011-2014.
4 *
5 * This code is meant to be linked in to various programs that run on Linux.
6 * As such, it is available with as few restrictions as possible. This file
7 * is licensed under the Creative Commons Zero License, version 1.0,
8 * available at http://creativecommons.org/publicdomain/zero/1.0/legalcode
9 *
10 * The vDSO is a regular ELF DSO that the kernel maps into user space when
11 * it starts a program. It works equally well in statically and dynamically
12 * linked binaries.
13 *
14 * This code is tested on x86. In principle it should work on any
15 * architecture that has a vDSO.
16 */
17
18#include <stdbool.h>
19#include <stdint.h>
20#include <string.h>
21#include <limits.h>
22#include <elf.h>
23
24/*
25 * To use this vDSO parser, first call one of the vdso_init_* functions.
26 * If you've already parsed auxv, then pass the value of AT_SYSINFO_EHDR
27 * to vdso_init_from_sysinfo_ehdr. Otherwise pass auxv to vdso_init_from_auxv.
28 * Then call vdso_sym for each symbol you want. For example, to look up
29 * gettimeofday on x86_64, use:
30 *
31 * <some pointer> = vdso_sym("LINUX_2.6", "gettimeofday");
32 * or
33 * <some pointer> = vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
34 *
35 * vdso_sym will return 0 if the symbol doesn't exist or if the init function
36 * failed or was not called. vdso_sym is a little slow, so its return value
37 * should be cached.
38 *
39 * vdso_sym is threadsafe; the init functions are not.
40 *
41 * These are the prototypes:
42 */
43extern void vdso_init_from_auxv(void *auxv);
44extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
45extern void *vdso_sym(const char *version, const char *name);
46
47
48/* And here's the code. */
49#ifndef ELF_BITS
50# if ULONG_MAX > 0xffffffffUL
51# define ELF_BITS 64
52# else
53# define ELF_BITS 32
54# endif
55#endif
56
57#define ELF_BITS_XFORM2(bits, x) Elf##bits##_##x
58#define ELF_BITS_XFORM(bits, x) ELF_BITS_XFORM2(bits, x)
59#define ELF(x) ELF_BITS_XFORM(ELF_BITS, x)
60
61static struct vdso_info
62{
63 bool valid;
64
65 /* Load information */
66 uintptr_t load_addr;
67 uintptr_t load_offset; /* load_addr - recorded vaddr */
68
69 /* Symbol table */
70 ELF(Sym) *symtab;
71 const char *symstrings;
72 ELF(Word) *bucket, *chain;
73 ELF(Word) nbucket, nchain;
74
75 /* Version table */
76 ELF(Versym) *versym;
77 ELF(Verdef) *verdef;
78} vdso_info;
79
80/* Straight from the ELF specification. */
81static unsigned long elf_hash(const unsigned char *name)
82{
83 unsigned long h = 0, g;
84 while (*name)
85 {
86 h = (h << 4) + *name++;
87 if (g = h & 0xf0000000)
88 h ^= g >> 24;
89 h &= ~g;
90 }
91 return h;
92}
93
94void vdso_init_from_sysinfo_ehdr(uintptr_t base)
95{
96 size_t i;
97 bool found_vaddr = false;
98
99 vdso_info.valid = false;
100
101 vdso_info.load_addr = base;
102
103 ELF(Ehdr) *hdr = (ELF(Ehdr)*)base;
104 if (hdr->e_ident[EI_CLASS] !=
105 (ELF_BITS == 32 ? ELFCLASS32 : ELFCLASS64)) {
106 return; /* Wrong ELF class -- check ELF_BITS */
107 }
108
109 ELF(Phdr) *pt = (ELF(Phdr)*)(vdso_info.load_addr + hdr->e_phoff);
110 ELF(Dyn) *dyn = 0;
111
112 /*
113 * We need two things from the segment table: the load offset
114 * and the dynamic table.
115 */
116 for (i = 0; i < hdr->e_phnum; i++)
117 {
118 if (pt[i].p_type == PT_LOAD && !found_vaddr) {
119 found_vaddr = true;
120 vdso_info.load_offset = base
121 + (uintptr_t)pt[i].p_offset
122 - (uintptr_t)pt[i].p_vaddr;
123 } else if (pt[i].p_type == PT_DYNAMIC) {
124 dyn = (ELF(Dyn)*)(base + pt[i].p_offset);
125 }
126 }
127
128 if (!found_vaddr || !dyn)
129 return; /* Failed */
130
131 /*
132 * Fish out the useful bits of the dynamic table.
133 */
134 ELF(Word) *hash = 0;
135 vdso_info.symstrings = 0;
136 vdso_info.symtab = 0;
137 vdso_info.versym = 0;
138 vdso_info.verdef = 0;
139 for (i = 0; dyn[i].d_tag != DT_NULL; i++) {
140 switch (dyn[i].d_tag) {
141 case DT_STRTAB:
142 vdso_info.symstrings = (const char *)
143 ((uintptr_t)dyn[i].d_un.d_ptr
144 + vdso_info.load_offset);
145 break;
146 case DT_SYMTAB:
147 vdso_info.symtab = (ELF(Sym) *)
148 ((uintptr_t)dyn[i].d_un.d_ptr
149 + vdso_info.load_offset);
150 break;
151 case DT_HASH:
152 hash = (ELF(Word) *)
153 ((uintptr_t)dyn[i].d_un.d_ptr
154 + vdso_info.load_offset);
155 break;
156 case DT_VERSYM:
157 vdso_info.versym = (ELF(Versym) *)
158 ((uintptr_t)dyn[i].d_un.d_ptr
159 + vdso_info.load_offset);
160 break;
161 case DT_VERDEF:
162 vdso_info.verdef = (ELF(Verdef) *)
163 ((uintptr_t)dyn[i].d_un.d_ptr
164 + vdso_info.load_offset);
165 break;
166 }
167 }
168 if (!vdso_info.symstrings || !vdso_info.symtab || !hash)
169 return; /* Failed */
170
171 if (!vdso_info.verdef)
172 vdso_info.versym = 0;
173
174 /* Parse the hash table header. */
175 vdso_info.nbucket = hash[0];
176 vdso_info.nchain = hash[1];
177 vdso_info.bucket = &hash[2];
178 vdso_info.chain = &hash[vdso_info.nbucket + 2];
179
180 /* That's all we need. */
181 vdso_info.valid = true;
182}
183
184static bool vdso_match_version(ELF(Versym) ver,
185 const char *name, ELF(Word) hash)
186{
187 /*
188 * This is a helper function to check if the version indexed by
189 * ver matches name (which hashes to hash).
190 *
191 * The version definition table is a mess, and I don't know how
192 * to do this in better than linear time without allocating memory
193 * to build an index. I also don't know why the table has
194 * variable size entries in the first place.
195 *
196 * For added fun, I can't find a comprehensible specification of how
197 * to parse all the weird flags in the table.
198 *
199 * So I just parse the whole table every time.
200 */
201
202 /* First step: find the version definition */
203 ver &= 0x7fff; /* Apparently bit 15 means "hidden" */
204 ELF(Verdef) *def = vdso_info.verdef;
205 while(true) {
206 if ((def->vd_flags & VER_FLG_BASE) == 0
207 && (def->vd_ndx & 0x7fff) == ver)
208 break;
209
210 if (def->vd_next == 0)
211 return false; /* No definition. */
212
213 def = (ELF(Verdef) *)((char *)def + def->vd_next);
214 }
215
216 /* Now figure out whether it matches. */
217 ELF(Verdaux) *aux = (ELF(Verdaux)*)((char *)def + def->vd_aux);
218 return def->vd_hash == hash
219 && !strcmp(name, vdso_info.symstrings + aux->vda_name);
220}
221
222void *vdso_sym(const char *version, const char *name)
223{
224 unsigned long ver_hash;
225 if (!vdso_info.valid)
226 return 0;
227
228 ver_hash = elf_hash(version);
229 ELF(Word) chain = vdso_info.bucket[elf_hash(name) % vdso_info.nbucket];
230
231 for (; chain != STN_UNDEF; chain = vdso_info.chain[chain]) {
232 ELF(Sym) *sym = &vdso_info.symtab[chain];
233
234 /* Check for a defined global or weak function w/ right name. */
235 if (ELF64_ST_TYPE(sym->st_info) != STT_FUNC)
236 continue;
237 if (ELF64_ST_BIND(sym->st_info) != STB_GLOBAL &&
238 ELF64_ST_BIND(sym->st_info) != STB_WEAK)
239 continue;
240 if (sym->st_shndx == SHN_UNDEF)
241 continue;
242 if (strcmp(name, vdso_info.symstrings + sym->st_name))
243 continue;
244
245 /* Check symbol version. */
246 if (vdso_info.versym
247 && !vdso_match_version(vdso_info.versym[chain],
248 version, ver_hash))
249 continue;
250
251 return (void *)(vdso_info.load_offset + sym->st_value);
252 }
253
254 return 0;
255}
256
257void vdso_init_from_auxv(void *auxv)
258{
259 ELF(auxv_t) *elf_auxv = auxv;
260 for (int i = 0; elf_auxv[i].a_type != AT_NULL; i++)
261 {
262 if (elf_auxv[i].a_type == AT_SYSINFO_EHDR) {
263 vdso_init_from_sysinfo_ehdr(elf_auxv[i].a_un.a_val);
264 return;
265 }
266 }
267
268 vdso_info.valid = false;
269}
diff --git a/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c
new file mode 100644
index 000000000000..93b0ebf8cc38
--- /dev/null
+++ b/tools/testing/selftests/vDSO/vdso_standalone_test_x86.c
@@ -0,0 +1,128 @@
1/*
2 * vdso_test.c: Sample code to test parse_vdso.c on x86
3 * Copyright (c) 2011-2014 Andy Lutomirski
4 * Subject to the GNU General Public License, version 2
5 *
6 * You can amuse yourself by compiling with:
7 * gcc -std=gnu99 -nostdlib
8 * -Os -fno-asynchronous-unwind-tables -flto -lgcc_s
9 * vdso_standalone_test_x86.c parse_vdso.c
10 * to generate a small binary. On x86_64, you can omit -lgcc_s
11 * if you want the binary to be completely standalone.
12 */
13
14#include <sys/syscall.h>
15#include <sys/time.h>
16#include <unistd.h>
17#include <stdint.h>
18
19extern void *vdso_sym(const char *version, const char *name);
20extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
21extern void vdso_init_from_auxv(void *auxv);
22
23/* We need a libc functions... */
24int strcmp(const char *a, const char *b)
25{
26 /* This implementation is buggy: it never returns -1. */
27 while (*a || *b) {
28 if (*a != *b)
29 return 1;
30 if (*a == 0 || *b == 0)
31 return 1;
32 a++;
33 b++;
34 }
35
36 return 0;
37}
38
39/* ...and two syscalls. This is x86-specific. */
40static inline long x86_syscall3(long nr, long a0, long a1, long a2)
41{
42 long ret;
43#ifdef __x86_64__
44 asm volatile ("syscall" : "=a" (ret) : "a" (nr),
45 "D" (a0), "S" (a1), "d" (a2) :
46 "cc", "memory", "rcx",
47 "r8", "r9", "r10", "r11" );
48#else
49 asm volatile ("int $0x80" : "=a" (ret) : "a" (nr),
50 "b" (a0), "c" (a1), "d" (a2) :
51 "cc", "memory" );
52#endif
53 return ret;
54}
55
56static inline long linux_write(int fd, const void *data, size_t len)
57{
58 return x86_syscall3(__NR_write, fd, (long)data, (long)len);
59}
60
61static inline void linux_exit(int code)
62{
63 x86_syscall3(__NR_exit, code, 0, 0);
64}
65
66void to_base10(char *lastdig, time_t n)
67{
68 while (n) {
69 *lastdig = (n % 10) + '0';
70 n /= 10;
71 lastdig--;
72 }
73}
74
75__attribute__((externally_visible)) void c_main(void **stack)
76{
77 /* Parse the stack */
78 long argc = (long)*stack;
79 stack += argc + 2;
80
81 /* Now we're pointing at the environment. Skip it. */
82 while(*stack)
83 stack++;
84 stack++;
85
86 /* Now we're pointing at auxv. Initialize the vDSO parser. */
87 vdso_init_from_auxv((void *)stack);
88
89 /* Find gettimeofday. */
90 typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
91 gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
92
93 if (!gtod)
94 linux_exit(1);
95
96 struct timeval tv;
97 long ret = gtod(&tv, 0);
98
99 if (ret == 0) {
100 char buf[] = "The time is .000000\n";
101 to_base10(buf + 31, tv.tv_sec);
102 to_base10(buf + 38, tv.tv_usec);
103 linux_write(1, buf, sizeof(buf) - 1);
104 } else {
105 linux_exit(ret);
106 }
107
108 linux_exit(0);
109}
110
111/*
112 * This is the real entry point. It passes the initial stack into
113 * the C entry point.
114 */
115asm (
116 ".text\n"
117 ".global _start\n"
118 ".type _start,@function\n"
119 "_start:\n\t"
120#ifdef __x86_64__
121 "mov %rsp,%rdi\n\t"
122 "jmp c_main"
123#else
124 "push %esp\n\t"
125 "call c_main\n\t"
126 "int $3"
127#endif
128 );
diff --git a/tools/testing/selftests/vDSO/vdso_test.c b/tools/testing/selftests/vDSO/vdso_test.c
new file mode 100644
index 000000000000..8daeb7d7032c
--- /dev/null
+++ b/tools/testing/selftests/vDSO/vdso_test.c
@@ -0,0 +1,52 @@
1/*
2 * vdso_test.c: Sample code to test parse_vdso.c
3 * Copyright (c) 2014 Andy Lutomirski
4 * Subject to the GNU General Public License, version 2
5 *
6 * Compile with:
7 * gcc -std=gnu99 vdso_test.c parse_vdso.c
8 *
9 * Tested on x86, 32-bit and 64-bit. It may work on other architectures, too.
10 */
11
12#include <stdint.h>
13#include <elf.h>
14#include <stdio.h>
15#include <sys/auxv.h>
16#include <sys/time.h>
17
18extern void *vdso_sym(const char *version, const char *name);
19extern void vdso_init_from_sysinfo_ehdr(uintptr_t base);
20extern void vdso_init_from_auxv(void *auxv);
21
22int main(int argc, char **argv)
23{
24 unsigned long sysinfo_ehdr = getauxval(AT_SYSINFO_EHDR);
25 if (!sysinfo_ehdr) {
26 printf("AT_SYSINFO_EHDR is not present!\n");
27 return 0;
28 }
29
30 vdso_init_from_sysinfo_ehdr(getauxval(AT_SYSINFO_EHDR));
31
32 /* Find gettimeofday. */
33 typedef long (*gtod_t)(struct timeval *tv, struct timezone *tz);
34 gtod_t gtod = (gtod_t)vdso_sym("LINUX_2.6", "__vdso_gettimeofday");
35
36 if (!gtod) {
37 printf("Could not find __vdso_gettimeofday\n");
38 return 1;
39 }
40
41 struct timeval tv;
42 long ret = gtod(&tv, 0);
43
44 if (ret == 0) {
45 printf("The time is %lld.%06lld\n",
46 (long long)tv.tv_sec, (long long)tv.tv_usec);
47 } else {
48 printf("__vdso_gettimeofday failed\n");
49 }
50
51 return 0;
52}
diff --git a/tools/testing/selftests/vm/.gitignore b/tools/testing/selftests/vm/.gitignore
index a937a9d26b60..142c565bb351 100644
--- a/tools/testing/selftests/vm/.gitignore
+++ b/tools/testing/selftests/vm/.gitignore
@@ -7,3 +7,4 @@ mlock2-tests
7on-fault-limit 7on-fault-limit
8transhuge-stress 8transhuge-stress
9userfaultfd 9userfaultfd
10mlock-intersect-test
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index e4bb1de1d526..bbab7f4664ac 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -10,6 +10,7 @@ BINARIES += on-fault-limit
10BINARIES += thuge-gen 10BINARIES += thuge-gen
11BINARIES += transhuge-stress 11BINARIES += transhuge-stress
12BINARIES += userfaultfd 12BINARIES += userfaultfd
13BINARIES += mlock-random-test
13 14
14all: $(BINARIES) 15all: $(BINARIES)
15%: %.c 16%: %.c
@@ -17,6 +18,9 @@ all: $(BINARIES)
17userfaultfd: userfaultfd.c ../../../../usr/include/linux/kernel.h 18userfaultfd: userfaultfd.c ../../../../usr/include/linux/kernel.h
18 $(CC) $(CFLAGS) -O2 -o $@ $< -lpthread 19 $(CC) $(CFLAGS) -O2 -o $@ $< -lpthread
19 20
21mlock-random-test: mlock-random-test.c
22 $(CC) $(CFLAGS) -o $@ $< -lcap
23
20../../../../usr/include/linux/kernel.h: 24../../../../usr/include/linux/kernel.h:
21 make -C ../../../.. headers_install 25 make -C ../../../.. headers_install
22 26
diff --git a/tools/testing/selftests/vm/compaction_test.c b/tools/testing/selftests/vm/compaction_test.c
index 932ff577ffc0..6d1437f895b8 100644
--- a/tools/testing/selftests/vm/compaction_test.c
+++ b/tools/testing/selftests/vm/compaction_test.c
@@ -101,7 +101,7 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
101 101
102 /* Start with the initial condition of 0 huge pages*/ 102 /* Start with the initial condition of 0 huge pages*/
103 if (write(fd, "0", sizeof(char)) != sizeof(char)) { 103 if (write(fd, "0", sizeof(char)) != sizeof(char)) {
104 perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); 104 perror("Failed to write 0 to /proc/sys/vm/nr_hugepages\n");
105 goto close_fd; 105 goto close_fd;
106 } 106 }
107 107
@@ -110,14 +110,14 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
110 /* Request a large number of huge pages. The Kernel will allocate 110 /* Request a large number of huge pages. The Kernel will allocate
111 as much as it can */ 111 as much as it can */
112 if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) { 112 if (write(fd, "100000", (6*sizeof(char))) != (6*sizeof(char))) {
113 perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); 113 perror("Failed to write 100000 to /proc/sys/vm/nr_hugepages\n");
114 goto close_fd; 114 goto close_fd;
115 } 115 }
116 116
117 lseek(fd, 0, SEEK_SET); 117 lseek(fd, 0, SEEK_SET);
118 118
119 if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) { 119 if (read(fd, nr_hugepages, sizeof(nr_hugepages)) <= 0) {
120 perror("Failed to read from /proc/sys/vm/nr_hugepages\n"); 120 perror("Failed to re-read from /proc/sys/vm/nr_hugepages\n");
121 goto close_fd; 121 goto close_fd;
122 } 122 }
123 123
@@ -136,9 +136,9 @@ int check_compaction(unsigned long mem_free, unsigned int hugepage_size)
136 printf("No of huge pages allocated = %d\n", 136 printf("No of huge pages allocated = %d\n",
137 (atoi(nr_hugepages))); 137 (atoi(nr_hugepages)));
138 138
139 if (write(fd, initial_nr_hugepages, sizeof(initial_nr_hugepages)) 139 if (write(fd, initial_nr_hugepages, strlen(initial_nr_hugepages))
140 != strlen(initial_nr_hugepages)) { 140 != strlen(initial_nr_hugepages)) {
141 perror("Failed to write to /proc/sys/vm/nr_hugepages\n"); 141 perror("Failed to write value to /proc/sys/vm/nr_hugepages\n");
142 goto close_fd; 142 goto close_fd;
143 } 143 }
144 144
diff --git a/tools/testing/selftests/vm/mlock-random-test.c b/tools/testing/selftests/vm/mlock-random-test.c
new file mode 100644
index 000000000000..83de4f58d262
--- /dev/null
+++ b/tools/testing/selftests/vm/mlock-random-test.c
@@ -0,0 +1,293 @@
1/*
2 * It tests the mlock/mlock2() when they are invoked
3 * on randomly memory region.
4 */
5#include <unistd.h>
6#include <sys/resource.h>
7#include <sys/capability.h>
8#include <sys/mman.h>
9#include <fcntl.h>
10#include <string.h>
11#include <sys/ipc.h>
12#include <sys/shm.h>
13#include <time.h>
14#include "mlock2.h"
15
16#define CHUNK_UNIT (128 * 1024)
17#define MLOCK_RLIMIT_SIZE (CHUNK_UNIT * 2)
18#define MLOCK_WITHIN_LIMIT_SIZE CHUNK_UNIT
19#define MLOCK_OUTOF_LIMIT_SIZE (CHUNK_UNIT * 3)
20
21#define TEST_LOOP 100
22#define PAGE_ALIGN(size, ps) (((size) + ((ps) - 1)) & ~((ps) - 1))
23
24int set_cap_limits(rlim_t max)
25{
26 struct rlimit new;
27 cap_t cap = cap_init();
28
29 new.rlim_cur = max;
30 new.rlim_max = max;
31 if (setrlimit(RLIMIT_MEMLOCK, &new)) {
32 perror("setrlimit() returns error\n");
33 return -1;
34 }
35
36 /* drop capabilities including CAP_IPC_LOCK */
37 if (cap_set_proc(cap)) {
38 perror("cap_set_proc() returns error\n");
39 return -2;
40 }
41
42 return 0;
43}
44
45int get_proc_locked_vm_size(void)
46{
47 FILE *f;
48 int ret = -1;
49 char line[1024] = {0};
50 unsigned long lock_size = 0;
51
52 f = fopen("/proc/self/status", "r");
53 if (!f) {
54 perror("fopen");
55 return -1;
56 }
57
58 while (fgets(line, 1024, f)) {
59 if (strstr(line, "VmLck")) {
60 ret = sscanf(line, "VmLck:\t%8lu kB", &lock_size);
61 if (ret <= 0) {
62 printf("sscanf() on VmLck error: %s: %d\n",
63 line, ret);
64 fclose(f);
65 return -1;
66 }
67 fclose(f);
68 return (int)(lock_size << 10);
69 }
70 }
71
72 perror("cann't parse VmLck in /proc/self/status\n");
73 fclose(f);
74 return -1;
75}
76
77/*
78 * Get the MMUPageSize of the memory region including input
79 * address from proc file.
80 *
81 * return value: on error case, 0 will be returned.
82 * Otherwise the page size(in bytes) is returned.
83 */
84int get_proc_page_size(unsigned long addr)
85{
86 FILE *smaps;
87 char *line;
88 unsigned long mmupage_size = 0;
89 size_t size;
90
91 smaps = seek_to_smaps_entry(addr);
92 if (!smaps) {
93 printf("Unable to parse /proc/self/smaps\n");
94 return 0;
95 }
96
97 while (getline(&line, &size, smaps) > 0) {
98 if (!strstr(line, "MMUPageSize")) {
99 free(line);
100 line = NULL;
101 size = 0;
102 continue;
103 }
104
105 /* found the MMUPageSize of this section */
106 if (sscanf(line, "MMUPageSize: %8lu kB",
107 &mmupage_size) < 1) {
108 printf("Unable to parse smaps entry for Size:%s\n",
109 line);
110 break;
111 }
112
113 }
114 free(line);
115 if (smaps)
116 fclose(smaps);
117 return mmupage_size << 10;
118}
119
120/*
121 * Test mlock/mlock2() on provided memory chunk.
122 * It expects the mlock/mlock2() to be successful (within rlimit)
123 *
124 * With allocated memory chunk [p, p + alloc_size), this
125 * test will choose start/len randomly to perform mlock/mlock2
126 * [start, start + len] memory range. The range is within range
127 * of the allocated chunk.
128 *
129 * The memory region size alloc_size is within the rlimit.
130 * So we always expect a success of mlock/mlock2.
131 *
132 * VmLck is assumed to be 0 before this test.
133 *
134 * return value: 0 - success
135 * else: failure
136 */
137int test_mlock_within_limit(char *p, int alloc_size)
138{
139 int i;
140 int ret = 0;
141 int locked_vm_size = 0;
142 struct rlimit cur;
143 int page_size = 0;
144
145 getrlimit(RLIMIT_MEMLOCK, &cur);
146 if (cur.rlim_cur < alloc_size) {
147 printf("alloc_size[%d] < %u rlimit,lead to mlock failure\n",
148 alloc_size, (unsigned int)cur.rlim_cur);
149 return -1;
150 }
151
152 srand(time(NULL));
153 for (i = 0; i < TEST_LOOP; i++) {
154 /*
155 * - choose mlock/mlock2 randomly
156 * - choose lock_size randomly but lock_size < alloc_size
157 * - choose start_offset randomly but p+start_offset+lock_size
158 * < p+alloc_size
159 */
160 int is_mlock = !!(rand() % 2);
161 int lock_size = rand() % alloc_size;
162 int start_offset = rand() % (alloc_size - lock_size);
163
164 if (is_mlock)
165 ret = mlock(p + start_offset, lock_size);
166 else
167 ret = mlock2_(p + start_offset, lock_size,
168 MLOCK_ONFAULT);
169
170 if (ret) {
171 printf("%s() failure at |%p(%d)| mlock:|%p(%d)|\n",
172 is_mlock ? "mlock" : "mlock2",
173 p, alloc_size,
174 p + start_offset, lock_size);
175 return ret;
176 }
177 }
178
179 /*
180 * Check VmLck left by the tests.
181 */
182 locked_vm_size = get_proc_locked_vm_size();
183 page_size = get_proc_page_size((unsigned long)p);
184 if (page_size == 0) {
185 printf("cannot get proc MMUPageSize\n");
186 return -1;
187 }
188
189 if (locked_vm_size > PAGE_ALIGN(alloc_size, page_size) + page_size) {
190 printf("test_mlock_within_limit() left VmLck:%d on %d chunk\n",
191 locked_vm_size, alloc_size);
192 return -1;
193 }
194
195 return 0;
196}
197
198
199/*
200 * We expect the mlock/mlock2() to be fail (outof limitation)
201 *
202 * With allocated memory chunk [p, p + alloc_size), this
203 * test will randomly choose start/len and perform mlock/mlock2
204 * on [start, start+len] range.
205 *
206 * The memory region size alloc_size is above the rlimit.
207 * And the len to be locked is higher than rlimit.
208 * So we always expect a failure of mlock/mlock2.
209 * No locked page number should be increased as a side effect.
210 *
211 * return value: 0 - success
212 * else: failure
213 */
214int test_mlock_outof_limit(char *p, int alloc_size)
215{
216 int i;
217 int ret = 0;
218 int locked_vm_size = 0, old_locked_vm_size = 0;
219 struct rlimit cur;
220
221 getrlimit(RLIMIT_MEMLOCK, &cur);
222 if (cur.rlim_cur >= alloc_size) {
223 printf("alloc_size[%d] >%u rlimit, violates test condition\n",
224 alloc_size, (unsigned int)cur.rlim_cur);
225 return -1;
226 }
227
228 old_locked_vm_size = get_proc_locked_vm_size();
229 srand(time(NULL));
230 for (i = 0; i < TEST_LOOP; i++) {
231 int is_mlock = !!(rand() % 2);
232 int lock_size = (rand() % (alloc_size - cur.rlim_cur))
233 + cur.rlim_cur;
234 int start_offset = rand() % (alloc_size - lock_size);
235
236 if (is_mlock)
237 ret = mlock(p + start_offset, lock_size);
238 else
239 ret = mlock2_(p + start_offset, lock_size,
240 MLOCK_ONFAULT);
241 if (ret == 0) {
242 printf("%s() succeeds? on %p(%d) mlock%p(%d)\n",
243 is_mlock ? "mlock" : "mlock2",
244 p, alloc_size,
245 p + start_offset, lock_size);
246 return -1;
247 }
248 }
249
250 locked_vm_size = get_proc_locked_vm_size();
251 if (locked_vm_size != old_locked_vm_size) {
252 printf("tests leads to new mlocked page: old[%d], new[%d]\n",
253 old_locked_vm_size,
254 locked_vm_size);
255 return -1;
256 }
257
258 return 0;
259}
260
261int main(int argc, char **argv)
262{
263 char *p = NULL;
264 int ret = 0;
265
266 if (set_cap_limits(MLOCK_RLIMIT_SIZE))
267 return -1;
268
269 p = malloc(MLOCK_WITHIN_LIMIT_SIZE);
270 if (p == NULL) {
271 perror("malloc() failure\n");
272 return -1;
273 }
274 ret = test_mlock_within_limit(p, MLOCK_WITHIN_LIMIT_SIZE);
275 if (ret)
276 return ret;
277 munlock(p, MLOCK_WITHIN_LIMIT_SIZE);
278 free(p);
279
280
281 p = malloc(MLOCK_OUTOF_LIMIT_SIZE);
282 if (p == NULL) {
283 perror("malloc() failure\n");
284 return -1;
285 }
286 ret = test_mlock_outof_limit(p, MLOCK_OUTOF_LIMIT_SIZE);
287 if (ret)
288 return ret;
289 munlock(p, MLOCK_OUTOF_LIMIT_SIZE);
290 free(p);
291
292 return 0;
293}
diff --git a/tools/testing/selftests/vm/mlock2-tests.c b/tools/testing/selftests/vm/mlock2-tests.c
index 02ca5e0177c5..ff0cda2b19c9 100644
--- a/tools/testing/selftests/vm/mlock2-tests.c
+++ b/tools/testing/selftests/vm/mlock2-tests.c
@@ -1,33 +1,12 @@
1#define _GNU_SOURCE 1#define _GNU_SOURCE
2#include <sys/mman.h> 2#include <sys/mman.h>
3#include <stdint.h> 3#include <stdint.h>
4#include <stdio.h>
5#include <stdlib.h>
6#include <unistd.h> 4#include <unistd.h>
7#include <string.h> 5#include <string.h>
8#include <sys/time.h> 6#include <sys/time.h>
9#include <sys/resource.h> 7#include <sys/resource.h>
10#include <syscall.h>
11#include <errno.h>
12#include <stdbool.h> 8#include <stdbool.h>
13 9#include "mlock2.h"
14#ifndef MLOCK_ONFAULT
15#define MLOCK_ONFAULT 1
16#endif
17
18#ifndef MCL_ONFAULT
19#define MCL_ONFAULT (MCL_FUTURE << 1)
20#endif
21
22static int mlock2_(void *start, size_t len, int flags)
23{
24#ifdef __NR_mlock2
25 return syscall(__NR_mlock2, start, len, flags);
26#else
27 errno = ENOSYS;
28 return -1;
29#endif
30}
31 10
32struct vm_boundaries { 11struct vm_boundaries {
33 unsigned long start; 12 unsigned long start;
@@ -138,46 +117,6 @@ static uint64_t get_kpageflags(unsigned long pfn)
138 return flags; 117 return flags;
139} 118}
140 119
141static FILE *seek_to_smaps_entry(unsigned long addr)
142{
143 FILE *file;
144 char *line = NULL;
145 size_t size = 0;
146 unsigned long start, end;
147 char perms[5];
148 unsigned long offset;
149 char dev[32];
150 unsigned long inode;
151 char path[BUFSIZ];
152
153 file = fopen("/proc/self/smaps", "r");
154 if (!file) {
155 perror("fopen smaps");
156 _exit(1);
157 }
158
159 while (getline(&line, &size, file) > 0) {
160 if (sscanf(line, "%lx-%lx %s %lx %s %lu %s\n",
161 &start, &end, perms, &offset, dev, &inode, path) < 6)
162 goto next;
163
164 if (start <= addr && addr < end)
165 goto out;
166
167next:
168 free(line);
169 line = NULL;
170 size = 0;
171 }
172
173 fclose(file);
174 file = NULL;
175
176out:
177 free(line);
178 return file;
179}
180
181#define VMFLAGS "VmFlags:" 120#define VMFLAGS "VmFlags:"
182 121
183static bool is_vmflag_set(unsigned long addr, const char *vmflag) 122static bool is_vmflag_set(unsigned long addr, const char *vmflag)
diff --git a/tools/testing/selftests/vm/mlock2.h b/tools/testing/selftests/vm/mlock2.h
new file mode 100644
index 000000000000..7ee062929d3e
--- /dev/null
+++ b/tools/testing/selftests/vm/mlock2.h
@@ -0,0 +1,62 @@
1#include <syscall.h>
2#include <errno.h>
3#include <stdio.h>
4#include <stdlib.h>
5
6#ifndef MLOCK_ONFAULT
7#define MLOCK_ONFAULT 1
8#endif
9
10#ifndef MCL_ONFAULT
11#define MCL_ONFAULT (MCL_FUTURE << 1)
12#endif
13
14static int mlock2_(void *start, size_t len, int flags)
15{
16#ifdef __NR_mlock2
17 return syscall(__NR_mlock2, start, len, flags);
18#else
19 errno = ENOSYS;
20 return -1;
21#endif
22}
23
24static FILE *seek_to_smaps_entry(unsigned long addr)
25{
26 FILE *file;
27 char *line = NULL;
28 size_t size = 0;
29 unsigned long start, end;
30 char perms[5];
31 unsigned long offset;
32 char dev[32];
33 unsigned long inode;
34 char path[BUFSIZ];
35
36 file = fopen("/proc/self/smaps", "r");
37 if (!file) {
38 perror("fopen smaps");
39 _exit(1);
40 }
41
42 while (getline(&line, &size, file) > 0) {
43 if (sscanf(line, "%lx-%lx %s %lx %s %lu %s\n",
44 &start, &end, perms, &offset, dev, &inode, path) < 6)
45 goto next;
46
47 if (start <= addr && addr < end)
48 goto out;
49
50next:
51 free(line);
52 line = NULL;
53 size = 0;
54 }
55
56 fclose(file);
57 file = NULL;
58
59out:
60 free(line);
61 return file;
62}
diff --git a/tools/testing/selftests/vm/on-fault-limit.c b/tools/testing/selftests/vm/on-fault-limit.c
index 245acccce42d..0ae458f32fdb 100644
--- a/tools/testing/selftests/vm/on-fault-limit.c
+++ b/tools/testing/selftests/vm/on-fault-limit.c
@@ -20,7 +20,7 @@ static int test_limit(void)
20 return ret; 20 return ret;
21 } 21 }
22 22
23 if (mlockall(MCL_CURRENT | MCL_ONFAULT | MCL_FUTURE)) { 23 if (mlockall(MCL_ONFAULT | MCL_FUTURE)) {
24 perror("mlockall"); 24 perror("mlockall");
25 return ret; 25 return ret;
26 } 26 }
diff --git a/tools/testing/selftests/watchdog/.gitignore b/tools/testing/selftests/watchdog/.gitignore
new file mode 100644
index 000000000000..5aac51575c7e
--- /dev/null
+++ b/tools/testing/selftests/watchdog/.gitignore
@@ -0,0 +1 @@
watchdog-test
diff --git a/tools/testing/selftests/watchdog/Makefile b/tools/testing/selftests/watchdog/Makefile
new file mode 100644
index 000000000000..f863c664e3d1
--- /dev/null
+++ b/tools/testing/selftests/watchdog/Makefile
@@ -0,0 +1,8 @@
1TEST_PROGS := watchdog-test
2
3all: $(TEST_PROGS)
4
5include ../lib.mk
6
7clean:
8 rm -fr $(TEST_PROGS)
diff --git a/tools/testing/selftests/watchdog/watchdog-test.c b/tools/testing/selftests/watchdog/watchdog-test.c
new file mode 100644
index 000000000000..6983d05097e2
--- /dev/null
+++ b/tools/testing/selftests/watchdog/watchdog-test.c
@@ -0,0 +1,105 @@
1/*
2 * Watchdog Driver Test Program
3 */
4
5#include <errno.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10#include <fcntl.h>
11#include <signal.h>
12#include <sys/ioctl.h>
13#include <linux/types.h>
14#include <linux/watchdog.h>
15
16int fd;
17const char v = 'V';
18
19/*
20 * This function simply sends an IOCTL to the driver, which in turn ticks
21 * the PC Watchdog card to reset its internal timer so it doesn't trigger
22 * a computer reset.
23 */
24static void keep_alive(void)
25{
26 int dummy;
27
28 printf(".");
29 ioctl(fd, WDIOC_KEEPALIVE, &dummy);
30}
31
32/*
33 * The main program. Run the program with "-d" to disable the card,
34 * or "-e" to enable the card.
35 */
36
37static void term(int sig)
38{
39 int ret = write(fd, &v, 1);
40
41 close(fd);
42 if (ret < 0)
43 printf("\nStopping watchdog ticks failed (%d)...\n", errno);
44 else
45 printf("\nStopping watchdog ticks...\n");
46 exit(0);
47}
48
49int main(int argc, char *argv[])
50{
51 int flags;
52 unsigned int ping_rate = 1;
53 int ret;
54
55 setbuf(stdout, NULL);
56
57 fd = open("/dev/watchdog", O_WRONLY);
58
59 if (fd == -1) {
60 printf("Watchdog device not enabled.\n");
61 exit(-1);
62 }
63
64 if (argc > 1) {
65 if (!strncasecmp(argv[1], "-d", 2)) {
66 flags = WDIOS_DISABLECARD;
67 ioctl(fd, WDIOC_SETOPTIONS, &flags);
68 printf("Watchdog card disabled.\n");
69 goto end;
70 } else if (!strncasecmp(argv[1], "-e", 2)) {
71 flags = WDIOS_ENABLECARD;
72 ioctl(fd, WDIOC_SETOPTIONS, &flags);
73 printf("Watchdog card enabled.\n");
74 goto end;
75 } else if (!strncasecmp(argv[1], "-t", 2) && argv[2]) {
76 flags = atoi(argv[2]);
77 ioctl(fd, WDIOC_SETTIMEOUT, &flags);
78 printf("Watchdog timeout set to %u seconds.\n", flags);
79 goto end;
80 } else if (!strncasecmp(argv[1], "-p", 2) && argv[2]) {
81 ping_rate = strtoul(argv[2], NULL, 0);
82 printf("Watchdog ping rate set to %u seconds.\n", ping_rate);
83 } else {
84 printf("-d to disable, -e to enable, -t <n> to set " \
85 "the timeout,\n-p <n> to set the ping rate, and \n");
86 printf("run by itself to tick the card.\n");
87 goto end;
88 }
89 }
90
91 printf("Watchdog Ticking Away!\n");
92
93 signal(SIGINT, term);
94
95 while(1) {
96 keep_alive();
97 sleep(ping_rate);
98 }
99end:
100 ret = write(fd, &v, 1);
101 if (ret < 0)
102 printf("Stopping watchdog ticks failed (%d)...\n", errno);
103 close(fd);
104 return 0;
105}
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index c73425de3cfe..a89f80a5b711 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -4,8 +4,9 @@ include ../lib.mk
4 4
5.PHONY: all all_32 all_64 warn_32bit_failure clean 5.PHONY: all all_32 all_64 warn_32bit_failure clean
6 6
7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall \ 7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \
8 check_initial_reg_state sigreturn ldt_gdt iopl 8 check_initial_reg_state sigreturn ldt_gdt iopl \
9 protection_keys
9TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ 10TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
10 test_FCMOV test_FCOMI test_FISTTP \ 11 test_FCMOV test_FCOMI test_FISTTP \
11 vdso_restorer 12 vdso_restorer
diff --git a/tools/testing/selftests/x86/mpx-debug.h b/tools/testing/selftests/x86/mpx-debug.h
new file mode 100644
index 000000000000..9230981f2e12
--- /dev/null
+++ b/tools/testing/selftests/x86/mpx-debug.h
@@ -0,0 +1,14 @@
1#ifndef _MPX_DEBUG_H
2#define _MPX_DEBUG_H
3
4#ifndef DEBUG_LEVEL
5#define DEBUG_LEVEL 0
6#endif
7#define dprintf_level(level, args...) do { if(level <= DEBUG_LEVEL) printf(args); } while(0)
8#define dprintf1(args...) dprintf_level(1, args)
9#define dprintf2(args...) dprintf_level(2, args)
10#define dprintf3(args...) dprintf_level(3, args)
11#define dprintf4(args...) dprintf_level(4, args)
12#define dprintf5(args...) dprintf_level(5, args)
13
14#endif /* _MPX_DEBUG_H */
diff --git a/tools/testing/selftests/x86/mpx-dig.c b/tools/testing/selftests/x86/mpx-dig.c
new file mode 100644
index 000000000000..ce85356d7e2e
--- /dev/null
+++ b/tools/testing/selftests/x86/mpx-dig.c
@@ -0,0 +1,498 @@
1/*
2 * Written by Dave Hansen <dave.hansen@intel.com>
3 */
4
5#include <stdlib.h>
6#include <sys/types.h>
7#include <unistd.h>
8#include <stdio.h>
9#include <errno.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <unistd.h>
13#include <sys/mman.h>
14#include <string.h>
15#include <fcntl.h>
16#include "mpx-debug.h"
17#include "mpx-mm.h"
18#include "mpx-hw.h"
19
20unsigned long bounds_dir_global;
21
22#define mpx_dig_abort() __mpx_dig_abort(__FILE__, __func__, __LINE__)
23static void inline __mpx_dig_abort(const char *file, const char *func, int line)
24{
25 fprintf(stderr, "MPX dig abort @ %s::%d in %s()\n", file, line, func);
26 printf("MPX dig abort @ %s::%d in %s()\n", file, line, func);
27 abort();
28}
29
30/*
31 * run like this (BDIR finds the probably bounds directory):
32 *
33 * BDIR="$(cat /proc/$pid/smaps | grep -B1 2097152 \
34 * | head -1 | awk -F- '{print $1}')";
35 * ./mpx-dig $pid 0x$BDIR
36 *
37 * NOTE:
38 * assumes that the only 2097152-kb VMA is the bounds dir
39 */
40
41long nr_incore(void *ptr, unsigned long size_bytes)
42{
43 int i;
44 long ret = 0;
45 long vec_len = size_bytes / PAGE_SIZE;
46 unsigned char *vec = malloc(vec_len);
47 int incore_ret;
48
49 if (!vec)
50 mpx_dig_abort();
51
52 incore_ret = mincore(ptr, size_bytes, vec);
53 if (incore_ret) {
54 printf("mincore ret: %d\n", incore_ret);
55 perror("mincore");
56 mpx_dig_abort();
57 }
58 for (i = 0; i < vec_len; i++)
59 ret += vec[i];
60 free(vec);
61 return ret;
62}
63
64int open_proc(int pid, char *file)
65{
66 static char buf[100];
67 int fd;
68
69 snprintf(&buf[0], sizeof(buf), "/proc/%d/%s", pid, file);
70 fd = open(&buf[0], O_RDONLY);
71 if (fd < 0)
72 perror(buf);
73
74 return fd;
75}
76
77struct vaddr_range {
78 unsigned long start;
79 unsigned long end;
80};
81struct vaddr_range *ranges;
82int nr_ranges_allocated;
83int nr_ranges_populated;
84int last_range = -1;
85
86int __pid_load_vaddrs(int pid)
87{
88 int ret = 0;
89 int proc_maps_fd = open_proc(pid, "maps");
90 char linebuf[10000];
91 unsigned long start;
92 unsigned long end;
93 char rest[1000];
94 FILE *f = fdopen(proc_maps_fd, "r");
95
96 if (!f)
97 mpx_dig_abort();
98 nr_ranges_populated = 0;
99 while (!feof(f)) {
100 char *readret = fgets(linebuf, sizeof(linebuf), f);
101 int parsed;
102
103 if (readret == NULL) {
104 if (feof(f))
105 break;
106 mpx_dig_abort();
107 }
108
109 parsed = sscanf(linebuf, "%lx-%lx%s", &start, &end, rest);
110 if (parsed != 3)
111 mpx_dig_abort();
112
113 dprintf4("result[%d]: %lx-%lx<->%s\n", parsed, start, end, rest);
114 if (nr_ranges_populated >= nr_ranges_allocated) {
115 ret = -E2BIG;
116 break;
117 }
118 ranges[nr_ranges_populated].start = start;
119 ranges[nr_ranges_populated].end = end;
120 nr_ranges_populated++;
121 }
122 last_range = -1;
123 fclose(f);
124 close(proc_maps_fd);
125 return ret;
126}
127
128int pid_load_vaddrs(int pid)
129{
130 int ret;
131
132 dprintf2("%s(%d)\n", __func__, pid);
133 if (!ranges) {
134 nr_ranges_allocated = 4;
135 ranges = malloc(nr_ranges_allocated * sizeof(ranges[0]));
136 dprintf2("%s(%d) allocated %d ranges @ %p\n", __func__, pid,
137 nr_ranges_allocated, ranges);
138 assert(ranges != NULL);
139 }
140 do {
141 ret = __pid_load_vaddrs(pid);
142 if (!ret)
143 break;
144 if (ret == -E2BIG) {
145 dprintf2("%s(%d) need to realloc\n", __func__, pid);
146 nr_ranges_allocated *= 2;
147 ranges = realloc(ranges,
148 nr_ranges_allocated * sizeof(ranges[0]));
149 dprintf2("%s(%d) allocated %d ranges @ %p\n", __func__,
150 pid, nr_ranges_allocated, ranges);
151 assert(ranges != NULL);
152 dprintf1("reallocating to hold %d ranges\n", nr_ranges_allocated);
153 }
154 } while (1);
155
156 dprintf2("%s(%d) done\n", __func__, pid);
157
158 return ret;
159}
160
161static inline int vaddr_in_range(unsigned long vaddr, struct vaddr_range *r)
162{
163 if (vaddr < r->start)
164 return 0;
165 if (vaddr >= r->end)
166 return 0;
167 return 1;
168}
169
170static inline int vaddr_mapped_by_range(unsigned long vaddr)
171{
172 int i;
173
174 if (last_range > 0 && vaddr_in_range(vaddr, &ranges[last_range]))
175 return 1;
176
177 for (i = 0; i < nr_ranges_populated; i++) {
178 struct vaddr_range *r = &ranges[i];
179
180 if (vaddr_in_range(vaddr, r))
181 continue;
182 last_range = i;
183 return 1;
184 }
185 return 0;
186}
187
188const int bt_entry_size_bytes = sizeof(unsigned long) * 4;
189
190void *read_bounds_table_into_buf(unsigned long table_vaddr)
191{
192#ifdef MPX_DIG_STANDALONE
193 static char bt_buf[MPX_BOUNDS_TABLE_SIZE_BYTES];
194 off_t seek_ret = lseek(fd, table_vaddr, SEEK_SET);
195 if (seek_ret != table_vaddr)
196 mpx_dig_abort();
197
198 int read_ret = read(fd, &bt_buf, sizeof(bt_buf));
199 if (read_ret != sizeof(bt_buf))
200 mpx_dig_abort();
201 return &bt_buf;
202#else
203 return (void *)table_vaddr;
204#endif
205}
206
207int dump_table(unsigned long table_vaddr, unsigned long base_controlled_vaddr,
208 unsigned long bde_vaddr)
209{
210 unsigned long offset_inside_bt;
211 int nr_entries = 0;
212 int do_abort = 0;
213 char *bt_buf;
214
215 dprintf3("%s() base_controlled_vaddr: 0x%012lx bde_vaddr: 0x%012lx\n",
216 __func__, base_controlled_vaddr, bde_vaddr);
217
218 bt_buf = read_bounds_table_into_buf(table_vaddr);
219
220 dprintf4("%s() read done\n", __func__);
221
222 for (offset_inside_bt = 0;
223 offset_inside_bt < MPX_BOUNDS_TABLE_SIZE_BYTES;
224 offset_inside_bt += bt_entry_size_bytes) {
225 unsigned long bt_entry_index;
226 unsigned long bt_entry_controls;
227 unsigned long this_bt_entry_for_vaddr;
228 unsigned long *bt_entry_buf;
229 int i;
230
231 dprintf4("%s() offset_inside_bt: 0x%lx of 0x%llx\n", __func__,
232 offset_inside_bt, MPX_BOUNDS_TABLE_SIZE_BYTES);
233 bt_entry_buf = (void *)&bt_buf[offset_inside_bt];
234 if (!bt_buf) {
235 printf("null bt_buf\n");
236 mpx_dig_abort();
237 }
238 if (!bt_entry_buf) {
239 printf("null bt_entry_buf\n");
240 mpx_dig_abort();
241 }
242 dprintf4("%s() reading *bt_entry_buf @ %p\n", __func__,
243 bt_entry_buf);
244 if (!bt_entry_buf[0] &&
245 !bt_entry_buf[1] &&
246 !bt_entry_buf[2] &&
247 !bt_entry_buf[3])
248 continue;
249
250 nr_entries++;
251
252 bt_entry_index = offset_inside_bt/bt_entry_size_bytes;
253 bt_entry_controls = sizeof(void *);
254 this_bt_entry_for_vaddr =
255 base_controlled_vaddr + bt_entry_index*bt_entry_controls;
256 /*
257 * We sign extend vaddr bits 48->63 which effectively
258 * creates a hole in the virtual address space.
259 * This calculation corrects for the hole.
260 */
261 if (this_bt_entry_for_vaddr > 0x00007fffffffffffUL)
262 this_bt_entry_for_vaddr |= 0xffff800000000000;
263
264 if (!vaddr_mapped_by_range(this_bt_entry_for_vaddr)) {
265 printf("bt_entry_buf: %p\n", bt_entry_buf);
266 printf("there is a bte for %lx but no mapping\n",
267 this_bt_entry_for_vaddr);
268 printf(" bde vaddr: %016lx\n", bde_vaddr);
269 printf("base_controlled_vaddr: %016lx\n", base_controlled_vaddr);
270 printf(" table_vaddr: %016lx\n", table_vaddr);
271 printf(" entry vaddr: %016lx @ offset %lx\n",
272 table_vaddr + offset_inside_bt, offset_inside_bt);
273 do_abort = 1;
274 mpx_dig_abort();
275 }
276 if (DEBUG_LEVEL < 4)
277 continue;
278
279 printf("table entry[%lx]: ", offset_inside_bt);
280 for (i = 0; i < bt_entry_size_bytes; i += sizeof(unsigned long))
281 printf("0x%016lx ", bt_entry_buf[i]);
282 printf("\n");
283 }
284 if (do_abort)
285 mpx_dig_abort();
286 dprintf4("%s() done\n", __func__);
287 return nr_entries;
288}
289
290int search_bd_buf(char *buf, int len_bytes, unsigned long bd_offset_bytes,
291 int *nr_populated_bdes)
292{
293 unsigned long i;
294 int total_entries = 0;
295
296 dprintf3("%s(%p, %x, %lx, ...) buf end: %p\n", __func__, buf,
297 len_bytes, bd_offset_bytes, buf + len_bytes);
298
299 for (i = 0; i < len_bytes; i += sizeof(unsigned long)) {
300 unsigned long bd_index = (bd_offset_bytes + i) / sizeof(unsigned long);
301 unsigned long *bounds_dir_entry_ptr = (unsigned long *)&buf[i];
302 unsigned long bounds_dir_entry;
303 unsigned long bd_for_vaddr;
304 unsigned long bt_start;
305 unsigned long bt_tail;
306 int nr_entries;
307
308 dprintf4("%s() loop i: %ld bounds_dir_entry_ptr: %p\n", __func__, i,
309 bounds_dir_entry_ptr);
310
311 bounds_dir_entry = *bounds_dir_entry_ptr;
312 if (!bounds_dir_entry) {
313 dprintf4("no bounds dir at index 0x%lx / 0x%lx "
314 "start at offset:%lx %lx\n", bd_index, bd_index,
315 bd_offset_bytes, i);
316 continue;
317 }
318 dprintf3("found bounds_dir_entry: 0x%lx @ "
319 "index 0x%lx buf ptr: %p\n", bounds_dir_entry, i,
320 &buf[i]);
321 /* mask off the enable bit: */
322 bounds_dir_entry &= ~0x1;
323 (*nr_populated_bdes)++;
324 dprintf4("nr_populated_bdes: %p\n", nr_populated_bdes);
325 dprintf4("*nr_populated_bdes: %d\n", *nr_populated_bdes);
326
327 bt_start = bounds_dir_entry;
328 bt_tail = bounds_dir_entry + MPX_BOUNDS_TABLE_SIZE_BYTES - 1;
329 if (!vaddr_mapped_by_range(bt_start)) {
330 printf("bounds directory 0x%lx points to nowhere\n",
331 bounds_dir_entry);
332 mpx_dig_abort();
333 }
334 if (!vaddr_mapped_by_range(bt_tail)) {
335 printf("bounds directory end 0x%lx points to nowhere\n",
336 bt_tail);
337 mpx_dig_abort();
338 }
339 /*
340 * Each bounds directory entry controls 1MB of virtual address
341 * space. This variable is the virtual address in the process
342 * of the beginning of the area controlled by this bounds_dir.
343 */
344 bd_for_vaddr = bd_index * (1UL<<20);
345
346 nr_entries = dump_table(bounds_dir_entry, bd_for_vaddr,
347 bounds_dir_global+bd_offset_bytes+i);
348 total_entries += nr_entries;
349 dprintf5("dir entry[%4ld @ %p]: 0x%lx %6d entries "
350 "total this buf: %7d bd_for_vaddrs: 0x%lx -> 0x%lx\n",
351 bd_index, buf+i,
352 bounds_dir_entry, nr_entries, total_entries,
353 bd_for_vaddr, bd_for_vaddr + (1UL<<20));
354 }
355 dprintf3("%s(%p, %x, %lx, ...) done\n", __func__, buf, len_bytes,
356 bd_offset_bytes);
357 return total_entries;
358}
359
360int proc_pid_mem_fd = -1;
361
362void *fill_bounds_dir_buf_other(long byte_offset_inside_bounds_dir,
363 long buffer_size_bytes, void *buffer)
364{
365 unsigned long seekto = bounds_dir_global + byte_offset_inside_bounds_dir;
366 int read_ret;
367 off_t seek_ret = lseek(proc_pid_mem_fd, seekto, SEEK_SET);
368
369 if (seek_ret != seekto)
370 mpx_dig_abort();
371
372 read_ret = read(proc_pid_mem_fd, buffer, buffer_size_bytes);
373 /* there shouldn't practically be short reads of /proc/$pid/mem */
374 if (read_ret != buffer_size_bytes)
375 mpx_dig_abort();
376
377 return buffer;
378}
379void *fill_bounds_dir_buf_self(long byte_offset_inside_bounds_dir,
380 long buffer_size_bytes, void *buffer)
381
382{
383 unsigned char vec[buffer_size_bytes / PAGE_SIZE];
384 char *dig_bounds_dir_ptr =
385 (void *)(bounds_dir_global + byte_offset_inside_bounds_dir);
386 /*
387 * use mincore() to quickly find the areas of the bounds directory
388 * that have memory and thus will be worth scanning.
389 */
390 int incore_ret;
391
392 int incore = 0;
393 int i;
394
395 dprintf4("%s() dig_bounds_dir_ptr: %p\n", __func__, dig_bounds_dir_ptr);
396
397 incore_ret = mincore(dig_bounds_dir_ptr, buffer_size_bytes, &vec[0]);
398 if (incore_ret) {
399 printf("mincore ret: %d\n", incore_ret);
400 perror("mincore");
401 mpx_dig_abort();
402 }
403 for (i = 0; i < sizeof(vec); i++)
404 incore += vec[i];
405 dprintf4("%s() total incore: %d\n", __func__, incore);
406 if (!incore)
407 return NULL;
408 dprintf3("%s() total incore: %d\n", __func__, incore);
409 return dig_bounds_dir_ptr;
410}
411
412int inspect_pid(int pid)
413{
414 static int dig_nr;
415 long offset_inside_bounds_dir;
416 char bounds_dir_buf[sizeof(unsigned long) * (1UL << 15)];
417 char *dig_bounds_dir_ptr;
418 int total_entries = 0;
419 int nr_populated_bdes = 0;
420 int inspect_self;
421
422 if (getpid() == pid) {
423 dprintf4("inspecting self\n");
424 inspect_self = 1;
425 } else {
426 dprintf4("inspecting pid %d\n", pid);
427 mpx_dig_abort();
428 }
429
430 for (offset_inside_bounds_dir = 0;
431 offset_inside_bounds_dir < MPX_BOUNDS_TABLE_SIZE_BYTES;
432 offset_inside_bounds_dir += sizeof(bounds_dir_buf)) {
433 static int bufs_skipped;
434 int this_entries;
435
436 if (inspect_self) {
437 dig_bounds_dir_ptr =
438 fill_bounds_dir_buf_self(offset_inside_bounds_dir,
439 sizeof(bounds_dir_buf),
440 &bounds_dir_buf[0]);
441 } else {
442 dig_bounds_dir_ptr =
443 fill_bounds_dir_buf_other(offset_inside_bounds_dir,
444 sizeof(bounds_dir_buf),
445 &bounds_dir_buf[0]);
446 }
447 if (!dig_bounds_dir_ptr) {
448 bufs_skipped++;
449 continue;
450 }
451 this_entries = search_bd_buf(dig_bounds_dir_ptr,
452 sizeof(bounds_dir_buf),
453 offset_inside_bounds_dir,
454 &nr_populated_bdes);
455 total_entries += this_entries;
456 }
457 printf("mpx dig (%3d) complete, SUCCESS (%8d / %4d)\n", ++dig_nr,
458 total_entries, nr_populated_bdes);
459 return total_entries + nr_populated_bdes;
460}
461
462#ifdef MPX_DIG_REMOTE
463int main(int argc, char **argv)
464{
465 int err;
466 char *c;
467 unsigned long bounds_dir_entry;
468 int pid;
469
470 printf("mpx-dig starting...\n");
471 err = sscanf(argv[1], "%d", &pid);
472 printf("parsing: '%s', err: %d\n", argv[1], err);
473 if (err != 1)
474 mpx_dig_abort();
475
476 err = sscanf(argv[2], "%lx", &bounds_dir_global);
477 printf("parsing: '%s': %d\n", argv[2], err);
478 if (err != 1)
479 mpx_dig_abort();
480
481 proc_pid_mem_fd = open_proc(pid, "mem");
482 if (proc_pid_mem_fd < 0)
483 mpx_dig_abort();
484
485 inspect_pid(pid);
486 return 0;
487}
488#endif
489
490long inspect_me(struct mpx_bounds_dir *bounds_dir)
491{
492 int pid = getpid();
493
494 pid_load_vaddrs(pid);
495 bounds_dir_global = (unsigned long)bounds_dir;
496 dprintf4("enter %s() bounds dir: %p\n", __func__, bounds_dir);
497 return inspect_pid(pid);
498}
diff --git a/tools/testing/selftests/x86/mpx-hw.h b/tools/testing/selftests/x86/mpx-hw.h
new file mode 100644
index 000000000000..093c190178a9
--- /dev/null
+++ b/tools/testing/selftests/x86/mpx-hw.h
@@ -0,0 +1,123 @@
1#ifndef _MPX_HW_H
2#define _MPX_HW_H
3
4#include <assert.h>
5
6/* Describe the MPX Hardware Layout in here */
7
8#define NR_MPX_BOUNDS_REGISTERS 4
9
10#ifdef __i386__
11
12#define MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES 16 /* 4 * 32-bits */
13#define MPX_BOUNDS_TABLE_SIZE_BYTES (1ULL << 14) /* 16k */
14#define MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES 4
15#define MPX_BOUNDS_DIR_SIZE_BYTES (1ULL << 22) /* 4MB */
16
17#define MPX_BOUNDS_TABLE_BOTTOM_BIT 2
18#define MPX_BOUNDS_TABLE_TOP_BIT 11
19#define MPX_BOUNDS_DIR_BOTTOM_BIT 12
20#define MPX_BOUNDS_DIR_TOP_BIT 31
21
22#else
23
24/*
25 * Linear Address of "pointer" (LAp)
26 * 0 -> 2: ignored
27 * 3 -> 19: index in to bounds table
28 * 20 -> 47: index in to bounds directory
29 * 48 -> 63: ignored
30 */
31
32#define MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES 32
33#define MPX_BOUNDS_TABLE_SIZE_BYTES (1ULL << 22) /* 4MB */
34#define MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES 8
35#define MPX_BOUNDS_DIR_SIZE_BYTES (1ULL << 31) /* 2GB */
36
37#define MPX_BOUNDS_TABLE_BOTTOM_BIT 3
38#define MPX_BOUNDS_TABLE_TOP_BIT 19
39#define MPX_BOUNDS_DIR_BOTTOM_BIT 20
40#define MPX_BOUNDS_DIR_TOP_BIT 47
41
42#endif
43
44#define MPX_BOUNDS_DIR_NR_ENTRIES \
45 (MPX_BOUNDS_DIR_SIZE_BYTES/MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES)
46#define MPX_BOUNDS_TABLE_NR_ENTRIES \
47 (MPX_BOUNDS_TABLE_SIZE_BYTES/MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES)
48
49#define MPX_BOUNDS_TABLE_ENTRY_VALID_BIT 0x1
50
51struct mpx_bd_entry {
52 union {
53 char x[MPX_BOUNDS_DIR_ENTRY_SIZE_BYTES];
54 void *contents[1];
55 };
56} __attribute__((packed));
57
58struct mpx_bt_entry {
59 union {
60 char x[MPX_BOUNDS_TABLE_ENTRY_SIZE_BYTES];
61 unsigned long contents[1];
62 };
63} __attribute__((packed));
64
65struct mpx_bounds_dir {
66 struct mpx_bd_entry entries[MPX_BOUNDS_DIR_NR_ENTRIES];
67} __attribute__((packed));
68
69struct mpx_bounds_table {
70 struct mpx_bt_entry entries[MPX_BOUNDS_TABLE_NR_ENTRIES];
71} __attribute__((packed));
72
73static inline unsigned long GET_BITS(unsigned long val, int bottombit, int topbit)
74{
75 int total_nr_bits = topbit - bottombit;
76 unsigned long mask = (1UL << total_nr_bits)-1;
77 return (val >> bottombit) & mask;
78}
79
80static inline unsigned long __vaddr_bounds_table_index(void *vaddr)
81{
82 return GET_BITS((unsigned long)vaddr, MPX_BOUNDS_TABLE_BOTTOM_BIT,
83 MPX_BOUNDS_TABLE_TOP_BIT);
84}
85
86static inline unsigned long __vaddr_bounds_directory_index(void *vaddr)
87{
88 return GET_BITS((unsigned long)vaddr, MPX_BOUNDS_DIR_BOTTOM_BIT,
89 MPX_BOUNDS_DIR_TOP_BIT);
90}
91
92static inline struct mpx_bd_entry *mpx_vaddr_to_bd_entry(void *vaddr,
93 struct mpx_bounds_dir *bounds_dir)
94{
95 unsigned long index = __vaddr_bounds_directory_index(vaddr);
96 return &bounds_dir->entries[index];
97}
98
99static inline int bd_entry_valid(struct mpx_bd_entry *bounds_dir_entry)
100{
101 unsigned long __bd_entry = (unsigned long)bounds_dir_entry->contents;
102 return (__bd_entry & MPX_BOUNDS_TABLE_ENTRY_VALID_BIT);
103}
104
105static inline struct mpx_bounds_table *
106__bd_entry_to_bounds_table(struct mpx_bd_entry *bounds_dir_entry)
107{
108 unsigned long __bd_entry = (unsigned long)bounds_dir_entry->contents;
109 assert(__bd_entry & MPX_BOUNDS_TABLE_ENTRY_VALID_BIT);
110 __bd_entry &= ~MPX_BOUNDS_TABLE_ENTRY_VALID_BIT;
111 return (struct mpx_bounds_table *)__bd_entry;
112}
113
114static inline struct mpx_bt_entry *
115mpx_vaddr_to_bt_entry(void *vaddr, struct mpx_bounds_dir *bounds_dir)
116{
117 struct mpx_bd_entry *bde = mpx_vaddr_to_bd_entry(vaddr, bounds_dir);
118 struct mpx_bounds_table *bt = __bd_entry_to_bounds_table(bde);
119 unsigned long index = __vaddr_bounds_table_index(vaddr);
120 return &bt->entries[index];
121}
122
123#endif /* _MPX_HW_H */
diff --git a/tools/testing/selftests/x86/mpx-mini-test.c b/tools/testing/selftests/x86/mpx-mini-test.c
new file mode 100644
index 000000000000..616ee9673339
--- /dev/null
+++ b/tools/testing/selftests/x86/mpx-mini-test.c
@@ -0,0 +1,1585 @@
1/*
2 * mpx-mini-test.c: routines to test Intel MPX (Memory Protection eXtentions)
3 *
4 * Written by:
5 * "Ren, Qiaowei" <qiaowei.ren@intel.com>
6 * "Wei, Gang" <gang.wei@intel.com>
7 * "Hansen, Dave" <dave.hansen@intel.com>
8 *
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms and conditions of the GNU General Public License,
11 * version 2.
12 */
13
14/*
15 * 2014-12-05: Dave Hansen: fixed all of the compiler warnings, and made sure
16 * it works on 32-bit.
17 */
18
19int inspect_every_this_many_mallocs = 100;
20int zap_all_every_this_many_mallocs = 1000;
21
22#define _GNU_SOURCE
23#define _LARGEFILE64_SOURCE
24
25#include <string.h>
26#include <stdio.h>
27#include <stdint.h>
28#include <stdbool.h>
29#include <signal.h>
30#include <assert.h>
31#include <stdlib.h>
32#include <ucontext.h>
33#include <sys/mman.h>
34#include <sys/types.h>
35#include <sys/stat.h>
36#include <fcntl.h>
37#include <unistd.h>
38
39#include "mpx-hw.h"
40#include "mpx-debug.h"
41#include "mpx-mm.h"
42
43#ifndef __always_inline
44#define __always_inline inline __attribute__((always_inline)
45#endif
46
47#ifndef TEST_DURATION_SECS
48#define TEST_DURATION_SECS 3
49#endif
50
51void write_int_to(char *prefix, char *file, int int_to_write)
52{
53 char buf[100];
54 int fd = open(file, O_RDWR);
55 int len;
56 int ret;
57
58 assert(fd >= 0);
59 len = snprintf(buf, sizeof(buf), "%s%d", prefix, int_to_write);
60 assert(len >= 0);
61 assert(len < sizeof(buf));
62 ret = write(fd, buf, len);
63 assert(ret == len);
64 ret = close(fd);
65 assert(!ret);
66}
67
68void write_pid_to(char *prefix, char *file)
69{
70 write_int_to(prefix, file, getpid());
71}
72
73void trace_me(void)
74{
75/* tracing events dir */
76#define TED "/sys/kernel/debug/tracing/events/"
77/*
78 write_pid_to("common_pid=", TED "signal/filter");
79 write_pid_to("common_pid=", TED "exceptions/filter");
80 write_int_to("", TED "signal/enable", 1);
81 write_int_to("", TED "exceptions/enable", 1);
82*/
83 write_pid_to("", "/sys/kernel/debug/tracing/set_ftrace_pid");
84 write_int_to("", "/sys/kernel/debug/tracing/trace", 0);
85}
86
87#define test_failed() __test_failed(__FILE__, __LINE__)
88static void __test_failed(char *f, int l)
89{
90 fprintf(stderr, "abort @ %s::%d\n", f, l);
91 abort();
92}
93
94/* Error Printf */
95#define eprintf(args...) fprintf(stderr, args)
96
97#ifdef __i386__
98
99/* i386 directory size is 4MB */
100#define REG_IP_IDX REG_EIP
101#define REX_PREFIX
102
103#define XSAVE_OFFSET_IN_FPMEM sizeof(struct _libc_fpstate)
104
105/*
106 * __cpuid() is from the Linux Kernel:
107 */
108static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
109 unsigned int *ecx, unsigned int *edx)
110{
111 /* ecx is often an input as well as an output. */
112 asm volatile(
113 "push %%ebx;"
114 "cpuid;"
115 "mov %%ebx, %1;"
116 "pop %%ebx"
117 : "=a" (*eax),
118 "=g" (*ebx),
119 "=c" (*ecx),
120 "=d" (*edx)
121 : "0" (*eax), "2" (*ecx));
122}
123
124#else /* __i386__ */
125
126#define REG_IP_IDX REG_RIP
127#define REX_PREFIX "0x48, "
128
129#define XSAVE_OFFSET_IN_FPMEM 0
130
131/*
132 * __cpuid() is from the Linux Kernel:
133 */
134static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
135 unsigned int *ecx, unsigned int *edx)
136{
137 /* ecx is often an input as well as an output. */
138 asm volatile(
139 "cpuid;"
140 : "=a" (*eax),
141 "=b" (*ebx),
142 "=c" (*ecx),
143 "=d" (*edx)
144 : "0" (*eax), "2" (*ecx));
145}
146
147#endif /* !__i386__ */
148
149struct xsave_hdr_struct {
150 uint64_t xstate_bv;
151 uint64_t reserved1[2];
152 uint64_t reserved2[5];
153} __attribute__((packed));
154
155struct bndregs_struct {
156 uint64_t bndregs[8];
157} __attribute__((packed));
158
159struct bndcsr_struct {
160 uint64_t cfg_reg_u;
161 uint64_t status_reg;
162} __attribute__((packed));
163
164struct xsave_struct {
165 uint8_t fpu_sse[512];
166 struct xsave_hdr_struct xsave_hdr;
167 uint8_t ymm[256];
168 uint8_t lwp[128];
169 struct bndregs_struct bndregs;
170 struct bndcsr_struct bndcsr;
171} __attribute__((packed));
172
173uint8_t __attribute__((__aligned__(64))) buffer[4096];
174struct xsave_struct *xsave_buf = (struct xsave_struct *)buffer;
175
176uint8_t __attribute__((__aligned__(64))) test_buffer[4096];
177struct xsave_struct *xsave_test_buf = (struct xsave_struct *)test_buffer;
178
179uint64_t num_bnd_chk;
180
181static __always_inline void xrstor_state(struct xsave_struct *fx, uint64_t mask)
182{
183 uint32_t lmask = mask;
184 uint32_t hmask = mask >> 32;
185
186 asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x2f\n\t"
187 : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
188 : "memory");
189}
190
191static __always_inline void xsave_state_1(void *_fx, uint64_t mask)
192{
193 uint32_t lmask = mask;
194 uint32_t hmask = mask >> 32;
195 unsigned char *fx = _fx;
196
197 asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
198 : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
199 : "memory");
200}
201
202static inline uint64_t xgetbv(uint32_t index)
203{
204 uint32_t eax, edx;
205
206 asm volatile(".byte 0x0f,0x01,0xd0" /* xgetbv */
207 : "=a" (eax), "=d" (edx)
208 : "c" (index));
209 return eax + ((uint64_t)edx << 32);
210}
211
212static uint64_t read_mpx_status_sig(ucontext_t *uctxt)
213{
214 memset(buffer, 0, sizeof(buffer));
215 memcpy(buffer,
216 (uint8_t *)uctxt->uc_mcontext.fpregs + XSAVE_OFFSET_IN_FPMEM,
217 sizeof(struct xsave_struct));
218
219 return xsave_buf->bndcsr.status_reg;
220}
221
222#include <pthread.h>
223
224static uint8_t *get_next_inst_ip(uint8_t *addr)
225{
226 uint8_t *ip = addr;
227 uint8_t sib;
228 uint8_t rm;
229 uint8_t mod;
230 uint8_t base;
231 uint8_t modrm;
232
233 /* determine the prefix. */
234 switch(*ip) {
235 case 0xf2:
236 case 0xf3:
237 case 0x66:
238 ip++;
239 break;
240 }
241
242 /* look for rex prefix */
243 if ((*ip & 0x40) == 0x40)
244 ip++;
245
246 /* Make sure we have a MPX instruction. */
247 if (*ip++ != 0x0f)
248 return addr;
249
250 /* Skip the op code byte. */
251 ip++;
252
253 /* Get the modrm byte. */
254 modrm = *ip++;
255
256 /* Break it down into parts. */
257 rm = modrm & 7;
258 mod = (modrm >> 6);
259
260 /* Init the parts of the address mode. */
261 base = 8;
262
263 /* Is it a mem mode? */
264 if (mod != 3) {
265 /* look for scaled indexed addressing */
266 if (rm == 4) {
267 /* SIB addressing */
268 sib = *ip++;
269 base = sib & 7;
270 switch (mod) {
271 case 0:
272 if (base == 5)
273 ip += 4;
274 break;
275
276 case 1:
277 ip++;
278 break;
279
280 case 2:
281 ip += 4;
282 break;
283 }
284
285 } else {
286 /* MODRM addressing */
287 switch (mod) {
288 case 0:
289 /* DISP32 addressing, no base */
290 if (rm == 5)
291 ip += 4;
292 break;
293
294 case 1:
295 ip++;
296 break;
297
298 case 2:
299 ip += 4;
300 break;
301 }
302 }
303 }
304 return ip;
305}
306
307#ifdef si_lower
308static inline void *__si_bounds_lower(siginfo_t *si)
309{
310 return si->si_lower;
311}
312
313static inline void *__si_bounds_upper(siginfo_t *si)
314{
315 return si->si_upper;
316}
317#else
318static inline void **__si_bounds_hack(siginfo_t *si)
319{
320 void *sigfault = &si->_sifields._sigfault;
321 void *end_sigfault = sigfault + sizeof(si->_sifields._sigfault);
322 void **__si_lower = end_sigfault;
323
324 return __si_lower;
325}
326
327static inline void *__si_bounds_lower(siginfo_t *si)
328{
329 return *__si_bounds_hack(si);
330}
331
332static inline void *__si_bounds_upper(siginfo_t *si)
333{
334 return (*__si_bounds_hack(si)) + sizeof(void *);
335}
336#endif
337
338static int br_count;
339static int expected_bnd_index = -1;
340uint64_t shadow_plb[NR_MPX_BOUNDS_REGISTERS][2]; /* shadow MPX bound registers */
341unsigned long shadow_map[NR_MPX_BOUNDS_REGISTERS];
342
343/*
344 * The kernel is supposed to provide some information about the bounds
345 * exception in the siginfo. It should match what we have in the bounds
346 * registers that we are checking against. Just check against the shadow copy
347 * since it is easily available, and we also check that *it* matches the real
348 * registers.
349 */
350void check_siginfo_vs_shadow(siginfo_t* si)
351{
352 int siginfo_ok = 1;
353 void *shadow_lower = (void *)(unsigned long)shadow_plb[expected_bnd_index][0];
354 void *shadow_upper = (void *)(unsigned long)shadow_plb[expected_bnd_index][1];
355
356 if ((expected_bnd_index < 0) ||
357 (expected_bnd_index >= NR_MPX_BOUNDS_REGISTERS)) {
358 fprintf(stderr, "ERROR: invalid expected_bnd_index: %d\n",
359 expected_bnd_index);
360 exit(6);
361 }
362 if (__si_bounds_lower(si) != shadow_lower)
363 siginfo_ok = 0;
364 if (__si_bounds_upper(si) != shadow_upper)
365 siginfo_ok = 0;
366
367 if (!siginfo_ok) {
368 fprintf(stderr, "ERROR: siginfo bounds do not match "
369 "shadow bounds for register %d\n", expected_bnd_index);
370 exit(7);
371 }
372}
373
374void handler(int signum, siginfo_t *si, void *vucontext)
375{
376 int i;
377 ucontext_t *uctxt = vucontext;
378 int trapno;
379 unsigned long ip;
380
381 dprintf1("entered signal handler\n");
382
383 trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
384 ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
385
386 if (trapno == 5) {
387 typeof(si->si_addr) *si_addr_ptr = &si->si_addr;
388 uint64_t status = read_mpx_status_sig(uctxt);
389 uint64_t br_reason = status & 0x3;
390
391 br_count++;
392 dprintf1("#BR 0x%jx (total seen: %d)\n", status, br_count);
393
394#define __SI_FAULT (3 << 16)
395#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */
396
397 dprintf2("Saw a #BR! status 0x%jx at %016lx br_reason: %jx\n",
398 status, ip, br_reason);
399 dprintf2("si_signo: %d\n", si->si_signo);
400 dprintf2(" signum: %d\n", signum);
401 dprintf2("info->si_code == SEGV_BNDERR: %d\n",
402 (si->si_code == SEGV_BNDERR));
403 dprintf2("info->si_code: %d\n", si->si_code);
404 dprintf2("info->si_lower: %p\n", __si_bounds_lower(si));
405 dprintf2("info->si_upper: %p\n", __si_bounds_upper(si));
406
407 check_siginfo_vs_shadow(si);
408
409 for (i = 0; i < 8; i++)
410 dprintf3("[%d]: %p\n", i, si_addr_ptr[i]);
411 switch (br_reason) {
412 case 0: /* traditional BR */
413 fprintf(stderr,
414 "Undefined status with bound exception:%jx\n",
415 status);
416 exit(5);
417 case 1: /* #BR MPX bounds exception */
418 /* these are normal and we expect to see them */
419 dprintf1("bounds exception (normal): status 0x%jx at %p si_addr: %p\n",
420 status, (void *)ip, si->si_addr);
421 num_bnd_chk++;
422 uctxt->uc_mcontext.gregs[REG_IP_IDX] =
423 (greg_t)get_next_inst_ip((uint8_t *)ip);
424 break;
425 case 2:
426 fprintf(stderr, "#BR status == 2, missing bounds table,"
427 "kernel should have handled!!\n");
428 exit(4);
429 break;
430 default:
431 fprintf(stderr, "bound check error: status 0x%jx at %p\n",
432 status, (void *)ip);
433 num_bnd_chk++;
434 uctxt->uc_mcontext.gregs[REG_IP_IDX] =
435 (greg_t)get_next_inst_ip((uint8_t *)ip);
436 fprintf(stderr, "bound check error: si_addr %p\n", si->si_addr);
437 exit(3);
438 }
439 } else if (trapno == 14) {
440 eprintf("ERROR: In signal handler, page fault, trapno = %d, ip = %016lx\n",
441 trapno, ip);
442 eprintf("si_addr %p\n", si->si_addr);
443 eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
444 test_failed();
445 } else {
446 eprintf("unexpected trap %d! at 0x%lx\n", trapno, ip);
447 eprintf("si_addr %p\n", si->si_addr);
448 eprintf("REG_ERR: %lx\n", (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
449 test_failed();
450 }
451}
452
453static inline void cpuid_count(unsigned int op, int count,
454 unsigned int *eax, unsigned int *ebx,
455 unsigned int *ecx, unsigned int *edx)
456{
457 *eax = op;
458 *ecx = count;
459 __cpuid(eax, ebx, ecx, edx);
460}
461
462#define XSTATE_CPUID 0x0000000d
463
464/*
465 * List of XSAVE features Linux knows about:
466 */
467enum xfeature_bit {
468 XSTATE_BIT_FP,
469 XSTATE_BIT_SSE,
470 XSTATE_BIT_YMM,
471 XSTATE_BIT_BNDREGS,
472 XSTATE_BIT_BNDCSR,
473 XSTATE_BIT_OPMASK,
474 XSTATE_BIT_ZMM_Hi256,
475 XSTATE_BIT_Hi16_ZMM,
476
477 XFEATURES_NR_MAX,
478};
479
480#define XSTATE_FP (1 << XSTATE_BIT_FP)
481#define XSTATE_SSE (1 << XSTATE_BIT_SSE)
482#define XSTATE_YMM (1 << XSTATE_BIT_YMM)
483#define XSTATE_BNDREGS (1 << XSTATE_BIT_BNDREGS)
484#define XSTATE_BNDCSR (1 << XSTATE_BIT_BNDCSR)
485#define XSTATE_OPMASK (1 << XSTATE_BIT_OPMASK)
486#define XSTATE_ZMM_Hi256 (1 << XSTATE_BIT_ZMM_Hi256)
487#define XSTATE_Hi16_ZMM (1 << XSTATE_BIT_Hi16_ZMM)
488
489#define MPX_XSTATES (XSTATE_BNDREGS | XSTATE_BNDCSR) /* 0x18 */
490
491bool one_bit(unsigned int x, int bit)
492{
493 return !!(x & (1<<bit));
494}
495
496void print_state_component(int state_bit_nr, char *name)
497{
498 unsigned int eax, ebx, ecx, edx;
499 unsigned int state_component_size;
500 unsigned int state_component_supervisor;
501 unsigned int state_component_user;
502 unsigned int state_component_aligned;
503
504 /* See SDM Section 13.2 */
505 cpuid_count(XSTATE_CPUID, state_bit_nr, &eax, &ebx, &ecx, &edx);
506 assert(eax || ebx || ecx);
507 state_component_size = eax;
508 state_component_supervisor = ((!ebx) && one_bit(ecx, 0));
509 state_component_user = !one_bit(ecx, 0);
510 state_component_aligned = one_bit(ecx, 1);
511 printf("%8s: size: %d user: %d supervisor: %d aligned: %d\n",
512 name,
513 state_component_size, state_component_user,
514 state_component_supervisor, state_component_aligned);
515
516}
517
518/* Intel-defined CPU features, CPUID level 0x00000001 (ecx) */
519#define XSAVE_FEATURE_BIT (26) /* XSAVE/XRSTOR/XSETBV/XGETBV */
520#define OSXSAVE_FEATURE_BIT (27) /* XSAVE enabled in the OS */
521
522bool check_mpx_support(void)
523{
524 unsigned int eax, ebx, ecx, edx;
525
526 cpuid_count(1, 0, &eax, &ebx, &ecx, &edx);
527
528 /* We can't do much without XSAVE, so just make these assert()'s */
529 if (!one_bit(ecx, XSAVE_FEATURE_BIT)) {
530 fprintf(stderr, "processor lacks XSAVE, can not run MPX tests\n");
531 exit(0);
532 }
533
534 if (!one_bit(ecx, OSXSAVE_FEATURE_BIT)) {
535 fprintf(stderr, "processor lacks OSXSAVE, can not run MPX tests\n");
536 exit(0);
537 }
538
539 /* CPUs not supporting the XSTATE CPUID leaf do not support MPX */
540 /* Is this redundant with the feature bit checks? */
541 cpuid_count(0, 0, &eax, &ebx, &ecx, &edx);
542 if (eax < XSTATE_CPUID) {
543 fprintf(stderr, "processor lacks XSTATE CPUID leaf,"
544 " can not run MPX tests\n");
545 exit(0);
546 }
547
548 printf("XSAVE is supported by HW & OS\n");
549
550 cpuid_count(XSTATE_CPUID, 0, &eax, &ebx, &ecx, &edx);
551
552 printf("XSAVE processor supported state mask: 0x%x\n", eax);
553 printf("XSAVE OS supported state mask: 0x%jx\n", xgetbv(0));
554
555 /* Make sure that the MPX states are enabled in in XCR0 */
556 if ((eax & MPX_XSTATES) != MPX_XSTATES) {
557 fprintf(stderr, "processor lacks MPX XSTATE(s), can not run MPX tests\n");
558 exit(0);
559 }
560
561 /* Make sure the MPX states are supported by XSAVE* */
562 if ((xgetbv(0) & MPX_XSTATES) != MPX_XSTATES) {
563 fprintf(stderr, "MPX XSTATE(s) no enabled in XCR0, "
564 "can not run MPX tests\n");
565 exit(0);
566 }
567
568 print_state_component(XSTATE_BIT_BNDREGS, "BNDREGS");
569 print_state_component(XSTATE_BIT_BNDCSR, "BNDCSR");
570
571 return true;
572}
573
574void enable_mpx(void *l1base)
575{
576 /* enable point lookup */
577 memset(buffer, 0, sizeof(buffer));
578 xrstor_state(xsave_buf, 0x18);
579
580 xsave_buf->xsave_hdr.xstate_bv = 0x10;
581 xsave_buf->bndcsr.cfg_reg_u = (unsigned long)l1base | 1;
582 xsave_buf->bndcsr.status_reg = 0;
583
584 dprintf2("bf xrstor\n");
585 dprintf2("xsave cndcsr: status %jx, configu %jx\n",
586 xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u);
587 xrstor_state(xsave_buf, 0x18);
588 dprintf2("after xrstor\n");
589
590 xsave_state_1(xsave_buf, 0x18);
591
592 dprintf1("xsave bndcsr: status %jx, configu %jx\n",
593 xsave_buf->bndcsr.status_reg, xsave_buf->bndcsr.cfg_reg_u);
594}
595
596#include <sys/prctl.h>
597
598struct mpx_bounds_dir *bounds_dir_ptr;
599
600unsigned long __bd_incore(const char *func, int line)
601{
602 unsigned long ret = nr_incore(bounds_dir_ptr, MPX_BOUNDS_DIR_SIZE_BYTES);
603 return ret;
604}
605#define bd_incore() __bd_incore(__func__, __LINE__)
606
607void check_clear(void *ptr, unsigned long sz)
608{
609 unsigned long *i;
610
611 for (i = ptr; (void *)i < ptr + sz; i++) {
612 if (*i) {
613 dprintf1("%p is NOT clear at %p\n", ptr, i);
614 assert(0);
615 }
616 }
617 dprintf1("%p is clear for %lx\n", ptr, sz);
618}
619
620void check_clear_bd(void)
621{
622 check_clear(bounds_dir_ptr, 2UL << 30);
623}
624
625#define USE_MALLOC_FOR_BOUNDS_DIR 1
626bool process_specific_init(void)
627{
628 unsigned long size;
629 unsigned long *dir;
630 /* Guarantee we have the space to align it, add padding: */
631 unsigned long pad = getpagesize();
632
633 size = 2UL << 30; /* 2GB */
634 if (sizeof(unsigned long) == 4)
635 size = 4UL << 20; /* 4MB */
636 dprintf1("trying to allocate %ld MB bounds directory\n", (size >> 20));
637
638 if (USE_MALLOC_FOR_BOUNDS_DIR) {
639 unsigned long _dir;
640
641 dir = malloc(size + pad);
642 assert(dir);
643 _dir = (unsigned long)dir;
644 _dir += 0xfffUL;
645 _dir &= ~0xfffUL;
646 dir = (void *)_dir;
647 } else {
648 /*
649 * This makes debugging easier because the address
650 * calculations are simpler:
651 */
652 dir = mmap((void *)0x200000000000, size + pad,
653 PROT_READ|PROT_WRITE,
654 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
655 if (dir == (void *)-1) {
656 perror("unable to allocate bounds directory");
657 abort();
658 }
659 check_clear(dir, size);
660 }
661 bounds_dir_ptr = (void *)dir;
662 madvise(bounds_dir_ptr, size, MADV_NOHUGEPAGE);
663 bd_incore();
664 dprintf1("bounds directory: 0x%p -> 0x%p\n", bounds_dir_ptr,
665 (char *)bounds_dir_ptr + size);
666 check_clear(dir, size);
667 enable_mpx(dir);
668 check_clear(dir, size);
669 if (prctl(43, 0, 0, 0, 0)) {
670 printf("no MPX support\n");
671 abort();
672 return false;
673 }
674 return true;
675}
676
677bool process_specific_finish(void)
678{
679 if (prctl(44)) {
680 printf("no MPX support\n");
681 return false;
682 }
683 return true;
684}
685
686void setup_handler()
687{
688 int r, rs;
689 struct sigaction newact;
690 struct sigaction oldact;
691
692 /* #BR is mapped to sigsegv */
693 int signum = SIGSEGV;
694
695 newact.sa_handler = 0; /* void(*)(int)*/
696 newact.sa_sigaction = handler; /* void (*)(int, siginfo_t*, void *) */
697
698 /*sigset_t - signals to block while in the handler */
699 /* get the old signal mask. */
700 rs = sigprocmask(SIG_SETMASK, 0, &newact.sa_mask);
701 assert(rs == 0);
702
703 /* call sa_sigaction, not sa_handler*/
704 newact.sa_flags = SA_SIGINFO;
705
706 newact.sa_restorer = 0; /* void(*)(), obsolete */
707 r = sigaction(signum, &newact, &oldact);
708 assert(r == 0);
709}
710
711void mpx_prepare(void)
712{
713 dprintf2("%s()\n", __func__);
714 setup_handler();
715 process_specific_init();
716}
717
718void mpx_cleanup(void)
719{
720 printf("%s(): %jd BRs. bye...\n", __func__, num_bnd_chk);
721 process_specific_finish();
722}
723
724/*-------------- the following is test case ---------------*/
725#include <stdint.h>
726#include <stdbool.h>
727#include <stdlib.h>
728#include <stdio.h>
729#include <time.h>
730
731uint64_t num_lower_brs;
732uint64_t num_upper_brs;
733
734#define MPX_CONFIG_OFFSET 1024
735#define MPX_BOUNDS_OFFSET 960
736#define MPX_HEADER_OFFSET 512
737#define MAX_ADDR_TESTED (1<<28)
738#define TEST_ROUNDS 100
739
740/*
741 0F 1A /r BNDLDX-Load
742 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation
743 66 0F 1A /r BNDMOV bnd1, bnd2/m128
744 66 0F 1B /r BNDMOV bnd1/m128, bnd2
745 F2 0F 1A /r BNDCU bnd, r/m64
746 F2 0F 1B /r BNDCN bnd, r/m64
747 F3 0F 1A /r BNDCL bnd, r/m64
748 F3 0F 1B /r BNDMK bnd, m64
749*/
750
751static __always_inline void xsave_state(void *_fx, uint64_t mask)
752{
753 uint32_t lmask = mask;
754 uint32_t hmask = mask >> 32;
755 unsigned char *fx = _fx;
756
757 asm volatile(".byte " REX_PREFIX "0x0f,0xae,0x27\n\t"
758 : : "D" (fx), "m" (*fx), "a" (lmask), "d" (hmask)
759 : "memory");
760}
761
762static __always_inline void mpx_clear_bnd0(void)
763{
764 long size = 0;
765 void *ptr = NULL;
766 /* F3 0F 1B /r BNDMK bnd, m64 */
767 /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */
768 asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t"
769 : : "c" (ptr), "d" (size-1)
770 : "memory");
771}
772
773static __always_inline void mpx_make_bound_helper(unsigned long ptr,
774 unsigned long size)
775{
776 /* F3 0F 1B /r BNDMK bnd, m64 */
777 /* f3 0f 1b 04 11 bndmk (%rcx,%rdx,1),%bnd0 */
778 asm volatile(".byte 0xf3,0x0f,0x1b,0x04,0x11\n\t"
779 : : "c" (ptr), "d" (size-1)
780 : "memory");
781}
782
783static __always_inline void mpx_check_lowerbound_helper(unsigned long ptr)
784{
785 /* F3 0F 1A /r NDCL bnd, r/m64 */
786 /* f3 0f 1a 01 bndcl (%rcx),%bnd0 */
787 asm volatile(".byte 0xf3,0x0f,0x1a,0x01\n\t"
788 : : "c" (ptr)
789 : "memory");
790}
791
792static __always_inline void mpx_check_upperbound_helper(unsigned long ptr)
793{
794 /* F2 0F 1A /r BNDCU bnd, r/m64 */
795 /* f2 0f 1a 01 bndcu (%rcx),%bnd0 */
796 asm volatile(".byte 0xf2,0x0f,0x1a,0x01\n\t"
797 : : "c" (ptr)
798 : "memory");
799}
800
801static __always_inline void mpx_movbndreg_helper()
802{
803 /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */
804 /* 66 0f 1b c2 bndmov %bnd0,%bnd2 */
805
806 asm volatile(".byte 0x66,0x0f,0x1b,0xc2\n\t");
807}
808
809static __always_inline void mpx_movbnd2mem_helper(uint8_t *mem)
810{
811 /* 66 0F 1B /r BNDMOV bnd1/m128, bnd2 */
812 /* 66 0f 1b 01 bndmov %bnd0,(%rcx) */
813 asm volatile(".byte 0x66,0x0f,0x1b,0x01\n\t"
814 : : "c" (mem)
815 : "memory");
816}
817
818static __always_inline void mpx_movbnd_from_mem_helper(uint8_t *mem)
819{
820 /* 66 0F 1A /r BNDMOV bnd1, bnd2/m128 */
821 /* 66 0f 1a 01 bndmov (%rcx),%bnd0 */
822 asm volatile(".byte 0x66,0x0f,0x1a,0x01\n\t"
823 : : "c" (mem)
824 : "memory");
825}
826
827static __always_inline void mpx_store_dsc_helper(unsigned long ptr_addr,
828 unsigned long ptr_val)
829{
830 /* 0F 1B /r BNDSTX-Store Extended Bounds Using Address Translation */
831 /* 0f 1b 04 11 bndstx %bnd0,(%rcx,%rdx,1) */
832 asm volatile(".byte 0x0f,0x1b,0x04,0x11\n\t"
833 : : "c" (ptr_addr), "d" (ptr_val)
834 : "memory");
835}
836
837static __always_inline void mpx_load_dsc_helper(unsigned long ptr_addr,
838 unsigned long ptr_val)
839{
840 /* 0F 1A /r BNDLDX-Load */
841 /*/ 0f 1a 04 11 bndldx (%rcx,%rdx,1),%bnd0 */
842 asm volatile(".byte 0x0f,0x1a,0x04,0x11\n\t"
843 : : "c" (ptr_addr), "d" (ptr_val)
844 : "memory");
845}
846
847void __print_context(void *__print_xsave_buffer, int line)
848{
849 uint64_t *bounds = (uint64_t *)(__print_xsave_buffer + MPX_BOUNDS_OFFSET);
850 uint64_t *cfg = (uint64_t *)(__print_xsave_buffer + MPX_CONFIG_OFFSET);
851
852 int i;
853 eprintf("%s()::%d\n", "print_context", line);
854 for (i = 0; i < 4; i++) {
855 eprintf("bound[%d]: 0x%016lx 0x%016lx(0x%016lx)\n", i,
856 (unsigned long)bounds[i*2],
857 ~(unsigned long)bounds[i*2+1],
858 (unsigned long)bounds[i*2+1]);
859 }
860
861 eprintf("cpcfg: %jx cpstatus: %jx\n", cfg[0], cfg[1]);
862}
863#define print_context(x) __print_context(x, __LINE__)
864#ifdef DEBUG
865#define dprint_context(x) print_context(x)
866#else
867#define dprint_context(x) do{}while(0)
868#endif
869
870void init()
871{
872 int i;
873
874 srand((unsigned int)time(NULL));
875
876 for (i = 0; i < 4; i++) {
877 shadow_plb[i][0] = 0;
878 shadow_plb[i][1] = ~(unsigned long)0;
879 }
880}
881
882long int __mpx_random(int line)
883{
884#ifdef NOT_SO_RANDOM
885 static long fake = 722122311;
886 fake += 563792075;
887 return fakse;
888#else
889 return random();
890#endif
891}
892#define mpx_random() __mpx_random(__LINE__)
893
894uint8_t *get_random_addr()
895{
896 uint8_t*addr = (uint8_t *)(unsigned long)(rand() % MAX_ADDR_TESTED);
897 return (addr - (unsigned long)addr % sizeof(uint8_t *));
898}
899
900static inline bool compare_context(void *__xsave_buffer)
901{
902 uint64_t *bounds = (uint64_t *)(__xsave_buffer + MPX_BOUNDS_OFFSET);
903
904 int i;
905 for (i = 0; i < 4; i++) {
906 dprintf3("shadow[%d]{%016lx/%016lx}\nbounds[%d]{%016lx/%016lx}\n",
907 i, (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1],
908 i, (unsigned long)bounds[i*2], ~(unsigned long)bounds[i*2+1]);
909 if ((shadow_plb[i][0] != bounds[i*2]) ||
910 (shadow_plb[i][1] != ~(unsigned long)bounds[i*2+1])) {
911 eprintf("ERROR comparing shadow to real bound register %d\n", i);
912 eprintf("shadow{0x%016lx/0x%016lx}\nbounds{0x%016lx/0x%016lx}\n",
913 (unsigned long)shadow_plb[i][0], (unsigned long)shadow_plb[i][1],
914 (unsigned long)bounds[i*2], (unsigned long)bounds[i*2+1]);
915 return false;
916 }
917 }
918
919 return true;
920}
921
922void mkbnd_shadow(uint8_t *ptr, int index, long offset)
923{
924 uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]);
925 uint64_t *upper = (uint64_t *)&(shadow_plb[index][1]);
926 *lower = (unsigned long)ptr;
927 *upper = (unsigned long)ptr + offset - 1;
928}
929
930void check_lowerbound_shadow(uint8_t *ptr, int index)
931{
932 uint64_t *lower = (uint64_t *)&(shadow_plb[index][0]);
933 if (*lower > (uint64_t)(unsigned long)ptr)
934 num_lower_brs++;
935 else
936 dprintf1("LowerBoundChk passed:%p\n", ptr);
937}
938
939void check_upperbound_shadow(uint8_t *ptr, int index)
940{
941 uint64_t upper = *(uint64_t *)&(shadow_plb[index][1]);
942 if (upper < (uint64_t)(unsigned long)ptr)
943 num_upper_brs++;
944 else
945 dprintf1("UpperBoundChk passed:%p\n", ptr);
946}
947
948__always_inline void movbndreg_shadow(int src, int dest)
949{
950 shadow_plb[dest][0] = shadow_plb[src][0];
951 shadow_plb[dest][1] = shadow_plb[src][1];
952}
953
954__always_inline void movbnd2mem_shadow(int src, unsigned long *dest)
955{
956 unsigned long *lower = (unsigned long *)&(shadow_plb[src][0]);
957 unsigned long *upper = (unsigned long *)&(shadow_plb[src][1]);
958 *dest = *lower;
959 *(dest+1) = *upper;
960}
961
962__always_inline void movbnd_from_mem_shadow(unsigned long *src, int dest)
963{
964 unsigned long *lower = (unsigned long *)&(shadow_plb[dest][0]);
965 unsigned long *upper = (unsigned long *)&(shadow_plb[dest][1]);
966 *lower = *src;
967 *upper = *(src+1);
968}
969
970__always_inline void stdsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val)
971{
972 shadow_map[0] = (unsigned long)shadow_plb[index][0];
973 shadow_map[1] = (unsigned long)shadow_plb[index][1];
974 shadow_map[2] = (unsigned long)ptr_val;
975 dprintf3("%s(%d, %p, %p) set shadow map[2]: %p\n", __func__,
976 index, ptr, ptr_val, ptr_val);
977 /*ptr ignored */
978}
979
980void lddsc_shadow(int index, uint8_t *ptr, uint8_t *ptr_val)
981{
982 uint64_t lower = shadow_map[0];
983 uint64_t upper = shadow_map[1];
984 uint8_t *value = (uint8_t *)shadow_map[2];
985
986 if (value != ptr_val) {
987 dprintf2("%s(%d, %p, %p) init shadow bounds[%d] "
988 "because %p != %p\n", __func__, index, ptr,
989 ptr_val, index, value, ptr_val);
990 shadow_plb[index][0] = 0;
991 shadow_plb[index][1] = ~(unsigned long)0;
992 } else {
993 shadow_plb[index][0] = lower;
994 shadow_plb[index][1] = upper;
995 }
996 /* ptr ignored */
997}
998
999static __always_inline void mpx_test_helper0(uint8_t *buf, uint8_t *ptr)
1000{
1001 mpx_make_bound_helper((unsigned long)ptr, 0x1800);
1002}
1003
1004static __always_inline void mpx_test_helper0_shadow(uint8_t *buf, uint8_t *ptr)
1005{
1006 mkbnd_shadow(ptr, 0, 0x1800);
1007}
1008
1009static __always_inline void mpx_test_helper1(uint8_t *buf, uint8_t *ptr)
1010{
1011 /* these are hard-coded to check bnd0 */
1012 expected_bnd_index = 0;
1013 mpx_check_lowerbound_helper((unsigned long)(ptr-1));
1014 mpx_check_upperbound_helper((unsigned long)(ptr+0x1800));
1015 /* reset this since we do not expect any more bounds exceptions */
1016 expected_bnd_index = -1;
1017}
1018
1019static __always_inline void mpx_test_helper1_shadow(uint8_t *buf, uint8_t *ptr)
1020{
1021 check_lowerbound_shadow(ptr-1, 0);
1022 check_upperbound_shadow(ptr+0x1800, 0);
1023}
1024
1025static __always_inline void mpx_test_helper2(uint8_t *buf, uint8_t *ptr)
1026{
1027 mpx_make_bound_helper((unsigned long)ptr, 0x1800);
1028 mpx_movbndreg_helper();
1029 mpx_movbnd2mem_helper(buf);
1030 mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800);
1031}
1032
1033static __always_inline void mpx_test_helper2_shadow(uint8_t *buf, uint8_t *ptr)
1034{
1035 mkbnd_shadow(ptr, 0, 0x1800);
1036 movbndreg_shadow(0, 2);
1037 movbnd2mem_shadow(0, (unsigned long *)buf);
1038 mkbnd_shadow(ptr+0x12, 0, 0x1800);
1039}
1040
1041static __always_inline void mpx_test_helper3(uint8_t *buf, uint8_t *ptr)
1042{
1043 mpx_movbnd_from_mem_helper(buf);
1044}
1045
1046static __always_inline void mpx_test_helper3_shadow(uint8_t *buf, uint8_t *ptr)
1047{
1048 movbnd_from_mem_shadow((unsigned long *)buf, 0);
1049}
1050
1051static __always_inline void mpx_test_helper4(uint8_t *buf, uint8_t *ptr)
1052{
1053 mpx_store_dsc_helper((unsigned long)buf, (unsigned long)ptr);
1054 mpx_make_bound_helper((unsigned long)(ptr+0x12), 0x1800);
1055}
1056
1057static __always_inline void mpx_test_helper4_shadow(uint8_t *buf, uint8_t *ptr)
1058{
1059 stdsc_shadow(0, buf, ptr);
1060 mkbnd_shadow(ptr+0x12, 0, 0x1800);
1061}
1062
1063static __always_inline void mpx_test_helper5(uint8_t *buf, uint8_t *ptr)
1064{
1065 mpx_load_dsc_helper((unsigned long)buf, (unsigned long)ptr);
1066}
1067
1068static __always_inline void mpx_test_helper5_shadow(uint8_t *buf, uint8_t *ptr)
1069{
1070 lddsc_shadow(0, buf, ptr);
1071}
1072
1073#define NR_MPX_TEST_FUNCTIONS 6
1074
1075/*
1076 * For compatibility reasons, MPX will clear the bounds registers
1077 * when you make function calls (among other things). We have to
1078 * preserve the registers in between calls to the "helpers" since
1079 * they build on each other.
1080 *
1081 * Be very careful not to make any function calls inside the
1082 * helpers, or anywhere else beween the xrstor and xsave.
1083 */
1084#define run_helper(helper_nr, buf, buf_shadow, ptr) do { \
1085 xrstor_state(xsave_test_buf, flags); \
1086 mpx_test_helper##helper_nr(buf, ptr); \
1087 xsave_state(xsave_test_buf, flags); \
1088 mpx_test_helper##helper_nr##_shadow(buf_shadow, ptr); \
1089} while (0)
1090
1091static void run_helpers(int nr, uint8_t *buf, uint8_t *buf_shadow, uint8_t *ptr)
1092{
1093 uint64_t flags = 0x18;
1094
1095 dprint_context(xsave_test_buf);
1096 switch (nr) {
1097 case 0:
1098 run_helper(0, buf, buf_shadow, ptr);
1099 break;
1100 case 1:
1101 run_helper(1, buf, buf_shadow, ptr);
1102 break;
1103 case 2:
1104 run_helper(2, buf, buf_shadow, ptr);
1105 break;
1106 case 3:
1107 run_helper(3, buf, buf_shadow, ptr);
1108 break;
1109 case 4:
1110 run_helper(4, buf, buf_shadow, ptr);
1111 break;
1112 case 5:
1113 run_helper(5, buf, buf_shadow, ptr);
1114 break;
1115 default:
1116 test_failed();
1117 break;
1118 }
1119 dprint_context(xsave_test_buf);
1120}
1121
1122unsigned long buf_shadow[1024]; /* used to check load / store descriptors */
1123extern long inspect_me(struct mpx_bounds_dir *bounds_dir);
1124
1125long cover_buf_with_bt_entries(void *buf, long buf_len)
1126{
1127 int i;
1128 long nr_to_fill;
1129 int ratio = 1000;
1130 unsigned long buf_len_in_ptrs;
1131
1132 /* Fill about 1/100 of the space with bt entries */
1133 nr_to_fill = buf_len / (sizeof(unsigned long) * ratio);
1134
1135 if (!nr_to_fill)
1136 dprintf3("%s() nr_to_fill: %ld\n", __func__, nr_to_fill);
1137
1138 /* Align the buffer to pointer size */
1139 while (((unsigned long)buf) % sizeof(void *)) {
1140 buf++;
1141 buf_len--;
1142 }
1143 /* We are storing pointers, so make */
1144 buf_len_in_ptrs = buf_len / sizeof(void *);
1145
1146 for (i = 0; i < nr_to_fill; i++) {
1147 long index = (mpx_random() % buf_len_in_ptrs);
1148 void *ptr = buf + index * sizeof(unsigned long);
1149 unsigned long ptr_addr = (unsigned long)ptr;
1150
1151 /* ptr and size can be anything */
1152 mpx_make_bound_helper((unsigned long)ptr, 8);
1153
1154 /*
1155 * take bnd0 and put it in to bounds tables "buf + index" is an
1156 * address inside the buffer where we are pretending that we
1157 * are going to put a pointer We do not, though because we will
1158 * never load entries from the table, so it doesn't matter.
1159 */
1160 mpx_store_dsc_helper(ptr_addr, (unsigned long)ptr);
1161 dprintf4("storing bound table entry for %lx (buf start @ %p)\n",
1162 ptr_addr, buf);
1163 }
1164 return nr_to_fill;
1165}
1166
1167unsigned long align_down(unsigned long alignme, unsigned long align_to)
1168{
1169 return alignme & ~(align_to-1);
1170}
1171
1172unsigned long align_up(unsigned long alignme, unsigned long align_to)
1173{
1174 return (alignme + align_to - 1) & ~(align_to-1);
1175}
1176
1177/*
1178 * Using 1MB alignment guarantees that each no allocation
1179 * will overlap with another's bounds tables.
1180 *
1181 * We have to cook our own allocator here. malloc() can
1182 * mix other allocation with ours which means that even
1183 * if we free all of our allocations, there might still
1184 * be bounds tables for the *areas* since there is other
1185 * valid memory there.
1186 *
1187 * We also can't use malloc() because a free() of an area
1188 * might not free it back to the kernel. We want it
1189 * completely unmapped an malloc() does not guarantee
1190 * that.
1191 */
1192#ifdef __i386__
1193long alignment = 4096;
1194long sz_alignment = 4096;
1195#else
1196long alignment = 1 * MB;
1197long sz_alignment = 1 * MB;
1198#endif
1199void *mpx_mini_alloc(unsigned long sz)
1200{
1201 unsigned long long tries = 0;
1202 static void *last;
1203 void *ptr;
1204 void *try_at;
1205
1206 sz = align_up(sz, sz_alignment);
1207
1208 try_at = last + alignment;
1209 while (1) {
1210 ptr = mmap(try_at, sz, PROT_READ|PROT_WRITE,
1211 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
1212 if (ptr == (void *)-1)
1213 return NULL;
1214 if (ptr == try_at)
1215 break;
1216
1217 munmap(ptr, sz);
1218 try_at += alignment;
1219#ifdef __i386__
1220 /*
1221 * This isn't quite correct for 32-bit binaries
1222 * on 64-bit kernels since they can use the
1223 * entire 32-bit address space, but it's close
1224 * enough.
1225 */
1226 if (try_at > (void *)0xC0000000)
1227#else
1228 if (try_at > (void *)0x0000800000000000)
1229#endif
1230 try_at = (void *)0x0;
1231 if (!(++tries % 10000))
1232 dprintf1("stuck in %s(), tries: %lld\n", __func__, tries);
1233 continue;
1234 }
1235 last = ptr;
1236 dprintf3("mpx_mini_alloc(0x%lx) returning: %p\n", sz, ptr);
1237 return ptr;
1238}
1239void mpx_mini_free(void *ptr, long sz)
1240{
1241 dprintf2("%s() ptr: %p\n", __func__, ptr);
1242 if ((unsigned long)ptr > 0x100000000000) {
1243 dprintf1("uh oh !!!!!!!!!!!!!!! pointer too high: %p\n", ptr);
1244 test_failed();
1245 }
1246 sz = align_up(sz, sz_alignment);
1247 dprintf3("%s() ptr: %p before munmap\n", __func__, ptr);
1248 munmap(ptr, sz);
1249 dprintf3("%s() ptr: %p DONE\n", __func__, ptr);
1250}
1251
1252#define NR_MALLOCS 100
1253struct one_malloc {
1254 char *ptr;
1255 int nr_filled_btes;
1256 unsigned long size;
1257};
1258struct one_malloc mallocs[NR_MALLOCS];
1259
1260void free_one_malloc(int index)
1261{
1262 unsigned long free_ptr;
1263 unsigned long mask;
1264
1265 if (!mallocs[index].ptr)
1266 return;
1267
1268 mpx_mini_free(mallocs[index].ptr, mallocs[index].size);
1269 dprintf4("freed[%d]: %p\n", index, mallocs[index].ptr);
1270
1271 free_ptr = (unsigned long)mallocs[index].ptr;
1272 mask = alignment-1;
1273 dprintf4("lowerbits: %lx / %lx mask: %lx\n", free_ptr,
1274 (free_ptr & mask), mask);
1275 assert((free_ptr & mask) == 0);
1276
1277 mallocs[index].ptr = NULL;
1278}
1279
1280#ifdef __i386__
1281#define MPX_BOUNDS_TABLE_COVERS 4096
1282#else
1283#define MPX_BOUNDS_TABLE_COVERS (1 * MB)
1284#endif
1285void zap_everything(void)
1286{
1287 long after_zap;
1288 long before_zap;
1289 int i;
1290
1291 before_zap = inspect_me(bounds_dir_ptr);
1292 dprintf1("zapping everything start: %ld\n", before_zap);
1293 for (i = 0; i < NR_MALLOCS; i++)
1294 free_one_malloc(i);
1295
1296 after_zap = inspect_me(bounds_dir_ptr);
1297 dprintf1("zapping everything done: %ld\n", after_zap);
1298 /*
1299 * We only guarantee to empty the thing out if our allocations are
1300 * exactly aligned on the boundaries of a boudns table.
1301 */
1302 if ((alignment >= MPX_BOUNDS_TABLE_COVERS) &&
1303 (sz_alignment >= MPX_BOUNDS_TABLE_COVERS)) {
1304 if (after_zap != 0)
1305 test_failed();
1306
1307 assert(after_zap == 0);
1308 }
1309}
1310
1311void do_one_malloc(void)
1312{
1313 static int malloc_counter;
1314 long sz;
1315 int rand_index = (mpx_random() % NR_MALLOCS);
1316 void *ptr = mallocs[rand_index].ptr;
1317
1318 dprintf3("%s() enter\n", __func__);
1319
1320 if (ptr) {
1321 dprintf3("freeing one malloc at index: %d\n", rand_index);
1322 free_one_malloc(rand_index);
1323 if (mpx_random() % (NR_MALLOCS*3) == 3) {
1324 int i;
1325 dprintf3("zapping some more\n");
1326 for (i = rand_index; i < NR_MALLOCS; i++)
1327 free_one_malloc(i);
1328 }
1329 if ((mpx_random() % zap_all_every_this_many_mallocs) == 4)
1330 zap_everything();
1331 }
1332
1333 /* 1->~1M */
1334 sz = (1 + mpx_random() % 1000) * 1000;
1335 ptr = mpx_mini_alloc(sz);
1336 if (!ptr) {
1337 /*
1338 * If we are failing allocations, just assume we
1339 * are out of memory and zap everything.
1340 */
1341 dprintf3("zapping everything because out of memory\n");
1342 zap_everything();
1343 goto out;
1344 }
1345
1346 dprintf3("malloc: %p size: 0x%lx\n", ptr, sz);
1347 mallocs[rand_index].nr_filled_btes = cover_buf_with_bt_entries(ptr, sz);
1348 mallocs[rand_index].ptr = ptr;
1349 mallocs[rand_index].size = sz;
1350out:
1351 if ((++malloc_counter) % inspect_every_this_many_mallocs == 0)
1352 inspect_me(bounds_dir_ptr);
1353}
1354
1355void run_timed_test(void (*test_func)(void))
1356{
1357 int done = 0;
1358 long iteration = 0;
1359 static time_t last_print;
1360 time_t now;
1361 time_t start;
1362
1363 time(&start);
1364 while (!done) {
1365 time(&now);
1366 if ((now - start) > TEST_DURATION_SECS)
1367 done = 1;
1368
1369 test_func();
1370 iteration++;
1371
1372 if ((now - last_print > 1) || done) {
1373 printf("iteration %ld complete, OK so far\n", iteration);
1374 last_print = now;
1375 }
1376 }
1377}
1378
1379void check_bounds_table_frees(void)
1380{
1381 printf("executing unmaptest\n");
1382 inspect_me(bounds_dir_ptr);
1383 run_timed_test(&do_one_malloc);
1384 printf("done with malloc() fun\n");
1385}
1386
1387void insn_test_failed(int test_nr, int test_round, void *buf,
1388 void *buf_shadow, void *ptr)
1389{
1390 print_context(xsave_test_buf);
1391 eprintf("ERROR: test %d round %d failed\n", test_nr, test_round);
1392 while (test_nr == 5) {
1393 struct mpx_bt_entry *bte;
1394 struct mpx_bounds_dir *bd = (void *)bounds_dir_ptr;
1395 struct mpx_bd_entry *bde = mpx_vaddr_to_bd_entry(buf, bd);
1396
1397 printf(" bd: %p\n", bd);
1398 printf("&bde: %p\n", bde);
1399 printf("*bde: %lx\n", *(unsigned long *)bde);
1400 if (!bd_entry_valid(bde))
1401 break;
1402
1403 bte = mpx_vaddr_to_bt_entry(buf, bd);
1404 printf(" te: %p\n", bte);
1405 printf("bte[0]: %lx\n", bte->contents[0]);
1406 printf("bte[1]: %lx\n", bte->contents[1]);
1407 printf("bte[2]: %lx\n", bte->contents[2]);
1408 printf("bte[3]: %lx\n", bte->contents[3]);
1409 break;
1410 }
1411 test_failed();
1412}
1413
1414void check_mpx_insns_and_tables(void)
1415{
1416 int successes = 0;
1417 int failures = 0;
1418 int buf_size = (1024*1024);
1419 unsigned long *buf = malloc(buf_size);
1420 const int total_nr_tests = NR_MPX_TEST_FUNCTIONS * TEST_ROUNDS;
1421 int i, j;
1422
1423 memset(buf, 0, buf_size);
1424 memset(buf_shadow, 0, sizeof(buf_shadow));
1425
1426 for (i = 0; i < TEST_ROUNDS; i++) {
1427 uint8_t *ptr = get_random_addr() + 8;
1428
1429 for (j = 0; j < NR_MPX_TEST_FUNCTIONS; j++) {
1430 if (0 && j != 5) {
1431 successes++;
1432 continue;
1433 }
1434 dprintf2("starting test %d round %d\n", j, i);
1435 dprint_context(xsave_test_buf);
1436 /*
1437 * test5 loads an address from the bounds tables.
1438 * The load will only complete if 'ptr' matches
1439 * the load and the store, so with random addrs,
1440 * the odds of this are very small. Make it
1441 * higher by only moving 'ptr' 1/10 times.
1442 */
1443 if (random() % 10 <= 0)
1444 ptr = get_random_addr() + 8;
1445 dprintf3("random ptr{%p}\n", ptr);
1446 dprint_context(xsave_test_buf);
1447 run_helpers(j, (void *)buf, (void *)buf_shadow, ptr);
1448 dprint_context(xsave_test_buf);
1449 if (!compare_context(xsave_test_buf)) {
1450 insn_test_failed(j, i, buf, buf_shadow, ptr);
1451 failures++;
1452 goto exit;
1453 }
1454 successes++;
1455 dprint_context(xsave_test_buf);
1456 dprintf2("finished test %d round %d\n", j, i);
1457 dprintf3("\n");
1458 dprint_context(xsave_test_buf);
1459 }
1460 }
1461
1462exit:
1463 dprintf2("\nabout to free:\n");
1464 free(buf);
1465 dprintf1("successes: %d\n", successes);
1466 dprintf1(" failures: %d\n", failures);
1467 dprintf1(" tests: %d\n", total_nr_tests);
1468 dprintf1(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs);
1469 dprintf1(" saw: %d #BRs\n", br_count);
1470 if (failures) {
1471 eprintf("ERROR: non-zero number of failures\n");
1472 exit(20);
1473 }
1474 if (successes != total_nr_tests) {
1475 eprintf("ERROR: succeded fewer than number of tries (%d != %d)\n",
1476 successes, total_nr_tests);
1477 exit(21);
1478 }
1479 if (num_upper_brs + num_lower_brs != br_count) {
1480 eprintf("ERROR: unexpected number of #BRs: %jd %jd %d\n",
1481 num_upper_brs, num_lower_brs, br_count);
1482 eprintf("successes: %d\n", successes);
1483 eprintf(" failures: %d\n", failures);
1484 eprintf(" tests: %d\n", total_nr_tests);
1485 eprintf(" expected: %jd #BRs\n", num_upper_brs + num_lower_brs);
1486 eprintf(" saw: %d #BRs\n", br_count);
1487 exit(22);
1488 }
1489}
1490
1491/*
1492 * This is supposed to SIGSEGV nicely once the kernel
1493 * can no longer allocate vaddr space.
1494 */
1495void exhaust_vaddr_space(void)
1496{
1497 unsigned long ptr;
1498 /* Try to make sure there is no room for a bounds table anywhere */
1499 unsigned long skip = MPX_BOUNDS_TABLE_SIZE_BYTES - PAGE_SIZE;
1500#ifdef __i386__
1501 unsigned long max_vaddr = 0xf7788000UL;
1502#else
1503 unsigned long max_vaddr = 0x800000000000UL;
1504#endif
1505
1506 dprintf1("%s() start\n", __func__);
1507 /* do not start at 0, we aren't allowed to map there */
1508 for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) {
1509 void *ptr_ret;
1510 int ret = madvise((void *)ptr, PAGE_SIZE, MADV_NORMAL);
1511
1512 if (!ret) {
1513 dprintf1("madvise() %lx ret: %d\n", ptr, ret);
1514 continue;
1515 }
1516 ptr_ret = mmap((void *)ptr, PAGE_SIZE, PROT_READ|PROT_WRITE,
1517 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
1518 if (ptr_ret != (void *)ptr) {
1519 perror("mmap");
1520 dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret);
1521 break;
1522 }
1523 if (!(ptr & 0xffffff))
1524 dprintf1("mmap(%lx) ret: %p\n", ptr, ptr_ret);
1525 }
1526 for (ptr = PAGE_SIZE; ptr < max_vaddr; ptr += skip) {
1527 dprintf2("covering 0x%lx with bounds table entries\n", ptr);
1528 cover_buf_with_bt_entries((void *)ptr, PAGE_SIZE);
1529 }
1530 dprintf1("%s() end\n", __func__);
1531 printf("done with vaddr space fun\n");
1532}
1533
1534void mpx_table_test(void)
1535{
1536 printf("starting mpx bounds table test\n");
1537 run_timed_test(check_mpx_insns_and_tables);
1538 printf("done with mpx bounds table test\n");
1539}
1540
1541int main(int argc, char **argv)
1542{
1543 int unmaptest = 0;
1544 int vaddrexhaust = 0;
1545 int tabletest = 0;
1546 int i;
1547
1548 check_mpx_support();
1549 mpx_prepare();
1550 srandom(11179);
1551
1552 bd_incore();
1553 init();
1554 bd_incore();
1555
1556 trace_me();
1557
1558 xsave_state((void *)xsave_test_buf, 0x1f);
1559 if (!compare_context(xsave_test_buf))
1560 printf("Init failed\n");
1561
1562 for (i = 1; i < argc; i++) {
1563 if (!strcmp(argv[i], "unmaptest"))
1564 unmaptest = 1;
1565 if (!strcmp(argv[i], "vaddrexhaust"))
1566 vaddrexhaust = 1;
1567 if (!strcmp(argv[i], "tabletest"))
1568 tabletest = 1;
1569 }
1570 if (!(unmaptest || vaddrexhaust || tabletest)) {
1571 unmaptest = 1;
1572 /* vaddrexhaust = 1; */
1573 tabletest = 1;
1574 }
1575 if (unmaptest)
1576 check_bounds_table_frees();
1577 if (tabletest)
1578 mpx_table_test();
1579 if (vaddrexhaust)
1580 exhaust_vaddr_space();
1581 printf("%s completed successfully\n", argv[0]);
1582 exit(0);
1583}
1584
1585#include "mpx-dig.c"
diff --git a/tools/testing/selftests/x86/mpx-mm.h b/tools/testing/selftests/x86/mpx-mm.h
new file mode 100644
index 000000000000..af706a5398f7
--- /dev/null
+++ b/tools/testing/selftests/x86/mpx-mm.h
@@ -0,0 +1,9 @@
1#ifndef _MPX_MM_H
2#define _MPX_MM_H
3
4#define PAGE_SIZE 4096
5#define MB (1UL<<20)
6
7extern long nr_incore(void *ptr, unsigned long size_bytes);
8
9#endif /* _MPX_MM_H */
diff --git a/tools/testing/selftests/x86/pkey-helpers.h b/tools/testing/selftests/x86/pkey-helpers.h
new file mode 100644
index 000000000000..b20293956eec
--- /dev/null
+++ b/tools/testing/selftests/x86/pkey-helpers.h
@@ -0,0 +1,219 @@
1#ifndef _PKEYS_HELPER_H
2#define _PKEYS_HELPER_H
3#define _GNU_SOURCE
4#include <string.h>
5#include <stdarg.h>
6#include <stdio.h>
7#include <stdint.h>
8#include <stdbool.h>
9#include <signal.h>
10#include <assert.h>
11#include <stdlib.h>
12#include <ucontext.h>
13#include <sys/mman.h>
14
15#define NR_PKEYS 16
16#define PKRU_BITS_PER_PKEY 2
17
18#ifndef DEBUG_LEVEL
19#define DEBUG_LEVEL 0
20#endif
21#define DPRINT_IN_SIGNAL_BUF_SIZE 4096
22extern int dprint_in_signal;
23extern char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE];
24static inline void sigsafe_printf(const char *format, ...)
25{
26 va_list ap;
27
28 va_start(ap, format);
29 if (!dprint_in_signal) {
30 vprintf(format, ap);
31 } else {
32 int len = vsnprintf(dprint_in_signal_buffer,
33 DPRINT_IN_SIGNAL_BUF_SIZE,
34 format, ap);
35 /*
36 * len is amount that would have been printed,
37 * but actual write is truncated at BUF_SIZE.
38 */
39 if (len > DPRINT_IN_SIGNAL_BUF_SIZE)
40 len = DPRINT_IN_SIGNAL_BUF_SIZE;
41 write(1, dprint_in_signal_buffer, len);
42 }
43 va_end(ap);
44}
45#define dprintf_level(level, args...) do { \
46 if (level <= DEBUG_LEVEL) \
47 sigsafe_printf(args); \
48 fflush(NULL); \
49} while (0)
50#define dprintf0(args...) dprintf_level(0, args)
51#define dprintf1(args...) dprintf_level(1, args)
52#define dprintf2(args...) dprintf_level(2, args)
53#define dprintf3(args...) dprintf_level(3, args)
54#define dprintf4(args...) dprintf_level(4, args)
55
56extern unsigned int shadow_pkru;
57static inline unsigned int __rdpkru(void)
58{
59 unsigned int eax, edx;
60 unsigned int ecx = 0;
61 unsigned int pkru;
62
63 asm volatile(".byte 0x0f,0x01,0xee\n\t"
64 : "=a" (eax), "=d" (edx)
65 : "c" (ecx));
66 pkru = eax;
67 return pkru;
68}
69
70static inline unsigned int _rdpkru(int line)
71{
72 unsigned int pkru = __rdpkru();
73
74 dprintf4("rdpkru(line=%d) pkru: %x shadow: %x\n",
75 line, pkru, shadow_pkru);
76 assert(pkru == shadow_pkru);
77
78 return pkru;
79}
80
81#define rdpkru() _rdpkru(__LINE__)
82
83static inline void __wrpkru(unsigned int pkru)
84{
85 unsigned int eax = pkru;
86 unsigned int ecx = 0;
87 unsigned int edx = 0;
88
89 dprintf4("%s() changing %08x to %08x\n", __func__, __rdpkru(), pkru);
90 asm volatile(".byte 0x0f,0x01,0xef\n\t"
91 : : "a" (eax), "c" (ecx), "d" (edx));
92 assert(pkru == __rdpkru());
93}
94
95static inline void wrpkru(unsigned int pkru)
96{
97 dprintf4("%s() changing %08x to %08x\n", __func__, __rdpkru(), pkru);
98 /* will do the shadow check for us: */
99 rdpkru();
100 __wrpkru(pkru);
101 shadow_pkru = pkru;
102 dprintf4("%s(%08x) pkru: %08x\n", __func__, pkru, __rdpkru());
103}
104
105/*
106 * These are technically racy. since something could
107 * change PKRU between the read and the write.
108 */
109static inline void __pkey_access_allow(int pkey, int do_allow)
110{
111 unsigned int pkru = rdpkru();
112 int bit = pkey * 2;
113
114 if (do_allow)
115 pkru &= (1<<bit);
116 else
117 pkru |= (1<<bit);
118
119 dprintf4("pkru now: %08x\n", rdpkru());
120 wrpkru(pkru);
121}
122
123static inline void __pkey_write_allow(int pkey, int do_allow_write)
124{
125 long pkru = rdpkru();
126 int bit = pkey * 2 + 1;
127
128 if (do_allow_write)
129 pkru &= (1<<bit);
130 else
131 pkru |= (1<<bit);
132
133 wrpkru(pkru);
134 dprintf4("pkru now: %08x\n", rdpkru());
135}
136
137#define PROT_PKEY0 0x10 /* protection key value (bit 0) */
138#define PROT_PKEY1 0x20 /* protection key value (bit 1) */
139#define PROT_PKEY2 0x40 /* protection key value (bit 2) */
140#define PROT_PKEY3 0x80 /* protection key value (bit 3) */
141
142#define PAGE_SIZE 4096
143#define MB (1<<20)
144
145static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
146 unsigned int *ecx, unsigned int *edx)
147{
148 /* ecx is often an input as well as an output. */
149 asm volatile(
150 "cpuid;"
151 : "=a" (*eax),
152 "=b" (*ebx),
153 "=c" (*ecx),
154 "=d" (*edx)
155 : "0" (*eax), "2" (*ecx));
156}
157
158/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx) */
159#define X86_FEATURE_PKU (1<<3) /* Protection Keys for Userspace */
160#define X86_FEATURE_OSPKE (1<<4) /* OS Protection Keys Enable */
161
162static inline int cpu_has_pku(void)
163{
164 unsigned int eax;
165 unsigned int ebx;
166 unsigned int ecx;
167 unsigned int edx;
168
169 eax = 0x7;
170 ecx = 0x0;
171 __cpuid(&eax, &ebx, &ecx, &edx);
172
173 if (!(ecx & X86_FEATURE_PKU)) {
174 dprintf2("cpu does not have PKU\n");
175 return 0;
176 }
177 if (!(ecx & X86_FEATURE_OSPKE)) {
178 dprintf2("cpu does not have OSPKE\n");
179 return 0;
180 }
181 return 1;
182}
183
184#define XSTATE_PKRU_BIT (9)
185#define XSTATE_PKRU 0x200
186
187int pkru_xstate_offset(void)
188{
189 unsigned int eax;
190 unsigned int ebx;
191 unsigned int ecx;
192 unsigned int edx;
193 int xstate_offset;
194 int xstate_size;
195 unsigned long XSTATE_CPUID = 0xd;
196 int leaf;
197
198 /* assume that XSTATE_PKRU is set in XCR0 */
199 leaf = XSTATE_PKRU_BIT;
200 {
201 eax = XSTATE_CPUID;
202 ecx = leaf;
203 __cpuid(&eax, &ebx, &ecx, &edx);
204
205 if (leaf == XSTATE_PKRU_BIT) {
206 xstate_offset = ebx;
207 xstate_size = eax;
208 }
209 }
210
211 if (xstate_size == 0) {
212 printf("could not find size/offset of PKRU in xsave state\n");
213 return 0;
214 }
215
216 return xstate_offset;
217}
218
219#endif /* _PKEYS_HELPER_H */
diff --git a/tools/testing/selftests/x86/protection_keys.c b/tools/testing/selftests/x86/protection_keys.c
new file mode 100644
index 000000000000..bdd58c78902e
--- /dev/null
+++ b/tools/testing/selftests/x86/protection_keys.c
@@ -0,0 +1,1410 @@
1/*
2 * Tests x86 Memory Protection Keys (see Documentation/x86/protection-keys.txt)
3 *
4 * There are examples in here of:
5 * * how to set protection keys on memory
6 * * how to set/clear bits in PKRU (the rights register)
7 * * how to handle SEGV_PKRU signals and extract pkey-relevant
8 * information from the siginfo
9 *
10 * Things to add:
11 * make sure KSM and KSM COW breaking works
12 * prefault pages in at malloc, or not
13 * protect MPX bounds tables with protection keys?
14 * make sure VMA splitting/merging is working correctly
15 * OOMs can destroy mm->mmap (see exit_mmap()), so make sure it is immune to pkeys
16 * look for pkey "leaks" where it is still set on a VMA but "freed" back to the kernel
17 * do a plain mprotect() to a mprotect_pkey() area and make sure the pkey sticks
18 *
19 * Compile like this:
20 * gcc -o protection_keys -O2 -g -std=gnu99 -pthread -Wall protection_keys.c -lrt -ldl -lm
21 * gcc -m32 -o protection_keys_32 -O2 -g -std=gnu99 -pthread -Wall protection_keys.c -lrt -ldl -lm
22 */
23#define _GNU_SOURCE
24#include <errno.h>
25#include <linux/futex.h>
26#include <sys/time.h>
27#include <sys/syscall.h>
28#include <string.h>
29#include <stdio.h>
30#include <stdint.h>
31#include <stdbool.h>
32#include <signal.h>
33#include <assert.h>
34#include <stdlib.h>
35#include <ucontext.h>
36#include <sys/mman.h>
37#include <sys/types.h>
38#include <sys/wait.h>
39#include <sys/stat.h>
40#include <fcntl.h>
41#include <unistd.h>
42#include <sys/ptrace.h>
43#include <setjmp.h>
44
45#include "pkey-helpers.h"
46
47int iteration_nr = 1;
48int test_nr;
49
50unsigned int shadow_pkru;
51
52#define HPAGE_SIZE (1UL<<21)
53#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
54#define ALIGN_UP(x, align_to) (((x) + ((align_to)-1)) & ~((align_to)-1))
55#define ALIGN_DOWN(x, align_to) ((x) & ~((align_to)-1))
56#define ALIGN_PTR_UP(p, ptr_align_to) ((typeof(p))ALIGN_UP((unsigned long)(p), ptr_align_to))
57#define ALIGN_PTR_DOWN(p, ptr_align_to) ((typeof(p))ALIGN_DOWN((unsigned long)(p), ptr_align_to))
58#define __stringify_1(x...) #x
59#define __stringify(x...) __stringify_1(x)
60
61#define PTR_ERR_ENOTSUP ((void *)-ENOTSUP)
62
63int dprint_in_signal;
64char dprint_in_signal_buffer[DPRINT_IN_SIGNAL_BUF_SIZE];
65
66extern void abort_hooks(void);
67#define pkey_assert(condition) do { \
68 if (!(condition)) { \
69 dprintf0("assert() at %s::%d test_nr: %d iteration: %d\n", \
70 __FILE__, __LINE__, \
71 test_nr, iteration_nr); \
72 dprintf0("errno at assert: %d", errno); \
73 abort_hooks(); \
74 assert(condition); \
75 } \
76} while (0)
77#define raw_assert(cond) assert(cond)
78
79void cat_into_file(char *str, char *file)
80{
81 int fd = open(file, O_RDWR);
82 int ret;
83
84 dprintf2("%s(): writing '%s' to '%s'\n", __func__, str, file);
85 /*
86 * these need to be raw because they are called under
87 * pkey_assert()
88 */
89 raw_assert(fd >= 0);
90 ret = write(fd, str, strlen(str));
91 if (ret != strlen(str)) {
92 perror("write to file failed");
93 fprintf(stderr, "filename: '%s' str: '%s'\n", file, str);
94 raw_assert(0);
95 }
96 close(fd);
97}
98
99#if CONTROL_TRACING > 0
100static int warned_tracing;
101int tracing_root_ok(void)
102{
103 if (geteuid() != 0) {
104 if (!warned_tracing)
105 fprintf(stderr, "WARNING: not run as root, "
106 "can not do tracing control\n");
107 warned_tracing = 1;
108 return 0;
109 }
110 return 1;
111}
112#endif
113
114void tracing_on(void)
115{
116#if CONTROL_TRACING > 0
117#define TRACEDIR "/sys/kernel/debug/tracing"
118 char pidstr[32];
119
120 if (!tracing_root_ok())
121 return;
122
123 sprintf(pidstr, "%d", getpid());
124 cat_into_file("0", TRACEDIR "/tracing_on");
125 cat_into_file("\n", TRACEDIR "/trace");
126 if (1) {
127 cat_into_file("function_graph", TRACEDIR "/current_tracer");
128 cat_into_file("1", TRACEDIR "/options/funcgraph-proc");
129 } else {
130 cat_into_file("nop", TRACEDIR "/current_tracer");
131 }
132 cat_into_file(pidstr, TRACEDIR "/set_ftrace_pid");
133 cat_into_file("1", TRACEDIR "/tracing_on");
134 dprintf1("enabled tracing\n");
135#endif
136}
137
138void tracing_off(void)
139{
140#if CONTROL_TRACING > 0
141 if (!tracing_root_ok())
142 return;
143 cat_into_file("0", "/sys/kernel/debug/tracing/tracing_on");
144#endif
145}
146
147void abort_hooks(void)
148{
149 fprintf(stderr, "running %s()...\n", __func__);
150 tracing_off();
151#ifdef SLEEP_ON_ABORT
152 sleep(SLEEP_ON_ABORT);
153#endif
154}
155
156static inline void __page_o_noops(void)
157{
158 /* 8-bytes of instruction * 512 bytes = 1 page */
159 asm(".rept 512 ; nopl 0x7eeeeeee(%eax) ; .endr");
160}
161
162/*
163 * This attempts to have roughly a page of instructions followed by a few
164 * instructions that do a write, and another page of instructions. That
165 * way, we are pretty sure that the write is in the second page of
166 * instructions and has at least a page of padding behind it.
167 *
168 * *That* lets us be sure to madvise() away the write instruction, which
169 * will then fault, which makes sure that the fault code handles
170 * execute-only memory properly.
171 */
172__attribute__((__aligned__(PAGE_SIZE)))
173void lots_o_noops_around_write(int *write_to_me)
174{
175 dprintf3("running %s()\n", __func__);
176 __page_o_noops();
177 /* Assume this happens in the second page of instructions: */
178 *write_to_me = __LINE__;
179 /* pad out by another page: */
180 __page_o_noops();
181 dprintf3("%s() done\n", __func__);
182}
183
184/* Define some kernel-like types */
185#define u8 uint8_t
186#define u16 uint16_t
187#define u32 uint32_t
188#define u64 uint64_t
189
190#ifdef __i386__
191#define SYS_mprotect_key 380
192#define SYS_pkey_alloc 381
193#define SYS_pkey_free 382
194#define REG_IP_IDX REG_EIP
195#define si_pkey_offset 0x18
196#else
197#define SYS_mprotect_key 329
198#define SYS_pkey_alloc 330
199#define SYS_pkey_free 331
200#define REG_IP_IDX REG_RIP
201#define si_pkey_offset 0x20
202#endif
203
204void dump_mem(void *dumpme, int len_bytes)
205{
206 char *c = (void *)dumpme;
207 int i;
208
209 for (i = 0; i < len_bytes; i += sizeof(u64)) {
210 u64 *ptr = (u64 *)(c + i);
211 dprintf1("dump[%03d][@%p]: %016jx\n", i, ptr, *ptr);
212 }
213}
214
215#define __SI_FAULT (3 << 16)
216#define SEGV_BNDERR (__SI_FAULT|3) /* failed address bound checks */
217#define SEGV_PKUERR (__SI_FAULT|4)
218
219static char *si_code_str(int si_code)
220{
221 if (si_code & SEGV_MAPERR)
222 return "SEGV_MAPERR";
223 if (si_code & SEGV_ACCERR)
224 return "SEGV_ACCERR";
225 if (si_code & SEGV_BNDERR)
226 return "SEGV_BNDERR";
227 if (si_code & SEGV_PKUERR)
228 return "SEGV_PKUERR";
229 return "UNKNOWN";
230}
231
232int pkru_faults;
233int last_si_pkey = -1;
234void signal_handler(int signum, siginfo_t *si, void *vucontext)
235{
236 ucontext_t *uctxt = vucontext;
237 int trapno;
238 unsigned long ip;
239 char *fpregs;
240 u32 *pkru_ptr;
241 u64 si_pkey;
242 u32 *si_pkey_ptr;
243 int pkru_offset;
244 fpregset_t fpregset;
245
246 dprint_in_signal = 1;
247 dprintf1(">>>>===============SIGSEGV============================\n");
248 dprintf1("%s()::%d, pkru: 0x%x shadow: %x\n", __func__, __LINE__,
249 __rdpkru(), shadow_pkru);
250
251 trapno = uctxt->uc_mcontext.gregs[REG_TRAPNO];
252 ip = uctxt->uc_mcontext.gregs[REG_IP_IDX];
253 fpregset = uctxt->uc_mcontext.fpregs;
254 fpregs = (void *)fpregset;
255
256 dprintf2("%s() trapno: %d ip: 0x%lx info->si_code: %s/%d\n", __func__,
257 trapno, ip, si_code_str(si->si_code), si->si_code);
258#ifdef __i386__
259 /*
260 * 32-bit has some extra padding so that userspace can tell whether
261 * the XSTATE header is present in addition to the "legacy" FPU
262 * state. We just assume that it is here.
263 */
264 fpregs += 0x70;
265#endif
266 pkru_offset = pkru_xstate_offset();
267 pkru_ptr = (void *)(&fpregs[pkru_offset]);
268
269 dprintf1("siginfo: %p\n", si);
270 dprintf1(" fpregs: %p\n", fpregs);
271 /*
272 * If we got a PKRU fault, we *HAVE* to have at least one bit set in
273 * here.
274 */
275 dprintf1("pkru_xstate_offset: %d\n", pkru_xstate_offset());
276 if (DEBUG_LEVEL > 4)
277 dump_mem(pkru_ptr - 128, 256);
278 pkey_assert(*pkru_ptr);
279
280 si_pkey_ptr = (u32 *)(((u8 *)si) + si_pkey_offset);
281 dprintf1("si_pkey_ptr: %p\n", si_pkey_ptr);
282 dump_mem(si_pkey_ptr - 8, 24);
283 si_pkey = *si_pkey_ptr;
284 pkey_assert(si_pkey < NR_PKEYS);
285 last_si_pkey = si_pkey;
286
287 if ((si->si_code == SEGV_MAPERR) ||
288 (si->si_code == SEGV_ACCERR) ||
289 (si->si_code == SEGV_BNDERR)) {
290 printf("non-PK si_code, exiting...\n");
291 exit(4);
292 }
293
294 dprintf1("signal pkru from xsave: %08x\n", *pkru_ptr);
295 /* need __rdpkru() version so we do not do shadow_pkru checking */
296 dprintf1("signal pkru from pkru: %08x\n", __rdpkru());
297 dprintf1("si_pkey from siginfo: %jx\n", si_pkey);
298 *(u64 *)pkru_ptr = 0x00000000;
299 dprintf1("WARNING: set PRKU=0 to allow faulting instruction to continue\n");
300 pkru_faults++;
301 dprintf1("<<<<==================================================\n");
302 return;
303 if (trapno == 14) {
304 fprintf(stderr,
305 "ERROR: In signal handler, page fault, trapno = %d, ip = %016lx\n",
306 trapno, ip);
307 fprintf(stderr, "si_addr %p\n", si->si_addr);
308 fprintf(stderr, "REG_ERR: %lx\n",
309 (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
310 exit(1);
311 } else {
312 fprintf(stderr, "unexpected trap %d! at 0x%lx\n", trapno, ip);
313 fprintf(stderr, "si_addr %p\n", si->si_addr);
314 fprintf(stderr, "REG_ERR: %lx\n",
315 (unsigned long)uctxt->uc_mcontext.gregs[REG_ERR]);
316 exit(2);
317 }
318 dprint_in_signal = 0;
319}
320
321int wait_all_children(void)
322{
323 int status;
324 return waitpid(-1, &status, 0);
325}
326
327void sig_chld(int x)
328{
329 dprint_in_signal = 1;
330 dprintf2("[%d] SIGCHLD: %d\n", getpid(), x);
331 dprint_in_signal = 0;
332}
333
334void setup_sigsegv_handler(void)
335{
336 int r, rs;
337 struct sigaction newact;
338 struct sigaction oldact;
339
340 /* #PF is mapped to sigsegv */
341 int signum = SIGSEGV;
342
343 newact.sa_handler = 0;
344 newact.sa_sigaction = signal_handler;
345
346 /*sigset_t - signals to block while in the handler */
347 /* get the old signal mask. */
348 rs = sigprocmask(SIG_SETMASK, 0, &newact.sa_mask);
349 pkey_assert(rs == 0);
350
351 /* call sa_sigaction, not sa_handler*/
352 newact.sa_flags = SA_SIGINFO;
353
354 newact.sa_restorer = 0; /* void(*)(), obsolete */
355 r = sigaction(signum, &newact, &oldact);
356 r = sigaction(SIGALRM, &newact, &oldact);
357 pkey_assert(r == 0);
358}
359
360void setup_handlers(void)
361{
362 signal(SIGCHLD, &sig_chld);
363 setup_sigsegv_handler();
364}
365
366pid_t fork_lazy_child(void)
367{
368 pid_t forkret;
369
370 forkret = fork();
371 pkey_assert(forkret >= 0);
372 dprintf3("[%d] fork() ret: %d\n", getpid(), forkret);
373
374 if (!forkret) {
375 /* in the child */
376 while (1) {
377 dprintf1("child sleeping...\n");
378 sleep(30);
379 }
380 }
381 return forkret;
382}
383
384void davecmp(void *_a, void *_b, int len)
385{
386 int i;
387 unsigned long *a = _a;
388 unsigned long *b = _b;
389
390 for (i = 0; i < len / sizeof(*a); i++) {
391 if (a[i] == b[i])
392 continue;
393
394 dprintf3("[%3d]: a: %016lx b: %016lx\n", i, a[i], b[i]);
395 }
396}
397
398void dumpit(char *f)
399{
400 int fd = open(f, O_RDONLY);
401 char buf[100];
402 int nr_read;
403
404 dprintf2("maps fd: %d\n", fd);
405 do {
406 nr_read = read(fd, &buf[0], sizeof(buf));
407 write(1, buf, nr_read);
408 } while (nr_read > 0);
409 close(fd);
410}
411
412#define PKEY_DISABLE_ACCESS 0x1
413#define PKEY_DISABLE_WRITE 0x2
414
415u32 pkey_get(int pkey, unsigned long flags)
416{
417 u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE);
418 u32 pkru = __rdpkru();
419 u32 shifted_pkru;
420 u32 masked_pkru;
421
422 dprintf1("%s(pkey=%d, flags=%lx) = %x / %d\n",
423 __func__, pkey, flags, 0, 0);
424 dprintf2("%s() raw pkru: %x\n", __func__, pkru);
425
426 shifted_pkru = (pkru >> (pkey * PKRU_BITS_PER_PKEY));
427 dprintf2("%s() shifted_pkru: %x\n", __func__, shifted_pkru);
428 masked_pkru = shifted_pkru & mask;
429 dprintf2("%s() masked pkru: %x\n", __func__, masked_pkru);
430 /*
431 * shift down the relevant bits to the lowest two, then
432 * mask off all the other high bits.
433 */
434 return masked_pkru;
435}
436
437int pkey_set(int pkey, unsigned long rights, unsigned long flags)
438{
439 u32 mask = (PKEY_DISABLE_ACCESS|PKEY_DISABLE_WRITE);
440 u32 old_pkru = __rdpkru();
441 u32 new_pkru;
442
443 /* make sure that 'rights' only contains the bits we expect: */
444 assert(!(rights & ~mask));
445
446 /* copy old pkru */
447 new_pkru = old_pkru;
448 /* mask out bits from pkey in old value: */
449 new_pkru &= ~(mask << (pkey * PKRU_BITS_PER_PKEY));
450 /* OR in new bits for pkey: */
451 new_pkru |= (rights << (pkey * PKRU_BITS_PER_PKEY));
452
453 __wrpkru(new_pkru);
454
455 dprintf3("%s(pkey=%d, rights=%lx, flags=%lx) = %x pkru now: %x old_pkru: %x\n",
456 __func__, pkey, rights, flags, 0, __rdpkru(), old_pkru);
457 return 0;
458}
459
460void pkey_disable_set(int pkey, int flags)
461{
462 unsigned long syscall_flags = 0;
463 int ret;
464 int pkey_rights;
465 u32 orig_pkru;
466
467 dprintf1("START->%s(%d, 0x%x)\n", __func__,
468 pkey, flags);
469 pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
470
471 pkey_rights = pkey_get(pkey, syscall_flags);
472
473 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__,
474 pkey, pkey, pkey_rights);
475 pkey_assert(pkey_rights >= 0);
476
477 pkey_rights |= flags;
478
479 ret = pkey_set(pkey, pkey_rights, syscall_flags);
480 assert(!ret);
481 /*pkru and flags have the same format */
482 shadow_pkru |= flags << (pkey * 2);
483 dprintf1("%s(%d) shadow: 0x%x\n", __func__, pkey, shadow_pkru);
484
485 pkey_assert(ret >= 0);
486
487 pkey_rights = pkey_get(pkey, syscall_flags);
488 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__,
489 pkey, pkey, pkey_rights);
490
491 dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru());
492 if (flags)
493 pkey_assert(rdpkru() > orig_pkru);
494 dprintf1("END<---%s(%d, 0x%x)\n", __func__,
495 pkey, flags);
496}
497
498void pkey_disable_clear(int pkey, int flags)
499{
500 unsigned long syscall_flags = 0;
501 int ret;
502 int pkey_rights = pkey_get(pkey, syscall_flags);
503 u32 orig_pkru = rdpkru();
504
505 pkey_assert(flags & (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE));
506
507 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__,
508 pkey, pkey, pkey_rights);
509 pkey_assert(pkey_rights >= 0);
510
511 pkey_rights |= flags;
512
513 ret = pkey_set(pkey, pkey_rights, 0);
514 /* pkru and flags have the same format */
515 shadow_pkru &= ~(flags << (pkey * 2));
516 pkey_assert(ret >= 0);
517
518 pkey_rights = pkey_get(pkey, syscall_flags);
519 dprintf1("%s(%d) pkey_get(%d): %x\n", __func__,
520 pkey, pkey, pkey_rights);
521
522 dprintf1("%s(%d) pkru: 0x%x\n", __func__, pkey, rdpkru());
523 if (flags)
524 assert(rdpkru() > orig_pkru);
525}
526
527void pkey_write_allow(int pkey)
528{
529 pkey_disable_clear(pkey, PKEY_DISABLE_WRITE);
530}
531void pkey_write_deny(int pkey)
532{
533 pkey_disable_set(pkey, PKEY_DISABLE_WRITE);
534}
535void pkey_access_allow(int pkey)
536{
537 pkey_disable_clear(pkey, PKEY_DISABLE_ACCESS);
538}
539void pkey_access_deny(int pkey)
540{
541 pkey_disable_set(pkey, PKEY_DISABLE_ACCESS);
542}
543
544int sys_mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
545 unsigned long pkey)
546{
547 int sret;
548
549 dprintf2("%s(0x%p, %zx, prot=%lx, pkey=%lx)\n", __func__,
550 ptr, size, orig_prot, pkey);
551
552 errno = 0;
553 sret = syscall(SYS_mprotect_key, ptr, size, orig_prot, pkey);
554 if (errno) {
555 dprintf2("SYS_mprotect_key sret: %d\n", sret);
556 dprintf2("SYS_mprotect_key prot: 0x%lx\n", orig_prot);
557 dprintf2("SYS_mprotect_key failed, errno: %d\n", errno);
558 if (DEBUG_LEVEL >= 2)
559 perror("SYS_mprotect_pkey");
560 }
561 return sret;
562}
563
564int sys_pkey_alloc(unsigned long flags, unsigned long init_val)
565{
566 int ret = syscall(SYS_pkey_alloc, flags, init_val);
567 dprintf1("%s(flags=%lx, init_val=%lx) syscall ret: %d errno: %d\n",
568 __func__, flags, init_val, ret, errno);
569 return ret;
570}
571
572int alloc_pkey(void)
573{
574 int ret;
575 unsigned long init_val = 0x0;
576
577 dprintf1("alloc_pkey()::%d, pkru: 0x%x shadow: %x\n",
578 __LINE__, __rdpkru(), shadow_pkru);
579 ret = sys_pkey_alloc(0, init_val);
580 /*
581 * pkey_alloc() sets PKRU, so we need to reflect it in
582 * shadow_pkru:
583 */
584 dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
585 __LINE__, ret, __rdpkru(), shadow_pkru);
586 if (ret) {
587 /* clear both the bits: */
588 shadow_pkru &= ~(0x3 << (ret * 2));
589 dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
590 __LINE__, ret, __rdpkru(), shadow_pkru);
591 /*
592 * move the new state in from init_val
593 * (remember, we cheated and init_val == pkru format)
594 */
595 shadow_pkru |= (init_val << (ret * 2));
596 }
597 dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
598 __LINE__, ret, __rdpkru(), shadow_pkru);
599 dprintf1("alloc_pkey()::%d errno: %d\n", __LINE__, errno);
600 /* for shadow checking: */
601 rdpkru();
602 dprintf4("alloc_pkey()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n",
603 __LINE__, ret, __rdpkru(), shadow_pkru);
604 return ret;
605}
606
607int sys_pkey_free(unsigned long pkey)
608{
609 int ret = syscall(SYS_pkey_free, pkey);
610 dprintf1("%s(pkey=%ld) syscall ret: %d\n", __func__, pkey, ret);
611 return ret;
612}
613
614/*
615 * I had a bug where pkey bits could be set by mprotect() but
616 * not cleared. This ensures we get lots of random bit sets
617 * and clears on the vma and pte pkey bits.
618 */
619int alloc_random_pkey(void)
620{
621 int max_nr_pkey_allocs;
622 int ret;
623 int i;
624 int alloced_pkeys[NR_PKEYS];
625 int nr_alloced = 0;
626 int random_index;
627 memset(alloced_pkeys, 0, sizeof(alloced_pkeys));
628
629 /* allocate every possible key and make a note of which ones we got */
630 max_nr_pkey_allocs = NR_PKEYS;
631 max_nr_pkey_allocs = 1;
632 for (i = 0; i < max_nr_pkey_allocs; i++) {
633 int new_pkey = alloc_pkey();
634 if (new_pkey < 0)
635 break;
636 alloced_pkeys[nr_alloced++] = new_pkey;
637 }
638
639 pkey_assert(nr_alloced > 0);
640 /* select a random one out of the allocated ones */
641 random_index = rand() % nr_alloced;
642 ret = alloced_pkeys[random_index];
643 /* now zero it out so we don't free it next */
644 alloced_pkeys[random_index] = 0;
645
646 /* go through the allocated ones that we did not want and free them */
647 for (i = 0; i < nr_alloced; i++) {
648 int free_ret;
649 if (!alloced_pkeys[i])
650 continue;
651 free_ret = sys_pkey_free(alloced_pkeys[i]);
652 pkey_assert(!free_ret);
653 }
654 dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
655 __LINE__, ret, __rdpkru(), shadow_pkru);
656 return ret;
657}
658
659int mprotect_pkey(void *ptr, size_t size, unsigned long orig_prot,
660 unsigned long pkey)
661{
662 int nr_iterations = random() % 100;
663 int ret;
664
665 while (0) {
666 int rpkey = alloc_random_pkey();
667 ret = sys_mprotect_pkey(ptr, size, orig_prot, pkey);
668 dprintf1("sys_mprotect_pkey(%p, %zx, prot=0x%lx, pkey=%ld) ret: %d\n",
669 ptr, size, orig_prot, pkey, ret);
670 if (nr_iterations-- < 0)
671 break;
672
673 dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
674 __LINE__, ret, __rdpkru(), shadow_pkru);
675 sys_pkey_free(rpkey);
676 dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
677 __LINE__, ret, __rdpkru(), shadow_pkru);
678 }
679 pkey_assert(pkey < NR_PKEYS);
680
681 ret = sys_mprotect_pkey(ptr, size, orig_prot, pkey);
682 dprintf1("mprotect_pkey(%p, %zx, prot=0x%lx, pkey=%ld) ret: %d\n",
683 ptr, size, orig_prot, pkey, ret);
684 pkey_assert(!ret);
685 dprintf1("%s()::%d, ret: %d pkru: 0x%x shadow: 0x%x\n", __func__,
686 __LINE__, ret, __rdpkru(), shadow_pkru);
687 return ret;
688}
689
690struct pkey_malloc_record {
691 void *ptr;
692 long size;
693};
694struct pkey_malloc_record *pkey_malloc_records;
695long nr_pkey_malloc_records;
696void record_pkey_malloc(void *ptr, long size)
697{
698 long i;
699 struct pkey_malloc_record *rec = NULL;
700
701 for (i = 0; i < nr_pkey_malloc_records; i++) {
702 rec = &pkey_malloc_records[i];
703 /* find a free record */
704 if (rec)
705 break;
706 }
707 if (!rec) {
708 /* every record is full */
709 size_t old_nr_records = nr_pkey_malloc_records;
710 size_t new_nr_records = (nr_pkey_malloc_records * 2 + 1);
711 size_t new_size = new_nr_records * sizeof(struct pkey_malloc_record);
712 dprintf2("new_nr_records: %zd\n", new_nr_records);
713 dprintf2("new_size: %zd\n", new_size);
714 pkey_malloc_records = realloc(pkey_malloc_records, new_size);
715 pkey_assert(pkey_malloc_records != NULL);
716 rec = &pkey_malloc_records[nr_pkey_malloc_records];
717 /*
718 * realloc() does not initialize memory, so zero it from
719 * the first new record all the way to the end.
720 */
721 for (i = 0; i < new_nr_records - old_nr_records; i++)
722 memset(rec + i, 0, sizeof(*rec));
723 }
724 dprintf3("filling malloc record[%d/%p]: {%p, %ld}\n",
725 (int)(rec - pkey_malloc_records), rec, ptr, size);
726 rec->ptr = ptr;
727 rec->size = size;
728 nr_pkey_malloc_records++;
729}
730
731void free_pkey_malloc(void *ptr)
732{
733 long i;
734 int ret;
735 dprintf3("%s(%p)\n", __func__, ptr);
736 for (i = 0; i < nr_pkey_malloc_records; i++) {
737 struct pkey_malloc_record *rec = &pkey_malloc_records[i];
738 dprintf4("looking for ptr %p at record[%ld/%p]: {%p, %ld}\n",
739 ptr, i, rec, rec->ptr, rec->size);
740 if ((ptr < rec->ptr) ||
741 (ptr >= rec->ptr + rec->size))
742 continue;
743
744 dprintf3("found ptr %p at record[%ld/%p]: {%p, %ld}\n",
745 ptr, i, rec, rec->ptr, rec->size);
746 nr_pkey_malloc_records--;
747 ret = munmap(rec->ptr, rec->size);
748 dprintf3("munmap ret: %d\n", ret);
749 pkey_assert(!ret);
750 dprintf3("clearing rec->ptr, rec: %p\n", rec);
751 rec->ptr = NULL;
752 dprintf3("done clearing rec->ptr, rec: %p\n", rec);
753 return;
754 }
755 pkey_assert(false);
756}
757
758
759void *malloc_pkey_with_mprotect(long size, int prot, u16 pkey)
760{
761 void *ptr;
762 int ret;
763
764 rdpkru();
765 dprintf1("doing %s(size=%ld, prot=0x%x, pkey=%d)\n", __func__,
766 size, prot, pkey);
767 pkey_assert(pkey < NR_PKEYS);
768 ptr = mmap(NULL, size, prot, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
769 pkey_assert(ptr != (void *)-1);
770 ret = mprotect_pkey((void *)ptr, PAGE_SIZE, prot, pkey);
771 pkey_assert(!ret);
772 record_pkey_malloc(ptr, size);
773 rdpkru();
774
775 dprintf1("%s() for pkey %d @ %p\n", __func__, pkey, ptr);
776 return ptr;
777}
778
779void *malloc_pkey_anon_huge(long size, int prot, u16 pkey)
780{
781 int ret;
782 void *ptr;
783
784 dprintf1("doing %s(size=%ld, prot=0x%x, pkey=%d)\n", __func__,
785 size, prot, pkey);
786 /*
787 * Guarantee we can fit at least one huge page in the resulting
788 * allocation by allocating space for 2:
789 */
790 size = ALIGN_UP(size, HPAGE_SIZE * 2);
791 ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
792 pkey_assert(ptr != (void *)-1);
793 record_pkey_malloc(ptr, size);
794 mprotect_pkey(ptr, size, prot, pkey);
795
796 dprintf1("unaligned ptr: %p\n", ptr);
797 ptr = ALIGN_PTR_UP(ptr, HPAGE_SIZE);
798 dprintf1(" aligned ptr: %p\n", ptr);
799 ret = madvise(ptr, HPAGE_SIZE, MADV_HUGEPAGE);
800 dprintf1("MADV_HUGEPAGE ret: %d\n", ret);
801 ret = madvise(ptr, HPAGE_SIZE, MADV_WILLNEED);
802 dprintf1("MADV_WILLNEED ret: %d\n", ret);
803 memset(ptr, 0, HPAGE_SIZE);
804
805 dprintf1("mmap()'d thp for pkey %d @ %p\n", pkey, ptr);
806 return ptr;
807}
808
809int hugetlb_setup_ok;
810#define GET_NR_HUGE_PAGES 10
811void setup_hugetlbfs(void)
812{
813 int err;
814 int fd;
815 int validated_nr_pages;
816 int i;
817 char buf[] = "123";
818
819 if (geteuid() != 0) {
820 fprintf(stderr, "WARNING: not run as root, can not do hugetlb test\n");
821 return;
822 }
823
824 cat_into_file(__stringify(GET_NR_HUGE_PAGES), "/proc/sys/vm/nr_hugepages");
825
826 /*
827 * Now go make sure that we got the pages and that they
828 * are 2M pages. Someone might have made 1G the default.
829 */
830 fd = open("/sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages", O_RDONLY);
831 if (fd < 0) {
832 perror("opening sysfs 2M hugetlb config");
833 return;
834 }
835
836 /* -1 to guarantee leaving the trailing \0 */
837 err = read(fd, buf, sizeof(buf)-1);
838 close(fd);
839 if (err <= 0) {
840 perror("reading sysfs 2M hugetlb config");
841 return;
842 }
843
844 if (atoi(buf) != GET_NR_HUGE_PAGES) {
845 fprintf(stderr, "could not confirm 2M pages, got: '%s' expected %d\n",
846 buf, GET_NR_HUGE_PAGES);
847 return;
848 }
849
850 hugetlb_setup_ok = 1;
851}
852
853void *malloc_pkey_hugetlb(long size, int prot, u16 pkey)
854{
855 void *ptr;
856 int flags = MAP_ANONYMOUS|MAP_PRIVATE|MAP_HUGETLB;
857
858 if (!hugetlb_setup_ok)
859 return PTR_ERR_ENOTSUP;
860
861 dprintf1("doing %s(%ld, %x, %x)\n", __func__, size, prot, pkey);
862 size = ALIGN_UP(size, HPAGE_SIZE * 2);
863 pkey_assert(pkey < NR_PKEYS);
864 ptr = mmap(NULL, size, PROT_NONE, flags, -1, 0);
865 pkey_assert(ptr != (void *)-1);
866 mprotect_pkey(ptr, size, prot, pkey);
867
868 record_pkey_malloc(ptr, size);
869
870 dprintf1("mmap()'d hugetlbfs for pkey %d @ %p\n", pkey, ptr);
871 return ptr;
872}
873
874void *malloc_pkey_mmap_dax(long size, int prot, u16 pkey)
875{
876 void *ptr;
877 int fd;
878
879 dprintf1("doing %s(size=%ld, prot=0x%x, pkey=%d)\n", __func__,
880 size, prot, pkey);
881 pkey_assert(pkey < NR_PKEYS);
882 fd = open("/dax/foo", O_RDWR);
883 pkey_assert(fd >= 0);
884
885 ptr = mmap(0, size, prot, MAP_SHARED, fd, 0);
886 pkey_assert(ptr != (void *)-1);
887
888 mprotect_pkey(ptr, size, prot, pkey);
889
890 record_pkey_malloc(ptr, size);
891
892 dprintf1("mmap()'d for pkey %d @ %p\n", pkey, ptr);
893 close(fd);
894 return ptr;
895}
896
897void *(*pkey_malloc[])(long size, int prot, u16 pkey) = {
898
899 malloc_pkey_with_mprotect,
900 malloc_pkey_anon_huge,
901 malloc_pkey_hugetlb
902/* can not do direct with the pkey_mprotect() API:
903 malloc_pkey_mmap_direct,
904 malloc_pkey_mmap_dax,
905*/
906};
907
908void *malloc_pkey(long size, int prot, u16 pkey)
909{
910 void *ret;
911 static int malloc_type;
912 int nr_malloc_types = ARRAY_SIZE(pkey_malloc);
913
914 pkey_assert(pkey < NR_PKEYS);
915
916 while (1) {
917 pkey_assert(malloc_type < nr_malloc_types);
918
919 ret = pkey_malloc[malloc_type](size, prot, pkey);
920 pkey_assert(ret != (void *)-1);
921
922 malloc_type++;
923 if (malloc_type >= nr_malloc_types)
924 malloc_type = (random()%nr_malloc_types);
925
926 /* try again if the malloc_type we tried is unsupported */
927 if (ret == PTR_ERR_ENOTSUP)
928 continue;
929
930 break;
931 }
932
933 dprintf3("%s(%ld, prot=%x, pkey=%x) returning: %p\n", __func__,
934 size, prot, pkey, ret);
935 return ret;
936}
937
938int last_pkru_faults;
939void expected_pk_fault(int pkey)
940{
941 dprintf2("%s(): last_pkru_faults: %d pkru_faults: %d\n",
942 __func__, last_pkru_faults, pkru_faults);
943 dprintf2("%s(%d): last_si_pkey: %d\n", __func__, pkey, last_si_pkey);
944 pkey_assert(last_pkru_faults + 1 == pkru_faults);
945 pkey_assert(last_si_pkey == pkey);
946 /*
947 * The signal handler shold have cleared out PKRU to let the
948 * test program continue. We now have to restore it.
949 */
950 if (__rdpkru() != 0)
951 pkey_assert(0);
952
953 __wrpkru(shadow_pkru);
954 dprintf1("%s() set PKRU=%x to restore state after signal nuked it\n",
955 __func__, shadow_pkru);
956 last_pkru_faults = pkru_faults;
957 last_si_pkey = -1;
958}
959
960void do_not_expect_pk_fault(void)
961{
962 pkey_assert(last_pkru_faults == pkru_faults);
963}
964
965int test_fds[10] = { -1 };
966int nr_test_fds;
967void __save_test_fd(int fd)
968{
969 pkey_assert(fd >= 0);
970 pkey_assert(nr_test_fds < ARRAY_SIZE(test_fds));
971 test_fds[nr_test_fds] = fd;
972 nr_test_fds++;
973}
974
975int get_test_read_fd(void)
976{
977 int test_fd = open("/etc/passwd", O_RDONLY);
978 __save_test_fd(test_fd);
979 return test_fd;
980}
981
982void close_test_fds(void)
983{
984 int i;
985
986 for (i = 0; i < nr_test_fds; i++) {
987 if (test_fds[i] < 0)
988 continue;
989 close(test_fds[i]);
990 test_fds[i] = -1;
991 }
992 nr_test_fds = 0;
993}
994
995#define barrier() __asm__ __volatile__("": : :"memory")
996__attribute__((noinline)) int read_ptr(int *ptr)
997{
998 /*
999 * Keep GCC from optimizing this away somehow
1000 */
1001 barrier();
1002 return *ptr;
1003}
1004
1005void test_read_of_write_disabled_region(int *ptr, u16 pkey)
1006{
1007 int ptr_contents;
1008
1009 dprintf1("disabling write access to PKEY[1], doing read\n");
1010 pkey_write_deny(pkey);
1011 ptr_contents = read_ptr(ptr);
1012 dprintf1("*ptr: %d\n", ptr_contents);
1013 dprintf1("\n");
1014}
1015void test_read_of_access_disabled_region(int *ptr, u16 pkey)
1016{
1017 int ptr_contents;
1018
1019 dprintf1("disabling access to PKEY[%02d], doing read @ %p\n", pkey, ptr);
1020 rdpkru();
1021 pkey_access_deny(pkey);
1022 ptr_contents = read_ptr(ptr);
1023 dprintf1("*ptr: %d\n", ptr_contents);
1024 expected_pk_fault(pkey);
1025}
1026void test_write_of_write_disabled_region(int *ptr, u16 pkey)
1027{
1028 dprintf1("disabling write access to PKEY[%02d], doing write\n", pkey);
1029 pkey_write_deny(pkey);
1030 *ptr = __LINE__;
1031 expected_pk_fault(pkey);
1032}
1033void test_write_of_access_disabled_region(int *ptr, u16 pkey)
1034{
1035 dprintf1("disabling access to PKEY[%02d], doing write\n", pkey);
1036 pkey_access_deny(pkey);
1037 *ptr = __LINE__;
1038 expected_pk_fault(pkey);
1039}
1040void test_kernel_write_of_access_disabled_region(int *ptr, u16 pkey)
1041{
1042 int ret;
1043 int test_fd = get_test_read_fd();
1044
1045 dprintf1("disabling access to PKEY[%02d], "
1046 "having kernel read() to buffer\n", pkey);
1047 pkey_access_deny(pkey);
1048 ret = read(test_fd, ptr, 1);
1049 dprintf1("read ret: %d\n", ret);
1050 pkey_assert(ret);
1051}
1052void test_kernel_write_of_write_disabled_region(int *ptr, u16 pkey)
1053{
1054 int ret;
1055 int test_fd = get_test_read_fd();
1056
1057 pkey_write_deny(pkey);
1058 ret = read(test_fd, ptr, 100);
1059 dprintf1("read ret: %d\n", ret);
1060 if (ret < 0 && (DEBUG_LEVEL > 0))
1061 perror("verbose read result (OK for this to be bad)");
1062 pkey_assert(ret);
1063}
1064
1065void test_kernel_gup_of_access_disabled_region(int *ptr, u16 pkey)
1066{
1067 int pipe_ret, vmsplice_ret;
1068 struct iovec iov;
1069 int pipe_fds[2];
1070
1071 pipe_ret = pipe(pipe_fds);
1072
1073 pkey_assert(pipe_ret == 0);
1074 dprintf1("disabling access to PKEY[%02d], "
1075 "having kernel vmsplice from buffer\n", pkey);
1076 pkey_access_deny(pkey);
1077 iov.iov_base = ptr;
1078 iov.iov_len = PAGE_SIZE;
1079 vmsplice_ret = vmsplice(pipe_fds[1], &iov, 1, SPLICE_F_GIFT);
1080 dprintf1("vmsplice() ret: %d\n", vmsplice_ret);
1081 pkey_assert(vmsplice_ret == -1);
1082
1083 close(pipe_fds[0]);
1084 close(pipe_fds[1]);
1085}
1086
1087void test_kernel_gup_write_to_write_disabled_region(int *ptr, u16 pkey)
1088{
1089 int ignored = 0xdada;
1090 int futex_ret;
1091 int some_int = __LINE__;
1092
1093 dprintf1("disabling write to PKEY[%02d], "
1094 "doing futex gunk in buffer\n", pkey);
1095 *ptr = some_int;
1096 pkey_write_deny(pkey);
1097 futex_ret = syscall(SYS_futex, ptr, FUTEX_WAIT, some_int-1, NULL,
1098 &ignored, ignored);
1099 if (DEBUG_LEVEL > 0)
1100 perror("futex");
1101 dprintf1("futex() ret: %d\n", futex_ret);
1102}
1103
1104/* Assumes that all pkeys other than 'pkey' are unallocated */
1105void test_pkey_syscalls_on_non_allocated_pkey(int *ptr, u16 pkey)
1106{
1107 int err;
1108 int i;
1109
1110 /* Note: 0 is the default pkey, so don't mess with it */
1111 for (i = 1; i < NR_PKEYS; i++) {
1112 if (pkey == i)
1113 continue;
1114
1115 dprintf1("trying get/set/free to non-allocated pkey: %2d\n", i);
1116 err = sys_pkey_free(i);
1117 pkey_assert(err);
1118
1119 /* not enforced when pkey_get() is not a syscall
1120 err = pkey_get(i, 0);
1121 pkey_assert(err < 0);
1122 */
1123
1124 err = sys_pkey_free(i);
1125 pkey_assert(err);
1126
1127 err = sys_mprotect_pkey(ptr, PAGE_SIZE, PROT_READ, i);
1128 pkey_assert(err);
1129 }
1130}
1131
1132/* Assumes that all pkeys other than 'pkey' are unallocated */
1133void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
1134{
1135 int err;
1136 int bad_flag = (PKEY_DISABLE_ACCESS | PKEY_DISABLE_WRITE) + 1;
1137 int bad_pkey = NR_PKEYS+99;
1138
1139 /* not enforced when pkey_get() is not a syscall
1140 err = pkey_get(bad_pkey, bad_flag);
1141 pkey_assert(err < 0);
1142 */
1143
1144 /* pass a known-invalid pkey in: */
1145 err = sys_mprotect_pkey(ptr, PAGE_SIZE, PROT_READ, bad_pkey);
1146 pkey_assert(err);
1147}
1148
1149/* Assumes that all pkeys other than 'pkey' are unallocated */
1150void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
1151{
1152 unsigned long flags;
1153 unsigned long init_val;
1154 int err;
1155 int allocated_pkeys[NR_PKEYS] = {0};
1156 int nr_allocated_pkeys = 0;
1157 int i;
1158
1159 for (i = 0; i < NR_PKEYS*2; i++) {
1160 int new_pkey;
1161 dprintf1("%s() alloc loop: %d\n", __func__, i);
1162 new_pkey = alloc_pkey();
1163 dprintf4("%s()::%d, err: %d pkru: 0x%x shadow: 0x%x\n", __func__,
1164 __LINE__, err, __rdpkru(), shadow_pkru);
1165 rdpkru(); /* for shadow checking */
1166 dprintf2("%s() errno: %d ENOSPC: %d\n", __func__, errno, ENOSPC);
1167 if ((new_pkey == -1) && (errno == ENOSPC)) {
1168 dprintf2("%s() failed to allocate pkey after %d tries\n",
1169 __func__, nr_allocated_pkeys);
1170 break;
1171 }
1172 pkey_assert(nr_allocated_pkeys < NR_PKEYS);
1173 allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
1174 }
1175
1176 dprintf3("%s()::%d\n", __func__, __LINE__);
1177
1178 /*
1179 * ensure it did not reach the end of the loop without
1180 * failure:
1181 */
1182 pkey_assert(i < NR_PKEYS*2);
1183
1184 /*
1185 * There are 16 pkeys supported in hardware. One is taken
1186 * up for the default (0) and another can be taken up by
1187 * an execute-only mapping. Ensure that we can allocate
1188 * at least 14 (16-2).
1189 */
1190 pkey_assert(i >= NR_PKEYS-2);
1191
1192 for (i = 0; i < nr_allocated_pkeys; i++) {
1193 err = sys_pkey_free(allocated_pkeys[i]);
1194 pkey_assert(!err);
1195 rdpkru(); /* for shadow checking */
1196 }
1197}
1198
1199void test_ptrace_of_child(int *ptr, u16 pkey)
1200{
1201 __attribute__((__unused__)) int peek_result;
1202 pid_t child_pid;
1203 void *ignored = 0;
1204 long ret;
1205 int status;
1206 /*
1207 * This is the "control" for our little expermient. Make sure
1208 * we can always access it when ptracing.
1209 */
1210 int *plain_ptr_unaligned = malloc(HPAGE_SIZE);
1211 int *plain_ptr = ALIGN_PTR_UP(plain_ptr_unaligned, PAGE_SIZE);
1212
1213 /*
1214 * Fork a child which is an exact copy of this process, of course.
1215 * That means we can do all of our tests via ptrace() and then plain
1216 * memory access and ensure they work differently.
1217 */
1218 child_pid = fork_lazy_child();
1219 dprintf1("[%d] child pid: %d\n", getpid(), child_pid);
1220
1221 ret = ptrace(PTRACE_ATTACH, child_pid, ignored, ignored);
1222 if (ret)
1223 perror("attach");
1224 dprintf1("[%d] attach ret: %ld %d\n", getpid(), ret, __LINE__);
1225 pkey_assert(ret != -1);
1226 ret = waitpid(child_pid, &status, WUNTRACED);
1227 if ((ret != child_pid) || !(WIFSTOPPED(status))) {
1228 fprintf(stderr, "weird waitpid result %ld stat %x\n",
1229 ret, status);
1230 pkey_assert(0);
1231 }
1232 dprintf2("waitpid ret: %ld\n", ret);
1233 dprintf2("waitpid status: %d\n", status);
1234
1235 pkey_access_deny(pkey);
1236 pkey_write_deny(pkey);
1237
1238 /* Write access, untested for now:
1239 ret = ptrace(PTRACE_POKEDATA, child_pid, peek_at, data);
1240 pkey_assert(ret != -1);
1241 dprintf1("poke at %p: %ld\n", peek_at, ret);
1242 */
1243
1244 /*
1245 * Try to access the pkey-protected "ptr" via ptrace:
1246 */
1247 ret = ptrace(PTRACE_PEEKDATA, child_pid, ptr, ignored);
1248 /* expect it to work, without an error: */
1249 pkey_assert(ret != -1);
1250 /* Now access from the current task, and expect an exception: */
1251 peek_result = read_ptr(ptr);
1252 expected_pk_fault(pkey);
1253
1254 /*
1255 * Try to access the NON-pkey-protected "plain_ptr" via ptrace:
1256 */
1257 ret = ptrace(PTRACE_PEEKDATA, child_pid, plain_ptr, ignored);
1258 /* expect it to work, without an error: */
1259 pkey_assert(ret != -1);
1260 /* Now access from the current task, and expect NO exception: */
1261 peek_result = read_ptr(plain_ptr);
1262 do_not_expect_pk_fault();
1263
1264 ret = ptrace(PTRACE_DETACH, child_pid, ignored, 0);
1265 pkey_assert(ret != -1);
1266
1267 ret = kill(child_pid, SIGKILL);
1268 pkey_assert(ret != -1);
1269
1270 wait(&status);
1271
1272 free(plain_ptr_unaligned);
1273}
1274
1275void test_executing_on_unreadable_memory(int *ptr, u16 pkey)
1276{
1277 void *p1;
1278 int scratch;
1279 int ptr_contents;
1280 int ret;
1281
1282 p1 = ALIGN_PTR_UP(&lots_o_noops_around_write, PAGE_SIZE);
1283 dprintf3("&lots_o_noops: %p\n", &lots_o_noops_around_write);
1284 /* lots_o_noops_around_write should be page-aligned already */
1285 assert(p1 == &lots_o_noops_around_write);
1286
1287 /* Point 'p1' at the *second* page of the function: */
1288 p1 += PAGE_SIZE;
1289
1290 madvise(p1, PAGE_SIZE, MADV_DONTNEED);
1291 lots_o_noops_around_write(&scratch);
1292 ptr_contents = read_ptr(p1);
1293 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
1294
1295 ret = mprotect_pkey(p1, PAGE_SIZE, PROT_EXEC, (u64)pkey);
1296 pkey_assert(!ret);
1297 pkey_access_deny(pkey);
1298
1299 dprintf2("pkru: %x\n", rdpkru());
1300
1301 /*
1302 * Make sure this is an *instruction* fault
1303 */
1304 madvise(p1, PAGE_SIZE, MADV_DONTNEED);
1305 lots_o_noops_around_write(&scratch);
1306 do_not_expect_pk_fault();
1307 ptr_contents = read_ptr(p1);
1308 dprintf2("ptr (%p) contents@%d: %x\n", p1, __LINE__, ptr_contents);
1309 expected_pk_fault(pkey);
1310}
1311
1312void test_mprotect_pkey_on_unsupported_cpu(int *ptr, u16 pkey)
1313{
1314 int size = PAGE_SIZE;
1315 int sret;
1316
1317 if (cpu_has_pku()) {
1318 dprintf1("SKIP: %s: no CPU support\n", __func__);
1319 return;
1320 }
1321
1322 sret = syscall(SYS_mprotect_key, ptr, size, PROT_READ, pkey);
1323 pkey_assert(sret < 0);
1324}
1325
1326void (*pkey_tests[])(int *ptr, u16 pkey) = {
1327 test_read_of_write_disabled_region,
1328 test_read_of_access_disabled_region,
1329 test_write_of_write_disabled_region,
1330 test_write_of_access_disabled_region,
1331 test_kernel_write_of_access_disabled_region,
1332 test_kernel_write_of_write_disabled_region,
1333 test_kernel_gup_of_access_disabled_region,
1334 test_kernel_gup_write_to_write_disabled_region,
1335 test_executing_on_unreadable_memory,
1336 test_ptrace_of_child,
1337 test_pkey_syscalls_on_non_allocated_pkey,
1338 test_pkey_syscalls_bad_args,
1339 test_pkey_alloc_exhaust,
1340};
1341
1342void run_tests_once(void)
1343{
1344 int *ptr;
1345 int prot = PROT_READ|PROT_WRITE;
1346
1347 for (test_nr = 0; test_nr < ARRAY_SIZE(pkey_tests); test_nr++) {
1348 int pkey;
1349 int orig_pkru_faults = pkru_faults;
1350
1351 dprintf1("======================\n");
1352 dprintf1("test %d preparing...\n", test_nr);
1353
1354 tracing_on();
1355 pkey = alloc_random_pkey();
1356 dprintf1("test %d starting with pkey: %d\n", test_nr, pkey);
1357 ptr = malloc_pkey(PAGE_SIZE, prot, pkey);
1358 dprintf1("test %d starting...\n", test_nr);
1359 pkey_tests[test_nr](ptr, pkey);
1360 dprintf1("freeing test memory: %p\n", ptr);
1361 free_pkey_malloc(ptr);
1362 sys_pkey_free(pkey);
1363
1364 dprintf1("pkru_faults: %d\n", pkru_faults);
1365 dprintf1("orig_pkru_faults: %d\n", orig_pkru_faults);
1366
1367 tracing_off();
1368 close_test_fds();
1369
1370 printf("test %2d PASSED (itertation %d)\n", test_nr, iteration_nr);
1371 dprintf1("======================\n\n");
1372 }
1373 iteration_nr++;
1374}
1375
1376void pkey_setup_shadow(void)
1377{
1378 shadow_pkru = __rdpkru();
1379}
1380
1381int main(void)
1382{
1383 int nr_iterations = 22;
1384
1385 setup_handlers();
1386
1387 printf("has pku: %d\n", cpu_has_pku());
1388
1389 if (!cpu_has_pku()) {
1390 int size = PAGE_SIZE;
1391 int *ptr;
1392
1393 printf("running PKEY tests for unsupported CPU/OS\n");
1394
1395 ptr = mmap(NULL, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
1396 assert(ptr != (void *)-1);
1397 test_mprotect_pkey_on_unsupported_cpu(ptr, 1);
1398 exit(0);
1399 }
1400
1401 pkey_setup_shadow();
1402 printf("startup pkru: %x\n", rdpkru());
1403 setup_hugetlbfs();
1404
1405 while (nr_iterations-- > 0)
1406 run_tests_once();
1407
1408 printf("done (all tests OK)\n");
1409 return 0;
1410}
diff --git a/tools/testing/selftests/x86/ptrace_syscall.c b/tools/testing/selftests/x86/ptrace_syscall.c
index 421456784bc6..b037ce9cf116 100644
--- a/tools/testing/selftests/x86/ptrace_syscall.c
+++ b/tools/testing/selftests/x86/ptrace_syscall.c
@@ -147,7 +147,7 @@ static void test_sys32_regs(void (*do_syscall)(struct syscall_args32 *))
147 if (args.nr != getpid() || 147 if (args.nr != getpid() ||
148 args.arg0 != 10 || args.arg1 != 11 || args.arg2 != 12 || 148 args.arg0 != 10 || args.arg1 != 11 || args.arg2 != 12 ||
149 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) { 149 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) {
150 printf("[FAIL]\tgetpid() failed to preseve regs\n"); 150 printf("[FAIL]\tgetpid() failed to preserve regs\n");
151 nerrs++; 151 nerrs++;
152 } else { 152 } else {
153 printf("[OK]\tgetpid() preserves regs\n"); 153 printf("[OK]\tgetpid() preserves regs\n");
@@ -162,7 +162,7 @@ static void test_sys32_regs(void (*do_syscall)(struct syscall_args32 *))
162 if (args.nr != 0 || 162 if (args.nr != 0 ||
163 args.arg0 != getpid() || args.arg1 != SIGUSR1 || args.arg2 != 12 || 163 args.arg0 != getpid() || args.arg1 != SIGUSR1 || args.arg2 != 12 ||
164 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) { 164 args.arg3 != 13 || args.arg4 != 14 || args.arg5 != 15) {
165 printf("[FAIL]\tkill(getpid(), SIGUSR1) failed to preseve regs\n"); 165 printf("[FAIL]\tkill(getpid(), SIGUSR1) failed to preserve regs\n");
166 nerrs++; 166 nerrs++;
167 } else { 167 } else {
168 printf("[OK]\tkill(getpid(), SIGUSR1) preserves regs\n"); 168 printf("[OK]\tkill(getpid(), SIGUSR1) preserves regs\n");
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
index 8a577e7070c6..246145b84a12 100644
--- a/tools/testing/selftests/x86/sigreturn.c
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -106,7 +106,7 @@ asm (".pushsection .text\n\t"
106 ".type int3, @function\n\t" 106 ".type int3, @function\n\t"
107 ".align 4096\n\t" 107 ".align 4096\n\t"
108 "int3:\n\t" 108 "int3:\n\t"
109 "mov %ss,%eax\n\t" 109 "mov %ss,%ecx\n\t"
110 "int3\n\t" 110 "int3\n\t"
111 ".size int3, . - int3\n\t" 111 ".size int3, . - int3\n\t"
112 ".align 4096, 0xcc\n\t" 112 ".align 4096, 0xcc\n\t"
@@ -306,7 +306,7 @@ static volatile sig_atomic_t sig_corrupt_final_ss;
306#ifdef __x86_64__ 306#ifdef __x86_64__
307# define REG_IP REG_RIP 307# define REG_IP REG_RIP
308# define REG_SP REG_RSP 308# define REG_SP REG_RSP
309# define REG_AX REG_RAX 309# define REG_CX REG_RCX
310 310
311struct selectors { 311struct selectors {
312 unsigned short cs, gs, fs, ss; 312 unsigned short cs, gs, fs, ss;
@@ -326,7 +326,7 @@ static unsigned short *csptr(ucontext_t *ctx)
326#else 326#else
327# define REG_IP REG_EIP 327# define REG_IP REG_EIP
328# define REG_SP REG_ESP 328# define REG_SP REG_ESP
329# define REG_AX REG_EAX 329# define REG_CX REG_ECX
330 330
331static greg_t *ssptr(ucontext_t *ctx) 331static greg_t *ssptr(ucontext_t *ctx)
332{ 332{
@@ -457,10 +457,10 @@ static void sigusr1(int sig, siginfo_t *info, void *ctx_void)
457 ctx->uc_mcontext.gregs[REG_IP] = 457 ctx->uc_mcontext.gregs[REG_IP] =
458 sig_cs == code16_sel ? 0 : (unsigned long)&int3; 458 sig_cs == code16_sel ? 0 : (unsigned long)&int3;
459 ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL; 459 ctx->uc_mcontext.gregs[REG_SP] = (unsigned long)0x8badf00d5aadc0deULL;
460 ctx->uc_mcontext.gregs[REG_AX] = 0; 460 ctx->uc_mcontext.gregs[REG_CX] = 0;
461 461
462 memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t)); 462 memcpy(&requested_regs, &ctx->uc_mcontext.gregs, sizeof(gregset_t));
463 requested_regs[REG_AX] = *ssptr(ctx); /* The asm code does this. */ 463 requested_regs[REG_CX] = *ssptr(ctx); /* The asm code does this. */
464 464
465 return; 465 return;
466} 466}
@@ -482,7 +482,7 @@ static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
482 unsigned short ss; 482 unsigned short ss;
483 asm ("mov %%ss,%0" : "=r" (ss)); 483 asm ("mov %%ss,%0" : "=r" (ss));
484 484
485 greg_t asm_ss = ctx->uc_mcontext.gregs[REG_AX]; 485 greg_t asm_ss = ctx->uc_mcontext.gregs[REG_CX];
486 if (asm_ss != sig_ss && sig == SIGTRAP) { 486 if (asm_ss != sig_ss && sig == SIGTRAP) {
487 /* Sanity check failure. */ 487 /* Sanity check failure. */
488 printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n", 488 printf("[FAIL]\tSIGTRAP: ss = %hx, frame ss = %hx, ax = %llx\n",
@@ -654,8 +654,8 @@ static int test_valid_sigreturn(int cs_bits, bool use_16bit_ss, int force_ss)
654#endif 654#endif
655 655
656 /* Sanity check on the kernel */ 656 /* Sanity check on the kernel */
657 if (i == REG_AX && requested_regs[i] != resulting_regs[i]) { 657 if (i == REG_CX && requested_regs[i] != resulting_regs[i]) {
658 printf("[FAIL]\tAX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n", 658 printf("[FAIL]\tCX (saved SP) mismatch: requested 0x%llx; got 0x%llx\n",
659 (unsigned long long)requested_regs[i], 659 (unsigned long long)requested_regs[i],
660 (unsigned long long)resulting_regs[i]); 660 (unsigned long long)resulting_regs[i]);
661 nerrs++; 661 nerrs++;
diff --git a/tools/testing/selftests/x86/test_mremap_vdso.c b/tools/testing/selftests/x86/test_mremap_vdso.c
new file mode 100644
index 000000000000..bf0d687c7db7
--- /dev/null
+++ b/tools/testing/selftests/x86/test_mremap_vdso.c
@@ -0,0 +1,111 @@
1/*
2 * 32-bit test to check vDSO mremap.
3 *
4 * Copyright (c) 2016 Dmitry Safonov
5 * Suggested-by: Andrew Lutomirski
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms and conditions of the GNU General Public License,
9 * version 2, as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
15 */
16/*
17 * Can be built statically:
18 * gcc -Os -Wall -static -m32 test_mremap_vdso.c
19 */
20#define _GNU_SOURCE
21#include <stdio.h>
22#include <errno.h>
23#include <unistd.h>
24#include <string.h>
25
26#include <sys/mman.h>
27#include <sys/auxv.h>
28#include <sys/syscall.h>
29#include <sys/wait.h>
30
31#define PAGE_SIZE 4096
32
33static int try_to_remap(void *vdso_addr, unsigned long size)
34{
35 void *dest_addr, *new_addr;
36
37 /* Searching for memory location where to remap */
38 dest_addr = mmap(0, size, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
39 if (dest_addr == MAP_FAILED) {
40 printf("[WARN]\tmmap failed (%d): %m\n", errno);
41 return 0;
42 }
43
44 printf("[NOTE]\tMoving vDSO: [%p, %#lx] -> [%p, %#lx]\n",
45 vdso_addr, (unsigned long)vdso_addr + size,
46 dest_addr, (unsigned long)dest_addr + size);
47 fflush(stdout);
48
49 new_addr = mremap(vdso_addr, size, size,
50 MREMAP_FIXED|MREMAP_MAYMOVE, dest_addr);
51 if ((unsigned long)new_addr == (unsigned long)-1) {
52 munmap(dest_addr, size);
53 if (errno == EINVAL) {
54 printf("[NOTE]\tvDSO partial move failed, will try with bigger size\n");
55 return -1; /* Retry with larger */
56 }
57 printf("[FAIL]\tmremap failed (%d): %m\n", errno);
58 return 1;
59 }
60
61 return 0;
62
63}
64
65int main(int argc, char **argv, char **envp)
66{
67 pid_t child;
68
69 child = fork();
70 if (child == -1) {
71 printf("[WARN]\tfailed to fork (%d): %m\n", errno);
72 return 1;
73 }
74
75 if (child == 0) {
76 unsigned long vdso_size = PAGE_SIZE;
77 unsigned long auxval;
78 int ret = -1;
79
80 auxval = getauxval(AT_SYSINFO_EHDR);
81 printf("\tAT_SYSINFO_EHDR is %#lx\n", auxval);
82 if (!auxval || auxval == -ENOENT) {
83 printf("[WARN]\tgetauxval failed\n");
84 return 0;
85 }
86
87 /* Simpler than parsing ELF header */
88 while (ret < 0) {
89 ret = try_to_remap((void *)auxval, vdso_size);
90 vdso_size += PAGE_SIZE;
91 }
92
93 /* Glibc is likely to explode now - exit with raw syscall */
94 asm volatile ("int $0x80" : : "a" (__NR_exit), "b" (!!ret));
95 } else {
96 int status;
97
98 if (waitpid(child, &status, 0) != child ||
99 !WIFEXITED(status)) {
100 printf("[FAIL]\tmremap() of the vDSO does not work on this kernel!\n");
101 return 1;
102 } else if (WEXITSTATUS(status) != 0) {
103 printf("[FAIL]\tChild failed with %d\n",
104 WEXITSTATUS(status));
105 return 1;
106 }
107 printf("[OK]\n");
108 }
109
110 return 0;
111}
diff --git a/tools/testing/selftests/zram/README b/tools/testing/selftests/zram/README
index eb17917c8a3a..7972cc512408 100644
--- a/tools/testing/selftests/zram/README
+++ b/tools/testing/selftests/zram/README
@@ -13,7 +13,7 @@ Statistics for individual zram devices are exported through sysfs nodes at
13 13
14Kconfig required: 14Kconfig required:
15CONFIG_ZRAM=y 15CONFIG_ZRAM=y
16CONFIG_ZRAM_LZ4_COMPRESS=y 16CONFIG_CRYPTO_LZ4=y
17CONFIG_ZPOOL=y 17CONFIG_ZPOOL=y
18CONFIG_ZSMALLOC=y 18CONFIG_ZSMALLOC=y
19 19
diff --git a/tools/virtio/linux/dma-mapping.h b/tools/virtio/linux/dma-mapping.h
index 4f93af89ae16..18601f6689b9 100644
--- a/tools/virtio/linux/dma-mapping.h
+++ b/tools/virtio/linux/dma-mapping.h
@@ -14,4 +14,20 @@ enum dma_data_direction {
14 DMA_NONE = 3, 14 DMA_NONE = 3,
15}; 15};
16 16
17#define dma_alloc_coherent(d, s, hp, f) ({ \
18 void *__dma_alloc_coherent_p = kmalloc((s), (f)); \
19 *(hp) = (unsigned long)__dma_alloc_coherent_p; \
20 __dma_alloc_coherent_p; \
21})
22
23#define dma_free_coherent(d, s, p, h) kfree(p)
24
25#define dma_map_page(d, p, o, s, dir) (page_to_phys(p) + (o))
26
27#define dma_map_single(d, p, s, dir) (virt_to_phys(p))
28#define dma_mapping_error(...) (0)
29
30#define dma_unmap_single(...) do { } while (0)
31#define dma_unmap_page(...) do { } while (0)
32
17#endif 33#endif
diff --git a/tools/virtio/linux/kernel.h b/tools/virtio/linux/kernel.h
index 033849948215..d9554fc3f340 100644
--- a/tools/virtio/linux/kernel.h
+++ b/tools/virtio/linux/kernel.h
@@ -20,7 +20,9 @@
20 20
21#define PAGE_SIZE getpagesize() 21#define PAGE_SIZE getpagesize()
22#define PAGE_MASK (~(PAGE_SIZE-1)) 22#define PAGE_MASK (~(PAGE_SIZE-1))
23#define PAGE_ALIGN(x) ((x + PAGE_SIZE - 1) & PAGE_MASK)
23 24
25typedef unsigned long long phys_addr_t;
24typedef unsigned long long dma_addr_t; 26typedef unsigned long long dma_addr_t;
25typedef size_t __kernel_size_t; 27typedef size_t __kernel_size_t;
26typedef unsigned int __wsum; 28typedef unsigned int __wsum;
@@ -57,6 +59,11 @@ static inline void *kzalloc(size_t s, gfp_t gfp)
57 return p; 59 return p;
58} 60}
59 61
62static inline void *alloc_pages_exact(size_t s, gfp_t gfp)
63{
64 return kmalloc(s, gfp);
65}
66
60static inline void kfree(void *p) 67static inline void kfree(void *p)
61{ 68{
62 if (p >= __kfree_ignore_start && p < __kfree_ignore_end) 69 if (p >= __kfree_ignore_start && p < __kfree_ignore_end)
@@ -64,6 +71,11 @@ static inline void kfree(void *p)
64 free(p); 71 free(p);
65} 72}
66 73
74static inline void free_pages_exact(void *p, size_t s)
75{
76 kfree(p);
77}
78
67static inline void *krealloc(void *p, size_t s, gfp_t gfp) 79static inline void *krealloc(void *p, size_t s, gfp_t gfp)
68{ 80{
69 return realloc(p, s); 81 return realloc(p, s);
@@ -105,6 +117,8 @@ static inline void free_page(unsigned long addr)
105#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) 117#define dev_err(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
106#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__) 118#define dev_warn(dev, format, ...) fprintf (stderr, format, ## __VA_ARGS__)
107 119
120#define WARN_ON_ONCE(cond) ((cond) && fprintf (stderr, "WARNING\n"))
121
108#define min(x, y) ({ \ 122#define min(x, y) ({ \
109 typeof(x) _min1 = (x); \ 123 typeof(x) _min1 = (x); \
110 typeof(y) _min2 = (y); \ 124 typeof(y) _min2 = (y); \
diff --git a/tools/virtio/linux/slab.h b/tools/virtio/linux/slab.h
index 81baeac8ae40..7e1c1197d439 100644
--- a/tools/virtio/linux/slab.h
+++ b/tools/virtio/linux/slab.h
@@ -1,2 +1,6 @@
1#ifndef LINUX_SLAB_H 1#ifndef LINUX_SLAB_H
2#define GFP_KERNEL 0
3#define GFP_ATOMIC 0
4#define __GFP_NOWARN 0
5#define __GFP_ZERO 0
2#endif 6#endif
diff --git a/tools/virtio/linux/virtio.h b/tools/virtio/linux/virtio.h
index ee125e714053..9377c8b4ac16 100644
--- a/tools/virtio/linux/virtio.h
+++ b/tools/virtio/linux/virtio.h
@@ -3,8 +3,12 @@
3#include <linux/scatterlist.h> 3#include <linux/scatterlist.h>
4#include <linux/kernel.h> 4#include <linux/kernel.h>
5 5
6struct device {
7 void *parent;
8};
9
6struct virtio_device { 10struct virtio_device {
7 void *dev; 11 struct device dev;
8 u64 features; 12 u64 features;
9}; 13};
10 14
diff --git a/tools/virtio/linux/virtio_config.h b/tools/virtio/linux/virtio_config.h
index 57a6964a1e35..9ba11815e0a1 100644
--- a/tools/virtio/linux/virtio_config.h
+++ b/tools/virtio/linux/virtio_config.h
@@ -40,6 +40,19 @@ static inline void __virtio_clear_bit(struct virtio_device *vdev,
40#define virtio_has_feature(dev, feature) \ 40#define virtio_has_feature(dev, feature) \
41 (__virtio_test_bit((dev), feature)) 41 (__virtio_test_bit((dev), feature))
42 42
43/**
44 * virtio_has_iommu_quirk - determine whether this device has the iommu quirk
45 * @vdev: the device
46 */
47static inline bool virtio_has_iommu_quirk(const struct virtio_device *vdev)
48{
49 /*
50 * Note the reverse polarity of the quirk feature (compared to most
51 * other features), this is for compatibility with legacy systems.
52 */
53 return !virtio_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
54}
55
43static inline bool virtio_is_little_endian(struct virtio_device *vdev) 56static inline bool virtio_is_little_endian(struct virtio_device *vdev)
44{ 57{
45 return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) || 58 return virtio_has_feature(vdev, VIRTIO_F_VERSION_1) ||
diff --git a/tools/virtio/ringtest/Makefile b/tools/virtio/ringtest/Makefile
index 6ba745529833..877a8a4721b6 100644
--- a/tools/virtio/ringtest/Makefile
+++ b/tools/virtio/ringtest/Makefile
@@ -1,6 +1,6 @@
1all: 1all:
2 2
3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder 3all: ring virtio_ring_0_9 virtio_ring_poll virtio_ring_inorder ptr_ring noring
4 4
5CFLAGS += -Wall 5CFLAGS += -Wall
6CFLAGS += -pthread -O2 -ggdb 6CFLAGS += -pthread -O2 -ggdb
@@ -8,6 +8,7 @@ LDFLAGS += -pthread -O2 -ggdb
8 8
9main.o: main.c main.h 9main.o: main.c main.h
10ring.o: ring.c main.h 10ring.o: ring.c main.h
11ptr_ring.o: ptr_ring.c main.h ../../../include/linux/ptr_ring.h
11virtio_ring_0_9.o: virtio_ring_0_9.c main.h 12virtio_ring_0_9.o: virtio_ring_0_9.c main.h
12virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h 13virtio_ring_poll.o: virtio_ring_poll.c virtio_ring_0_9.c main.h
13virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h 14virtio_ring_inorder.o: virtio_ring_inorder.c virtio_ring_0_9.c main.h
@@ -15,11 +16,15 @@ ring: ring.o main.o
15virtio_ring_0_9: virtio_ring_0_9.o main.o 16virtio_ring_0_9: virtio_ring_0_9.o main.o
16virtio_ring_poll: virtio_ring_poll.o main.o 17virtio_ring_poll: virtio_ring_poll.o main.o
17virtio_ring_inorder: virtio_ring_inorder.o main.o 18virtio_ring_inorder: virtio_ring_inorder.o main.o
19ptr_ring: ptr_ring.o main.o
20noring: noring.o main.o
18clean: 21clean:
19 -rm main.o 22 -rm main.o
20 -rm ring.o ring 23 -rm ring.o ring
21 -rm virtio_ring_0_9.o virtio_ring_0_9 24 -rm virtio_ring_0_9.o virtio_ring_0_9
22 -rm virtio_ring_poll.o virtio_ring_poll 25 -rm virtio_ring_poll.o virtio_ring_poll
23 -rm virtio_ring_inorder.o virtio_ring_inorder 26 -rm virtio_ring_inorder.o virtio_ring_inorder
27 -rm ptr_ring.o ptr_ring
28 -rm noring.o noring
24 29
25.PHONY: all clean 30.PHONY: all clean
diff --git a/tools/virtio/ringtest/README b/tools/virtio/ringtest/README
index 34e94c46104f..d83707a336c9 100644
--- a/tools/virtio/ringtest/README
+++ b/tools/virtio/ringtest/README
@@ -1,2 +1,6 @@
1Partial implementation of various ring layouts, useful to tune virtio design. 1Partial implementation of various ring layouts, useful to tune virtio design.
2Uses shared memory heavily. 2Uses shared memory heavily.
3
4Typical use:
5
6# sh run-on-all.sh perf stat -r 10 --log-fd 1 -- ./ring
diff --git a/tools/virtio/ringtest/noring.c b/tools/virtio/ringtest/noring.c
new file mode 100644
index 000000000000..eda2f4824130
--- /dev/null
+++ b/tools/virtio/ringtest/noring.c
@@ -0,0 +1,69 @@
1#define _GNU_SOURCE
2#include "main.h"
3#include <assert.h>
4
5/* stub implementation: useful for measuring overhead */
6void alloc_ring(void)
7{
8}
9
10/* guest side */
11int add_inbuf(unsigned len, void *buf, void *datap)
12{
13 return 0;
14}
15
16/*
17 * skb_array API provides no way for producer to find out whether a given
18 * buffer was consumed. Our tests merely require that a successful get_buf
19 * implies that add_inbuf succeed in the past, and that add_inbuf will succeed,
20 * fake it accordingly.
21 */
22void *get_buf(unsigned *lenp, void **bufp)
23{
24 return "Buffer";
25}
26
27void poll_used(void)
28{
29}
30
31void disable_call()
32{
33 assert(0);
34}
35
36bool enable_call()
37{
38 assert(0);
39}
40
41void kick_available(void)
42{
43 assert(0);
44}
45
46/* host side */
47void disable_kick()
48{
49 assert(0);
50}
51
52bool enable_kick()
53{
54 assert(0);
55}
56
57void poll_avail(void)
58{
59}
60
61bool use_buf(unsigned *lenp, void **bufp)
62{
63 return true;
64}
65
66void call_used(void)
67{
68 assert(0);
69}
diff --git a/tools/virtio/ringtest/ptr_ring.c b/tools/virtio/ringtest/ptr_ring.c
new file mode 100644
index 000000000000..bd2ad1d3b7a9
--- /dev/null
+++ b/tools/virtio/ringtest/ptr_ring.c
@@ -0,0 +1,198 @@
1#define _GNU_SOURCE
2#include "main.h"
3#include <stdlib.h>
4#include <stdio.h>
5#include <string.h>
6#include <pthread.h>
7#include <malloc.h>
8#include <assert.h>
9#include <errno.h>
10#include <limits.h>
11
12#define SMP_CACHE_BYTES 64
13#define cache_line_size() SMP_CACHE_BYTES
14#define ____cacheline_aligned_in_smp __attribute__ ((aligned (SMP_CACHE_BYTES)))
15#define unlikely(x) (__builtin_expect(!!(x), 0))
16#define likely(x) (__builtin_expect(!!(x), 1))
17#define ALIGN(x, a) (((x) + (a) - 1) / (a) * (a))
18typedef pthread_spinlock_t spinlock_t;
19
20typedef int gfp_t;
21static void *kmalloc(unsigned size, gfp_t gfp)
22{
23 return memalign(64, size);
24}
25
26static void *kzalloc(unsigned size, gfp_t gfp)
27{
28 void *p = memalign(64, size);
29 if (!p)
30 return p;
31 memset(p, 0, size);
32
33 return p;
34}
35
36static void kfree(void *p)
37{
38 if (p)
39 free(p);
40}
41
42static void spin_lock_init(spinlock_t *lock)
43{
44 int r = pthread_spin_init(lock, 0);
45 assert(!r);
46}
47
48static void spin_lock(spinlock_t *lock)
49{
50 int ret = pthread_spin_lock(lock);
51 assert(!ret);
52}
53
54static void spin_unlock(spinlock_t *lock)
55{
56 int ret = pthread_spin_unlock(lock);
57 assert(!ret);
58}
59
60static void spin_lock_bh(spinlock_t *lock)
61{
62 spin_lock(lock);
63}
64
65static void spin_unlock_bh(spinlock_t *lock)
66{
67 spin_unlock(lock);
68}
69
70static void spin_lock_irq(spinlock_t *lock)
71{
72 spin_lock(lock);
73}
74
75static void spin_unlock_irq(spinlock_t *lock)
76{
77 spin_unlock(lock);
78}
79
80static void spin_lock_irqsave(spinlock_t *lock, unsigned long f)
81{
82 spin_lock(lock);
83}
84
85static void spin_unlock_irqrestore(spinlock_t *lock, unsigned long f)
86{
87 spin_unlock(lock);
88}
89
90#include "../../../include/linux/ptr_ring.h"
91
92static unsigned long long headcnt, tailcnt;
93static struct ptr_ring array ____cacheline_aligned_in_smp;
94
95/* implemented by ring */
96void alloc_ring(void)
97{
98 int ret = ptr_ring_init(&array, ring_size, 0);
99 assert(!ret);
100}
101
102/* guest side */
103int add_inbuf(unsigned len, void *buf, void *datap)
104{
105 int ret;
106
107 ret = __ptr_ring_produce(&array, buf);
108 if (ret >= 0) {
109 ret = 0;
110 headcnt++;
111 }
112
113 return ret;
114}
115
116/*
117 * ptr_ring API provides no way for producer to find out whether a given
118 * buffer was consumed. Our tests merely require that a successful get_buf
119 * implies that add_inbuf succeed in the past, and that add_inbuf will succeed,
120 * fake it accordingly.
121 */
122void *get_buf(unsigned *lenp, void **bufp)
123{
124 void *datap;
125
126 if (tailcnt == headcnt || __ptr_ring_full(&array))
127 datap = NULL;
128 else {
129 datap = "Buffer\n";
130 ++tailcnt;
131 }
132
133 return datap;
134}
135
136void poll_used(void)
137{
138 void *b;
139
140 do {
141 if (tailcnt == headcnt || __ptr_ring_full(&array)) {
142 b = NULL;
143 barrier();
144 } else {
145 b = "Buffer\n";
146 }
147 } while (!b);
148}
149
150void disable_call()
151{
152 assert(0);
153}
154
155bool enable_call()
156{
157 assert(0);
158}
159
160void kick_available(void)
161{
162 assert(0);
163}
164
165/* host side */
166void disable_kick()
167{
168 assert(0);
169}
170
171bool enable_kick()
172{
173 assert(0);
174}
175
176void poll_avail(void)
177{
178 void *b;
179
180 do {
181 barrier();
182 b = __ptr_ring_peek(&array);
183 } while (!b);
184}
185
186bool use_buf(unsigned *lenp, void **bufp)
187{
188 void *ptr;
189
190 ptr = __ptr_ring_consume(&array);
191
192 return ptr;
193}
194
195void call_used(void)
196{
197 assert(0);
198}
diff --git a/tools/virtio/ringtest/run-on-all.sh b/tools/virtio/ringtest/run-on-all.sh
index 52b0f71ffa8d..2e69ca812b4c 100755
--- a/tools/virtio/ringtest/run-on-all.sh
+++ b/tools/virtio/ringtest/run-on-all.sh
@@ -3,10 +3,10 @@
3#use last CPU for host. Why not the first? 3#use last CPU for host. Why not the first?
4#many devices tend to use cpu0 by default so 4#many devices tend to use cpu0 by default so
5#it tends to be busier 5#it tends to be busier
6HOST_AFFINITY=$(cd /dev/cpu; ls|grep -v '[a-z]'|sort -n|tail -1) 6HOST_AFFINITY=$(lscpu -p=cpu | tail -1)
7 7
8#run command on all cpus 8#run command on all cpus
9for cpu in $(cd /dev/cpu; ls|grep -v '[a-z]'|sort -n); 9for cpu in $(seq 0 $HOST_AFFINITY)
10do 10do
11 #Don't run guest and host on same CPU 11 #Don't run guest and host on same CPU
12 #It actually works ok if using signalling 12 #It actually works ok if using signalling
diff --git a/tools/vm/page_owner_sort.c b/tools/vm/page_owner_sort.c
index 77147b42d598..f1c055f3c243 100644
--- a/tools/vm/page_owner_sort.c
+++ b/tools/vm/page_owner_sort.c
@@ -79,12 +79,12 @@ static void add_list(char *buf, int len)
79 } 79 }
80} 80}
81 81
82#define BUF_SIZE 1024 82#define BUF_SIZE (128 * 1024)
83 83
84int main(int argc, char **argv) 84int main(int argc, char **argv)
85{ 85{
86 FILE *fin, *fout; 86 FILE *fin, *fout;
87 char buf[BUF_SIZE]; 87 char *buf;
88 int ret, i, count; 88 int ret, i, count;
89 struct block_list *list2; 89 struct block_list *list2;
90 struct stat st; 90 struct stat st;
@@ -107,6 +107,11 @@ int main(int argc, char **argv)
107 max_size = st.st_size / 100; /* hack ... */ 107 max_size = st.st_size / 100; /* hack ... */
108 108
109 list = malloc(max_size * sizeof(*list)); 109 list = malloc(max_size * sizeof(*list));
110 buf = malloc(BUF_SIZE);
111 if (!list || !buf) {
112 printf("Out of memory\n");
113 exit(1);
114 }
110 115
111 for ( ; ; ) { 116 for ( ; ; ) {
112 ret = read_block(buf, BUF_SIZE, fin); 117 ret = read_block(buf, BUF_SIZE, fin);
diff --git a/tools/vm/slabinfo.c b/tools/vm/slabinfo.c
index 1889163f2f05..b9d34b37c017 100644
--- a/tools/vm/slabinfo.c
+++ b/tools/vm/slabinfo.c
@@ -492,7 +492,7 @@ static void slab_stats(struct slabinfo *s)
492 s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass; 492 s->deactivate_to_head + s->deactivate_to_tail + s->deactivate_bypass;
493 493
494 if (total) { 494 if (total) {
495 printf("\nSlab Deactivation Ocurrences %%\n"); 495 printf("\nSlab Deactivation Occurrences %%\n");
496 printf("-------------------------------------------------\n"); 496 printf("-------------------------------------------------\n");
497 printf("Slab full %7lu %3lu%%\n", 497 printf("Slab full %7lu %3lu%%\n",
498 s->deactivate_full, (s->deactivate_full * 100) / total); 498 s->deactivate_full, (s->deactivate_full * 100) / total);
@@ -510,10 +510,11 @@ static void slab_stats(struct slabinfo *s)
510 s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total); 510 s->alloc_node_mismatch, (s->alloc_node_mismatch * 100) / total);
511 } 511 }
512 512
513 if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) 513 if (s->cmpxchg_double_fail || s->cmpxchg_double_cpu_fail) {
514 printf("\nCmpxchg_double Looping\n------------------------\n"); 514 printf("\nCmpxchg_double Looping\n------------------------\n");
515 printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n", 515 printf("Locked Cmpxchg Double redos %lu\nUnlocked Cmpxchg Double redos %lu\n",
516 s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail); 516 s->cmpxchg_double_fail, s->cmpxchg_double_cpu_fail);
517 }
517} 518}
518 519
519static void report(struct slabinfo *s) 520static void report(struct slabinfo *s)